aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml2
-rw-r--r--Makefile.am13
-rw-r--r--build-aux/m4/bitcoin_find_bdb48.m42
-rw-r--r--configure.ac7
-rw-r--r--contrib/debian/manpages/bitcoind.124
-rwxr-xr-xcontrib/devtools/optimize-pngs.py73
-rw-r--r--contrib/gitian-descriptors/gitian-osx.yml4
-rw-r--r--contrib/gitian-downloader/jonasschnelli-key.pgpbin0 -> 2230 bytes
-rw-r--r--contrib/macdeploy/DS_Storebin15364 -> 10244 bytes
-rw-r--r--contrib/macdeploy/background.pngbin12073 -> 48690 bytes
-rw-r--r--contrib/macdeploy/background.psdbin163518 -> 982442 bytes
-rw-r--r--contrib/macdeploy/background.tiffbin0 -> 202136 bytes
-rw-r--r--contrib/macdeploy/background@2x.pngbin0 -> 138890 bytes
-rw-r--r--contrib/macdeploy/fancy.plist2
-rwxr-xr-xcontrib/macdeploy/macdeployqtplus9
-rw-r--r--depends/README2
-rwxr-xr-xdepends/config.guess15
-rwxr-xr-xdepends/config.sub25
-rw-r--r--depends/funcs.mk2
-rw-r--r--depends/hosts/darwin.mk4
-rw-r--r--depends/packages/openssl.mk6
-rw-r--r--doc/README.md2
-rw-r--r--doc/README_osx.txt9
-rw-r--r--doc/bootstrap.md56
-rw-r--r--doc/build-osx.md16
-rw-r--r--doc/build-unix.md4
-rw-r--r--doc/gitian-building.md34
-rw-r--r--doc/release-process.md6
-rw-r--r--pkg.m4214
-rw-r--r--qa/rpc-tests/README.md2
-rwxr-xr-xqa/rpc-tests/bipdersig.py90
-rwxr-xr-xqa/rpc-tests/getblocktemplate_proposals.py1
-rwxr-xr-xqa/rpc-tests/httpbasics.py36
-rwxr-xr-xqa/rpc-tests/test_framework.py5
-rwxr-xr-xqa/rpc-tests/wallet.py2
-rw-r--r--src/Makefile.am54
-rw-r--r--src/Makefile.qt.include3
-rw-r--r--src/Makefile.test.include2
-rw-r--r--src/alert.cpp2
-rw-r--r--src/bitcoin-tx.cpp2
-rw-r--r--src/chainparams.cpp20
-rw-r--r--src/checkqueue.h14
-rw-r--r--src/crypter.cpp39
-rw-r--r--src/crypter.h3
-rw-r--r--src/crypto/rfc6979_hmac_sha256.cpp47
-rw-r--r--src/crypto/rfc6979_hmac_sha256.h36
-rw-r--r--src/db.cpp46
-rw-r--r--src/db.h3
-rw-r--r--src/ecwrapper.cpp30
-rw-r--r--src/init.cpp61
-rw-r--r--src/key.cpp45
-rw-r--r--src/keystore.cpp4
-rw-r--r--src/keystore.h5
-rw-r--r--src/main.cpp240
-rw-r--r--src/main.h14
-rw-r--r--src/miner.cpp49
-rw-r--r--src/miner.h14
-rw-r--r--src/net.cpp70
-rw-r--r--src/net.h1
-rw-r--r--src/pow.cpp4
-rw-r--r--src/primitives/block.h2
-rw-r--r--src/primitives/transaction.cpp2
-rw-r--r--src/protocol.cpp6
-rw-r--r--src/qt/addresstablemodel.cpp6
-rw-r--r--src/qt/bitcoin.cpp27
-rw-r--r--src/qt/bitcoin.qrc3
-rw-r--r--src/qt/bitcoinamountfield.cpp40
-rw-r--r--src/qt/bitcoingui.cpp23
-rw-r--r--src/qt/bitcoingui.h2
-rw-r--r--src/qt/clientmodel.cpp4
-rw-r--r--src/qt/coincontroldialog.cpp20
-rw-r--r--src/qt/coincontroldialog.h2
-rw-r--r--src/qt/coincontroltreewidget.cpp5
-rw-r--r--src/qt/forms/helpmessagedialog.ui104
-rw-r--r--src/qt/forms/signverifymessagedialog.ui4
-rw-r--r--src/qt/guiutil.cpp38
-rw-r--r--src/qt/guiutil.h2
-rw-r--r--src/qt/paymentrequestplus.cpp32
-rw-r--r--src/qt/paymentserver.cpp85
-rw-r--r--src/qt/paymentserver.h5
-rw-r--r--src/qt/res/icons/about.pngbin5925 -> 4726 bytes
-rw-r--r--src/qt/res/icons/about_qt.pngbin3107 -> 2338 bytes
-rw-r--r--src/qt/res/icons/add.pngbin15199 -> 784 bytes
-rw-r--r--src/qt/res/icons/address-book.pngbin16150 -> 1275 bytes
-rw-r--r--src/qt/res/icons/bitcoin.pngbin350390 -> 312944 bytes
-rw-r--r--src/qt/res/icons/clock1.pngbin2448 -> 1921 bytes
-rw-r--r--src/qt/res/icons/clock2.pngbin2269 -> 1731 bytes
-rw-r--r--src/qt/res/icons/clock3.pngbin2184 -> 1557 bytes
-rw-r--r--src/qt/res/icons/clock4.pngbin1995 -> 1395 bytes
-rw-r--r--src/qt/res/icons/clock5.pngbin2682 -> 1889 bytes
-rw-r--r--src/qt/res/icons/configure.pngbin3891 -> 2865 bytes
-rw-r--r--src/qt/res/icons/connect0.pngbin16890 -> 2290 bytes
-rw-r--r--src/qt/res/icons/connect1.pngbin16870 -> 2242 bytes
-rw-r--r--src/qt/res/icons/connect2.pngbin16566 -> 1966 bytes
-rw-r--r--src/qt/res/icons/connect3.pngbin16566 -> 1966 bytes
-rw-r--r--src/qt/res/icons/connect4.pngbin16117 -> 1490 bytes
-rw-r--r--src/qt/res/icons/debugwindow.pngbin15930 -> 1327 bytes
-rw-r--r--src/qt/res/icons/edit.pngbin2544 -> 1847 bytes
-rw-r--r--src/qt/res/icons/editcopy.pngbin1295 -> 883 bytes
-rw-r--r--src/qt/res/icons/editpaste.pngbin15778 -> 1024 bytes
-rw-r--r--src/qt/res/icons/export.pngbin17005 -> 1750 bytes
-rw-r--r--src/qt/res/icons/eye.pngbin2806 -> 2241 bytes
-rw-r--r--src/qt/res/icons/eye_minus.pngbin3087 -> 2438 bytes
-rw-r--r--src/qt/res/icons/eye_plus.pngbin3368 -> 2599 bytes
-rw-r--r--src/qt/res/icons/filesave.pngbin2874 -> 2359 bytes
-rw-r--r--src/qt/res/icons/history.pngbin16271 -> 762 bytes
-rw-r--r--src/qt/res/icons/info.pngbin2895 -> 2028 bytes
-rw-r--r--src/qt/res/icons/key.pngbin2434 -> 1759 bytes
-rw-r--r--src/qt/res/icons/lock_closed.pngbin1686 -> 1197 bytes
-rw-r--r--src/qt/res/icons/lock_open.pngbin1751 -> 1257 bytes
-rw-r--r--src/qt/res/icons/open.pngbin2239 -> 1694 bytes
-rw-r--r--src/qt/res/icons/overview.pngbin2215 -> 1662 bytes
-rw-r--r--src/qt/res/icons/quit.pngbin15766 -> 1091 bytes
-rw-r--r--src/qt/res/icons/receive.pngbin2874 -> 2067 bytes
-rw-r--r--src/qt/res/icons/remove.pngbin16663 -> 1723 bytes
-rw-r--r--src/qt/res/icons/send.pngbin17005 -> 1750 bytes
-rw-r--r--src/qt/res/icons/synced.pngbin16891 -> 1619 bytes
-rw-r--r--src/qt/res/icons/transaction0.pngbin1759 -> 1220 bytes
-rw-r--r--src/qt/res/icons/transaction2.pngbin16891 -> 1619 bytes
-rw-r--r--src/qt/res/icons/transaction_conflicted.pngbin15766 -> 1091 bytes
-rw-r--r--src/qt/res/icons/tx_inout.pngbin2568 -> 1655 bytes
-rw-r--r--src/qt/res/icons/tx_input.pngbin2590 -> 1783 bytes
-rw-r--r--src/qt/res/icons/tx_mined.pngbin2166 -> 1578 bytes
-rw-r--r--src/qt/res/icons/tx_output.pngbin2699 -> 1771 bytes
-rw-r--r--src/qt/res/icons/verify.pngbin2984 -> 2034 bytes
-rw-r--r--src/qt/res/images/about.pngbin1136 -> 0 bytes
-rw-r--r--src/qt/res/movies/spinner-000.pngbin16636 -> 1835 bytes
-rw-r--r--src/qt/res/movies/spinner-001.pngbin2785 -> 2376 bytes
-rw-r--r--src/qt/res/movies/spinner-002.pngbin2814 -> 2376 bytes
-rw-r--r--src/qt/res/movies/spinner-003.pngbin2775 -> 2355 bytes
-rw-r--r--src/qt/res/movies/spinner-004.pngbin2850 -> 2349 bytes
-rw-r--r--src/qt/res/movies/spinner-005.pngbin2728 -> 2305 bytes
-rw-r--r--src/qt/res/movies/spinner-006.pngbin2734 -> 2304 bytes
-rw-r--r--src/qt/res/movies/spinner-007.pngbin2633 -> 2283 bytes
-rw-r--r--src/qt/res/movies/spinner-008.pngbin2611 -> 2312 bytes
-rw-r--r--src/qt/res/movies/spinner-009.pngbin2074 -> 1810 bytes
-rw-r--r--src/qt/res/movies/spinner-010.pngbin2666 -> 2305 bytes
-rw-r--r--src/qt/res/movies/spinner-011.pngbin2751 -> 2338 bytes
-rw-r--r--src/qt/res/movies/spinner-012.pngbin2828 -> 2352 bytes
-rw-r--r--src/qt/res/movies/spinner-013.pngbin2896 -> 2377 bytes
-rw-r--r--src/qt/res/movies/spinner-014.pngbin2867 -> 2358 bytes
-rw-r--r--src/qt/res/movies/spinner-015.pngbin2860 -> 2405 bytes
-rw-r--r--src/qt/res/movies/spinner-016.pngbin2825 -> 2429 bytes
-rw-r--r--src/qt/res/movies/spinner-017.pngbin2833 -> 2408 bytes
-rw-r--r--src/qt/res/movies/spinner-018.pngbin2147 -> 1831 bytes
-rw-r--r--src/qt/res/movies/spinner-019.pngbin2808 -> 2380 bytes
-rw-r--r--src/qt/res/movies/spinner-020.pngbin2800 -> 2366 bytes
-rw-r--r--src/qt/res/movies/spinner-021.pngbin2833 -> 2368 bytes
-rw-r--r--src/qt/res/movies/spinner-022.pngbin2823 -> 2356 bytes
-rw-r--r--src/qt/res/movies/spinner-023.pngbin2710 -> 2311 bytes
-rw-r--r--src/qt/res/movies/spinner-024.pngbin2732 -> 2315 bytes
-rw-r--r--src/qt/res/movies/spinner-025.pngbin2635 -> 2298 bytes
-rw-r--r--src/qt/res/movies/spinner-026.pngbin2643 -> 2291 bytes
-rw-r--r--src/qt/res/movies/spinner-027.pngbin2099 -> 1816 bytes
-rw-r--r--src/qt/res/movies/spinner-028.pngbin2665 -> 2308 bytes
-rw-r--r--src/qt/res/movies/spinner-029.pngbin2761 -> 2356 bytes
-rw-r--r--src/qt/res/movies/spinner-030.pngbin2832 -> 2346 bytes
-rw-r--r--src/qt/res/movies/spinner-031.pngbin2871 -> 2380 bytes
-rw-r--r--src/qt/res/movies/spinner-032.pngbin2839 -> 2345 bytes
-rw-r--r--src/qt/res/movies/spinner-033.pngbin2829 -> 2401 bytes
-rw-r--r--src/qt/res/movies/spinner-034.pngbin2851 -> 2422 bytes
-rw-r--r--src/qt/res/movies/spinner-035.pngbin2837 -> 2406 bytes
-rw-r--r--src/qt/sendcoinsdialog.cpp16
-rw-r--r--src/qt/splashscreen.cpp2
-rw-r--r--src/qt/test/paymentrequestdata.h148
-rw-r--r--src/qt/test/paymentservertests.cpp90
-rw-r--r--src/qt/transactiontablemodel.cpp10
-rw-r--r--src/qt/transactionview.h4
-rw-r--r--src/qt/utilitydialog.cpp12
-rw-r--r--src/qt/walletmodel.cpp14
-rw-r--r--src/qt/walletmodel.h5
-rw-r--r--src/rpcblockchain.cpp19
-rw-r--r--src/rpcdump.cpp10
-rw-r--r--src/rpcmining.cpp41
-rw-r--r--src/rpcmisc.cpp18
-rw-r--r--src/rpcnet.cpp10
-rw-r--r--src/rpcrawtransaction.cpp18
-rw-r--r--src/rpcserver.cpp245
-rw-r--r--src/rpcserver.h12
-rw-r--r--src/rpcwallet.cpp146
-rw-r--r--src/script/bitcoinconsensus.cpp2
-rw-r--r--src/script/bitcoinconsensus.h1
-rw-r--r--src/script/interpreter.cpp139
-rw-r--r--src/script/interpreter.h16
-rw-r--r--src/script/script.h2
-rw-r--r--src/script/sigcache.cpp4
-rw-r--r--src/script/sigcache.h4
-rw-r--r--src/script/sign.cpp4
-rw-r--r--src/script/standard.h3
-rw-r--r--src/secp256k1/.gitignore1
-rw-r--r--src/secp256k1/.travis.yml14
-rw-r--r--src/secp256k1/Makefile.am4
-rw-r--r--src/secp256k1/build-aux/m4/bitcoin_secp.m420
-rw-r--r--src/secp256k1/configure.ac113
-rw-r--r--src/secp256k1/include/secp256k1.h51
-rw-r--r--src/secp256k1/src/bench_sign.c5
-rw-r--r--src/secp256k1/src/bench_verify.c4
-rw-r--r--src/secp256k1/src/ecdsa_impl.h59
-rw-r--r--src/secp256k1/src/ecmult_gen_impl.h2
-rw-r--r--src/secp256k1/src/ecmult_impl.h4
-rw-r--r--src/secp256k1/src/field.h19
-rw-r--r--src/secp256k1/src/field_10x26_impl.h111
-rw-r--r--src/secp256k1/src/field_5x52_impl.h96
-rw-r--r--src/secp256k1/src/field_gmp.h18
-rw-r--r--src/secp256k1/src/field_gmp_impl.h184
-rw-r--r--src/secp256k1/src/field_impl.h16
-rw-r--r--src/secp256k1/src/group.h7
-rw-r--r--src/secp256k1/src/group_impl.h66
-rw-r--r--src/secp256k1/src/hash.h41
-rw-r--r--src/secp256k1/src/hash_impl.h291
-rw-r--r--src/secp256k1/src/secp256k1.c73
-rw-r--r--src/secp256k1/src/tests.c502
-rw-r--r--src/serialize.h2
-rw-r--r--src/streams.h18
-rw-r--r--src/sync.h11
-rw-r--r--src/test/accounting_tests.cpp6
-rw-r--r--src/test/bignum.h8
-rw-r--r--src/test/crypto_tests.cpp35
-rw-r--r--src/test/data/script_invalid.json108
-rw-r--r--src/test/data/script_valid.json63
-rw-r--r--src/test/data/sig_canonical.json7
-rw-r--r--src/test/data/sig_noncanonical.json22
-rw-r--r--src/test/multisig_tests.cpp20
-rw-r--r--src/test/script_P2SH_tests.cpp2
-rw-r--r--src/test/script_tests.cpp101
-rw-r--r--src/test/sighash_tests.cpp4
-rw-r--r--src/test/transaction_tests.cpp12
-rw-r--r--src/test/util_tests.cpp18
-rw-r--r--src/txdb.cpp59
-rw-r--r--src/txmempool.cpp8
-rw-r--r--src/wallet.cpp239
-rw-r--r--src/wallet.h837
-rw-r--r--src/walletdb.cpp6
-rw-r--r--src/walletdb.h2
234 files changed, 3681 insertions, 2490 deletions
diff --git a/.travis.yml b/.travis.yml
index 8b9ede3e1c..3c995be9a5 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -33,7 +33,7 @@ matrix:
- compiler: ": 32-bit + dash"
env: HOST=i686-pc-linux-gnu PACKAGES="g++-multilib bc" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-glibc-back-compat" USE_SHELL="/bin/dash"
- compiler: ": Cross-Mac"
- env: HOST=x86_64-apple-darwin11 PACKAGES="cmake libcap-dev libz-dev libbz2-dev" OSX_SDK=10.7 GOAL="deploy"
+ env: HOST=x86_64-apple-darwin11 PACKAGES="cmake libcap-dev libz-dev libbz2-dev" OSX_SDK=10.9 GOAL="deploy"
- compiler: ": Win64"
env: HOST=x86_64-w64-mingw32 PACKAGES="nsis gcc-mingw-w64-x86-64 g++-mingw-w64-x86-64 binutils-mingw-w64-x86-64 mingw-w64-dev wine bc" RUN_TESTS=true GOAL="deploy" BITCOIN_CONFIG="--enable-gui" MAKEJOBS="-j2"
- compiler: ": Win32"
diff --git a/Makefile.am b/Makefile.am
index 5649770602..c59648fd02 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -16,6 +16,7 @@ BITCOIN_WIN_INSTALLER=$(PACKAGE)-$(PACKAGE_VERSION)-win$(WINDOWS_BITS)-setup$(EX
OSX_APP=Bitcoin-Qt.app
OSX_DMG=Bitcoin-Qt.dmg
+OSX_BACKGROUND_IMAGE=background.tiff
OSX_DEPLOY_SCRIPT=$(top_srcdir)/contrib/macdeploy/macdeployqtplus
OSX_FANCY_PLIST=$(top_srcdir)/contrib/macdeploy/fancy.plist
OSX_INSTALLER_ICONS=$(top_srcdir)/src/qt/res/icons/bitcoin.icns
@@ -30,7 +31,7 @@ WINDOWS_PACKAGING = $(top_srcdir)/share/pixmaps/bitcoin.ico \
$(top_srcdir)/doc/README_windows.txt
OSX_PACKAGING = $(OSX_DEPLOY_SCRIPT) $(OSX_FANCY_PLIST) $(OSX_INSTALLER_ICONS) \
- $(top_srcdir)/contrib/macdeploy/background.png \
+ $(top_srcdir)/contrib/macdeploy/$(OSX_BACKGROUND_IMAGE) \
$(top_srcdir)/contrib/macdeploy/DS_Store \
$(top_srcdir)/contrib/macdeploy/detached-sig-apply.sh \
$(top_srcdir)/contrib/macdeploy/detached-sig-create.sh
@@ -95,7 +96,7 @@ $(OSX_DMG): $(OSX_APP_BUILT) $(OSX_PACKAGING)
deploydir: $(OSX_DMG)
else
APP_DIST_DIR=$(top_builddir)/dist
-APP_DIST_EXTRAS=$(APP_DIST_DIR)/.background/background.png $(APP_DIST_DIR)/.DS_Store $(APP_DIST_DIR)/Applications
+APP_DIST_EXTRAS=$(APP_DIST_DIR)/.background/$(OSX_BACKGROUND_IMAGE) $(APP_DIST_DIR)/.DS_Store $(APP_DIST_DIR)/Applications
$(APP_DIST_DIR)/Applications:
@rm -f $@
@@ -106,11 +107,11 @@ $(APP_DIST_EXTRAS): $(APP_DIST_DIR)/$(OSX_APP)/Contents/MacOS/Bitcoin-Qt
$(OSX_DMG): $(APP_DIST_EXTRAS)
$(GENISOIMAGE) -no-cache-inodes -D -l -probe -V "Bitcoin-Qt" -no-pad -r -apple -o $@ dist
-$(APP_DIST_DIR)/.background/background.png:
+$(APP_DIST_DIR)/.background/$(OSX_BACKGROUND_IMAGE): contrib/macdeploy/$(OSX_BACKGROUND_IMAGE)
$(MKDIR_P) $(@D)
- $(INSTALL) $(top_srcdir)/contrib/macdeploy/background.png $@
-$(APP_DIST_DIR)/.DS_Store:
- $(INSTALL) $(top_srcdir)/contrib/macdeploy/DS_Store $@
+ $(INSTALL) $< $@
+$(APP_DIST_DIR)/.DS_Store: contrib/macdeploy/DS_Store
+ $(INSTALL) $< $@
$(APP_DIST_DIR)/$(OSX_APP)/Contents/MacOS/Bitcoin-Qt: $(OSX_APP_BUILT) $(OSX_PACKAGING)
INSTALLNAMETOOL=$(INSTALLNAMETOOL) OTOOL=$(OTOOL) STRIP=$(STRIP) $(OSX_DEPLOY_SCRIPT) $(OSX_APP) -translations-dir=$(QT_TRANSLATION_DIR) -add-qt-tr $(OSX_QT_TRANSLATIONS) -verbose 2
diff --git a/build-aux/m4/bitcoin_find_bdb48.m4 b/build-aux/m4/bitcoin_find_bdb48.m4
index f3b14461eb..0bf558d25b 100644
--- a/build-aux/m4/bitcoin_find_bdb48.m4
+++ b/build-aux/m4/bitcoin_find_bdb48.m4
@@ -38,7 +38,7 @@ AC_DEFUN([BITCOIN_FIND_BDB48],[
done
if test "x$bdbpath" = "xX"; then
AC_MSG_RESULT([no])
- AC_MSG_ERROR(libdb_cxx headers missing)
+ AC_MSG_ERROR([libdb_cxx headers missing, Bitcoin Core requires this library for wallet functionality (--disable-wallet to disable wallet functionality)])
elif test "x$bdb48path" = "xX"; then
BITCOIN_SUBDIR_TO_INCLUDE(BDB_CPPFLAGS,[${bdbpath}],db_cxx)
AC_ARG_WITH([incompatible-bdb],[AS_HELP_STRING([--with-incompatible-bdb], [allow using a bdb version other than 4.8])],[
diff --git a/configure.ac b/configure.ac
index 9ca2f19bf9..85e3d1d669 100644
--- a/configure.ac
+++ b/configure.ac
@@ -64,13 +64,6 @@ AC_PATH_PROG(CCACHE,ccache)
AC_PATH_PROG(XGETTEXT,xgettext)
AC_PATH_PROG(HEXDUMP,hexdump)
-# This m4 will only be used if a system copy cannot be found. This is helpful
-# on systems where autotools are installed but the pkg-config macros are not in
-# a default location. It is currently used for building on OSX where autotools
-# are preinstalled but pkg-config comes from macports or homebrew. It should
-# probably be removed when building on <= 10.6 is no longer supported.
-m4_include([pkg.m4])
-
dnl pkg-config check.
PKG_PROG_PKG_CONFIG
diff --git a/contrib/debian/manpages/bitcoind.1 b/contrib/debian/manpages/bitcoind.1
index a1b17d6077..c225b9f3e9 100644
--- a/contrib/debian/manpages/bitcoind.1
+++ b/contrib/debian/manpages/bitcoind.1
@@ -85,19 +85,19 @@ This help message
Safely copies *wallet.dat* to 'destination', which can be a directory or a path with filename.
.TP
\fBgetaccount 'bitcoinaddress'\fR
-Returns the account associated with the given address.
+DEPRECATED. Returns the account associated with the given address.
.TP
\fBsetaccount 'bitcoinaddress' ['account']\fR
-Sets the ['account'] associated with the given address. ['account'] may be omitted to remove an address from ['account'].
+DEPRECATED. Sets the ['account'] associated with the given address. ['account'] may be omitted to remove an address from ['account'].
.TP
\fBgetaccountaddress 'account'\fR
-Returns a new bitcoin address for 'account'.
+DEPRECATED. Returns a new bitcoin address for 'account'.
.TP
\fBgetaddressesbyaccount 'account'\fR
-Returns the list of addresses associated with the given 'account'.
+DEPRECATED. Returns the list of addresses associated with the given 'account'.
.TP
\fBgetbalance 'account'\fR
-Returns the server's available balance, or the balance for 'account'.
+Returns the server's available balance, or the balance for 'account' (accounts are deprecated).
.TP
\fBgetblockcount\fR
Returns the number of blocks in the longest block chain.
@@ -124,10 +124,10 @@ Returns a recent hashes per second performance measurement while generating.
Returns an object containing server information.
.TP
\fBgetnewaddress 'account'\fR
-Returns a new bitcoin address for receiving payments. If 'account' is specified (recommended), it is added to the address book so payments received with the address will be credited to 'account'.
+Returns a new bitcoin address for receiving payments. If 'account' is specified (deprecated), it is added to the address book so payments received with the address will be credited to 'account'.
.TP
\fBgetreceivedbyaccount 'account' ['minconf=1']\fR
-Returns the total amount received by addresses associated with 'account' in transactions with at least ['minconf'] confirmations.
+DEPRECATED. Returns the total amount received by addresses associated with 'account' in transactions with at least ['minconf'] confirmations.
.TP
\fBgetreceivedbyaddress 'bitcoinaddress' ['minconf=1']\fR
Returns the total amount received by 'bitcoinaddress' in transactions with at least ['minconf'] confirmations.
@@ -147,13 +147,13 @@ If 'data' is specified, tries to solve the block and returns true if it was succ
List commands, or get help for a command.
.TP
\fBlistaccounts ['minconf=1']\fR
-List accounts and their current balances.
+DEPRECATED. List accounts and their current balances.
*note: requires bitcoin 0.3.20 or later.
.TP
\fBlistreceivedbyaccount ['minconf=1'] ['includeempty=false']\fR
['minconf'] is the minimum number of confirmations before payments are included. ['includeempty'] whether to include addresses that haven't received any payments. Returns an array of objects containing:
- "account" : the account of the receiving address.
+ "account" : DEPRECATED. the account of the receiving address.
"amount" : total amount received by the address.
"confirmations" : number of confirmations of the most recent transaction included.
.TP
@@ -161,7 +161,7 @@ List accounts and their current balances.
['minconf'] is the minimum number of confirmations before payments are included. ['includeempty'] whether to include addresses that haven't received any payments. Returns an array of objects containing:
"address" : receiving address.
- "account" : the account of the receiving address.
+ "account" : DEPRECATED. the account of the receiving address.
"amount" : total amount received by the address.
"confirmations" : number of confirmations of the most recent transaction included.
.TP
@@ -180,10 +180,10 @@ Returns a list of the last ['count'] transactions for 'account' \- for all accou
*note: requires bitcoin 0.3.20 or later.
.TP
\fBmove <'fromaccount'> <'toaccount'> <'amount'> ['minconf=1'] ['comment']\fR
-Moves funds between accounts.
+DEPRECATED. Moves funds between accounts.
.TP
\fBsendfrom* <'account'> <'bitcoinaddress'> <'amount'> ['minconf=1'] ['comment'] ['comment-to']\fR
-Sends amount from account's balance to 'bitcoinaddress'. This method will fail if there is less than amount bitcoins with ['minconf'] confirmations in the account's balance (unless account is the empty-string-named default account; it behaves like the *sendtoaddress* method). Returns transaction ID on success.
+DEPRECATED. Sends amount from account's balance to 'bitcoinaddress'. This method will fail if there is less than amount bitcoins with ['minconf'] confirmations in the account's balance (unless account is the empty-string-named default account; it behaves like the *sendtoaddress* method). Returns transaction ID on success.
.TP
\fBsendtoaddress 'bitcoinaddress' 'amount' ['comment'] ['comment-to']\fR
Sends amount from the server's available balance to 'bitcoinaddress'. amount is a real and is rounded to the nearest 0.01. Returns transaction id on success.
diff --git a/contrib/devtools/optimize-pngs.py b/contrib/devtools/optimize-pngs.py
new file mode 100755
index 0000000000..38aaa00f31
--- /dev/null
+++ b/contrib/devtools/optimize-pngs.py
@@ -0,0 +1,73 @@
+#!/usr/bin/env python
+
+import os
+import sys
+import subprocess
+import hashlib
+from PIL import Image
+
+def file_hash(filename):
+ '''Return hash of raw file contents'''
+ with open(filename, 'rb') as f:
+ return hashlib.sha256(f.read()).hexdigest()
+
+def content_hash(filename):
+ '''Return hash of RGBA contents of image'''
+ i = Image.open(filename)
+ i = i.convert('RGBA')
+ data = i.tostring()
+ return hashlib.sha256(data).hexdigest()
+
+#optimize png, remove various color profiles, remove ancillary chunks (alla) and text chunks (text)
+#pngcrush -brute -ow -rem gAMA -rem cHRM -rem iCCP -rem sRGB -rem alla -rem text
+
+pngcrush = 'pngcrush'
+git = 'git'
+folders = ["src/qt/res/movies", "src/qt/res/icons", "src/qt/res/images"]
+basePath = subprocess.check_output([git, 'rev-parse', '--show-toplevel']).rstrip('\n')
+totalSaveBytes = 0
+
+outputArray = []
+for folder in folders:
+ absFolder=os.path.join(basePath, folder)
+ for file in os.listdir(absFolder):
+ extension = os.path.splitext(file)[1]
+ if extension.lower() == '.png':
+ print("optimizing "+file+"..."),
+ file_path = os.path.join(absFolder, file)
+ fileMetaMap = {'file' : file, 'osize': os.path.getsize(file_path), 'sha256Old' : file_hash(file_path)};
+ fileMetaMap['contentHashPre'] = content_hash(file_path)
+
+ pngCrushOutput = ""
+ try:
+ pngCrushOutput = subprocess.check_output(
+ [pngcrush, "-brute", "-ow", "-rem", "gAMA", "-rem", "cHRM", "-rem", "iCCP", "-rem", "sRGB", "-rem", "alla", "-rem", "text", file_path],
+ stderr=subprocess.STDOUT).rstrip('\n')
+ except:
+ print "pngcrush is not installed, aborting..."
+ sys.exit(0)
+
+ #verify
+ if "Not a PNG file" in subprocess.check_output([pngcrush, "-n", "-v", file_path], stderr=subprocess.STDOUT):
+ print "PNG file "+file+" is corrupted after crushing, check out pngcursh version"
+ sys.exit(1)
+
+ fileMetaMap['sha256New'] = file_hash(file_path)
+ fileMetaMap['contentHashPost'] = content_hash(file_path)
+
+ if fileMetaMap['contentHashPre'] != fileMetaMap['contentHashPost']:
+ print "Image contents of PNG file "+file+" before and after crushing don't match"
+ sys.exit(1)
+
+ fileMetaMap['psize'] = os.path.getsize(file_path)
+ outputArray.append(fileMetaMap)
+ print("done\n"),
+
+print "summary:\n+++++++++++++++++"
+for fileDict in outputArray:
+ oldHash = fileDict['sha256Old']
+ newHash = fileDict['sha256New']
+ totalSaveBytes += fileDict['osize'] - fileDict['psize']
+ print fileDict['file']+"\n size diff from: "+str(fileDict['osize'])+" to: "+str(fileDict['psize'])+"\n old sha256: "+oldHash+"\n new sha256: "+newHash+"\n"
+
+print "completed. Total reduction: "+str(totalSaveBytes)+" bytes"
diff --git a/contrib/gitian-descriptors/gitian-osx.yml b/contrib/gitian-descriptors/gitian-osx.yml
index 0732d35301..3ca42248d4 100644
--- a/contrib/gitian-descriptors/gitian-osx.yml
+++ b/contrib/gitian-descriptors/gitian-osx.yml
@@ -23,7 +23,7 @@ remotes:
- "url": "https://github.com/bitcoin/bitcoin.git"
"dir": "bitcoin"
files:
-- "MacOSX10.7.sdk.tar.gz"
+- "MacOSX10.9.sdk.tar.gz"
script: |
WRAP_DIR=$HOME/wrapped
HOSTS="x86_64-apple-darwin11"
@@ -72,7 +72,7 @@ script: |
BASEPREFIX=`pwd`/depends
mkdir -p ${BASEPREFIX}/SDKs
- tar -C ${BASEPREFIX}/SDKs -xf ${BUILD_DIR}/MacOSX10.7.sdk.tar.gz
+ tar -C ${BASEPREFIX}/SDKs -xf ${BUILD_DIR}/MacOSX10.9.sdk.tar.gz
# Build dependencies for each host
for i in $HOSTS; do
diff --git a/contrib/gitian-downloader/jonasschnelli-key.pgp b/contrib/gitian-downloader/jonasschnelli-key.pgp
new file mode 100644
index 0000000000..fe44c0fbd4
--- /dev/null
+++ b/contrib/gitian-downloader/jonasschnelli-key.pgp
Binary files differ
diff --git a/contrib/macdeploy/DS_Store b/contrib/macdeploy/DS_Store
index 7527dc671f..099960712a 100644
--- a/contrib/macdeploy/DS_Store
+++ b/contrib/macdeploy/DS_Store
Binary files differ
diff --git a/contrib/macdeploy/background.png b/contrib/macdeploy/background.png
index fce12e3807..f88a2ae74b 100644
--- a/contrib/macdeploy/background.png
+++ b/contrib/macdeploy/background.png
Binary files differ
diff --git a/contrib/macdeploy/background.psd b/contrib/macdeploy/background.psd
index 5889676f8e..fdc4f4ca4a 100644
--- a/contrib/macdeploy/background.psd
+++ b/contrib/macdeploy/background.psd
Binary files differ
diff --git a/contrib/macdeploy/background.tiff b/contrib/macdeploy/background.tiff
new file mode 100644
index 0000000000..4b44ac672e
--- /dev/null
+++ b/contrib/macdeploy/background.tiff
Binary files differ
diff --git a/contrib/macdeploy/background@2x.png b/contrib/macdeploy/background@2x.png
new file mode 100644
index 0000000000..4858183f75
--- /dev/null
+++ b/contrib/macdeploy/background@2x.png
Binary files differ
diff --git a/contrib/macdeploy/fancy.plist b/contrib/macdeploy/fancy.plist
index e73b9b697e..ef277a7f14 100644
--- a/contrib/macdeploy/fancy.plist
+++ b/contrib/macdeploy/fancy.plist
@@ -10,7 +10,7 @@
<integer>620</integer>
</array>
<key>background_picture</key>
- <string>background.png</string>
+ <string>background.tiff</string>
<key>icon_size</key>
<integer>96</integer>
<key>applications_symlink</key>
diff --git a/contrib/macdeploy/macdeployqtplus b/contrib/macdeploy/macdeployqtplus
index 541136001f..0eb6b2c84d 100755
--- a/contrib/macdeploy/macdeployqtplus
+++ b/contrib/macdeploy/macdeployqtplus
@@ -767,7 +767,7 @@ if config.dmg is not None:
for path, dirs, files in os.walk("dist"):
for file in files:
size += os.path.getsize(os.path.join(path, file))
- size += int(size * 0.1)
+ size += int(size * 0.15)
if verbose >= 3:
print "Creating temp image for modification..."
@@ -791,7 +791,8 @@ if config.dmg is not None:
print "+ Applying fancy settings +"
if fancy.has_key("background_picture"):
- bg_path = os.path.join(disk_root, os.path.basename(fancy["background_picture"]))
+ bg_path = os.path.join(disk_root, ".background", os.path.basename(fancy["background_picture"]))
+ os.mkdir(os.path.dirname(bg_path))
if verbose >= 3:
print fancy["background_picture"], "->", bg_path
shutil.copy2(fancy["background_picture"], bg_path)
@@ -849,8 +850,8 @@ if config.dmg is not None:
if bg_path is not None:
# Set background file, then call SetFile to make it invisible.
# (note: making it invisible first makes set background picture fail)
- bgscript = Template("""set background picture of theViewOptions to file "$bgpic"
- do shell script "SetFile -a V /Volumes/$disk/$bgpic" """)
+ bgscript = Template("""set background picture of theViewOptions to file ".background:$bgpic"
+ do shell script "SetFile -a V /Volumes/$disk/.background/$bgpic" """)
params["background_commands"] = bgscript.substitute({"bgpic" : os.path.basename(bg_path), "disk" : params["disk"]})
s = appscript.substitute(params)
diff --git a/depends/README b/depends/README
index fed2f9b5ab..55e7222697 100644
--- a/depends/README
+++ b/depends/README
@@ -7,7 +7,7 @@ There are several features that make it different from most similar systems:
In theory, binaries for any target OS/architecture can be created, from a
builder running any OS/architecture. In practice, build-side tools must be
-specified when the defaults don't fit, and packages must be ammended to work
+specified when the defaults don't fit, and packages must be amended to work
on new hosts. For now, a build architecture of x86_64 is assumed, either on
Linux or OSX.
diff --git a/depends/config.guess b/depends/config.guess
index 1f5c50c0d1..dbfb9786cb 100755
--- a/depends/config.guess
+++ b/depends/config.guess
@@ -1,8 +1,8 @@
#! /bin/sh
# Attempt to guess a canonical system name.
-# Copyright 1992-2014 Free Software Foundation, Inc.
+# Copyright 1992-2015 Free Software Foundation, Inc.
-timestamp='2014-03-23'
+timestamp='2015-01-01'
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
@@ -24,12 +24,12 @@ timestamp='2014-03-23'
# program. This Exception is an additional permission under section 7
# of the GNU General Public License, version 3 ("GPLv3").
#
-# Originally written by Per Bothner.
+# Originally written by Per Bothner; maintained since 2000 by Ben Elliston.
#
# You can get the latest version of this script from:
# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
#
-# Please send patches with a ChangeLog entry to config-patches@gnu.org.
+# Please send patches to <config-patches@gnu.org>.
me=`echo "$0" | sed -e 's,.*/,,'`
@@ -50,7 +50,7 @@ version="\
GNU config.guess ($timestamp)
Originally written by Per Bothner.
-Copyright 1992-2014 Free Software Foundation, Inc.
+Copyright 1992-2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
@@ -579,8 +579,9 @@ EOF
else
IBM_ARCH=powerpc
fi
- if [ -x /usr/bin/oslevel ] ; then
- IBM_REV=`/usr/bin/oslevel`
+ if [ -x /usr/bin/lslpp ] ; then
+ IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc |
+ awk -F: '{ print $3 }' | sed s/[0-9]*$/0/`
else
IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
fi
diff --git a/depends/config.sub b/depends/config.sub
index d654d03cdc..6d2e94c8bf 100755
--- a/depends/config.sub
+++ b/depends/config.sub
@@ -1,8 +1,8 @@
#! /bin/sh
# Configuration validation subroutine script.
-# Copyright 1992-2014 Free Software Foundation, Inc.
+# Copyright 1992-2015 Free Software Foundation, Inc.
-timestamp='2014-05-01'
+timestamp='2015-01-01'
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
@@ -25,7 +25,7 @@ timestamp='2014-05-01'
# of the GNU General Public License, version 3 ("GPLv3").
-# Please send patches with a ChangeLog entry to config-patches@gnu.org.
+# Please send patches to <config-patches@gnu.org>.
#
# Configuration subroutine to validate and canonicalize a configuration type.
# Supply the specified configuration type as an argument.
@@ -68,7 +68,7 @@ Report bugs and patches to <config-patches@gnu.org>."
version="\
GNU config.sub ($timestamp)
-Copyright 1992-2014 Free Software Foundation, Inc.
+Copyright 1992-2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
@@ -260,7 +260,7 @@ case $basic_machine in
| c4x | c8051 | clipper \
| d10v | d30v | dlx | dsp16xx \
| epiphany \
- | fido | fr30 | frv \
+ | fido | fr30 | frv | ft32 \
| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
| hexagon \
| i370 | i860 | i960 | ia64 \
@@ -302,6 +302,7 @@ case $basic_machine in
| pdp10 | pdp11 | pj | pjl \
| powerpc | powerpc64 | powerpc64le | powerpcle \
| pyramid \
+ | riscv32 | riscv64 \
| rl78 | rx \
| score \
| sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
@@ -312,6 +313,7 @@ case $basic_machine in
| tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \
| ubicom32 \
| v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \
+ | visium \
| we32k \
| x86 | xc16x | xstormy16 | xtensa \
| z8k | z80)
@@ -326,6 +328,9 @@ case $basic_machine in
c6x)
basic_machine=tic6x-unknown
;;
+ leon|leon[3-9])
+ basic_machine=sparc-$basic_machine
+ ;;
m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip)
basic_machine=$basic_machine-unknown
os=-none
@@ -436,6 +441,7 @@ case $basic_machine in
| ubicom32-* \
| v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \
| vax-* \
+ | visium-* \
| we32k-* \
| x86-* | x86_64-* | xc16x-* | xps100-* \
| xstormy16-* | xtensa*-* \
@@ -773,6 +779,9 @@ case $basic_machine in
basic_machine=m68k-isi
os=-sysv
;;
+ leon-*|leon[3-9]-*)
+ basic_machine=sparc-`echo $basic_machine | sed 's/-.*//'`
+ ;;
m68knommu)
basic_machine=m68k-unknown
os=-linux
@@ -828,6 +837,10 @@ case $basic_machine in
basic_machine=powerpc-unknown
os=-morphos
;;
+ moxiebox)
+ basic_machine=moxie-unknown
+ os=-moxiebox
+ ;;
msdos)
basic_machine=i386-pc
os=-msdos
@@ -1373,7 +1386,7 @@ case $os in
| -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
| -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \
| -linux-newlib* | -linux-musl* | -linux-uclibc* \
- | -uxpv* | -beos* | -mpeix* | -udk* \
+ | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \
| -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
| -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
| -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
diff --git a/depends/funcs.mk b/depends/funcs.mk
index 337634253f..b407737f7f 100644
--- a/depends/funcs.mk
+++ b/depends/funcs.mk
@@ -205,7 +205,7 @@ endef
# These functions create the build targets for each package. They must be
# broken down into small steps so that each part is done for all packages
# before moving on to the next step. Otherwise, a package's info
-# (build-id for example) would only be avilable to another package if it
+# (build-id for example) would only be available to another package if it
# happened to be computed already.
#set the type for host/build packages.
diff --git a/depends/hosts/darwin.mk b/depends/hosts/darwin.mk
index c1070d8775..2958dc50cc 100644
--- a/depends/hosts/darwin.mk
+++ b/depends/hosts/darwin.mk
@@ -1,5 +1,5 @@
-OSX_MIN_VERSION=10.6
-OSX_SDK_VERSION=10.7
+OSX_MIN_VERSION=10.7
+OSX_SDK_VERSION=10.9
OSX_SDK=$(SDK_PATH)/MacOSX$(OSX_SDK_VERSION).sdk
LD64_VERSION=241.9
darwin_CC=clang -target $(host) -mmacosx-version-min=$(OSX_MIN_VERSION) --sysroot $(OSX_SDK) -mlinker-version=$(LD64_VERSION)
diff --git a/depends/packages/openssl.mk b/depends/packages/openssl.mk
index ad64494c1f..22b1017ffc 100644
--- a/depends/packages/openssl.mk
+++ b/depends/packages/openssl.mk
@@ -1,8 +1,8 @@
package=openssl
-$(package)_version=1.0.1j
+$(package)_version=1.0.1k
$(package)_download_path=https://www.openssl.org/source
$(package)_file_name=$(package)-$($(package)_version).tar.gz
-$(package)_sha256_hash=1b60ca8789ba6f03e8ef20da2293b8dc131c39d83814e775069f02d26354edf3
+$(package)_sha256_hash=8f9faeaebad088e772f4ef5e38252d472be4d878c6b3a2718c10a4fcebe7a41c
define $(package)_set_vars
$(package)_config_env=AR="$($(package)_ar)" RANLIB="$($(package)_ranlib)" CC="$($(package)_cc)"
@@ -23,7 +23,7 @@ $(package)_config_opts_i686_mingw32=mingw
endef
define $(package)_preprocess_cmds
- sed -i.old "/define DATE/d" crypto/Makefile && \
+ sed -i.old "/define DATE/d" util/mkbuildinf.pl && \
sed -i.old "s|engines apps test|engines|" Makefile.org
endef
diff --git a/doc/README.md b/doc/README.md
index b2a0c2dcb7..0ade8f9923 100644
--- a/doc/README.md
+++ b/doc/README.md
@@ -3,7 +3,7 @@ Bitcoin Core 0.10.99
Setup
---------------------
-[Bitcoin Core](http://bitcoin.org/en/download) is the original Bitcoin client and it builds the backbone of the network. However, it downloads and stores the entire history of Bitcoin transactions (which is currently several GBs); depending on the speed of your computer and network connection, the synchronization process can take anywhere from a few hours to a day or more. Thankfully you only have to do this once. If you would like the process to go faster you can [download the blockchain directly](bootstrap.md).
+[Bitcoin Core](http://bitcoin.org/en/download) is the original Bitcoin client and it builds the backbone of the network. However, it downloads and stores the entire history of Bitcoin transactions (which is currently several GBs); depending on the speed of your computer and network connection, the synchronization process can take anywhere from a few hours to a day or more.
Running
---------------------
diff --git a/doc/README_osx.txt b/doc/README_osx.txt
index d56234f7d9..6c0c21c190 100644
--- a/doc/README_osx.txt
+++ b/doc/README_osx.txt
@@ -29,14 +29,15 @@ originally done in toolchain4.
To complicate things further, all builds must target an Apple SDK. These SDKs
are free to download, but not redistributable.
-To obtain it, register for a developer account, then download xcode4630916281a.dmg:
-https://developer.apple.com/downloads/download.action?path=Developer_Tools/xcode_4.6.3/xcode4630916281a.dmg
+To obtain it, register for a developer account, then download the XCode 6.1.1 dmg:
+https://developer.apple.com/downloads/download.action?path=Developer_Tools/xcode_6.1.1/xcode_6.1.1.dmg
+
This file is several gigabytes in size, but only a single directory inside is
-needed: Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.7.sdk
+needed: Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk
Unfortunately, the usual linux tools (7zip, hpmount, loopback mount) are incapable of opening this file.
To create a tarball suitable for gitian input, mount the dmg in OSX, then create it with:
- $ tar -C /Volumes/Xcode/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/ -czf MacOSX10.7.sdk.tar.gz MacOSX10.7.sdk
+ $ tar -C /Volumes/Xcode/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/ -czf MacOSX10.9.sdk.tar.gz MacOSX10.9.sdk
The gitian descriptors build 2 sets of files: Linux tools, then Apple binaries
diff --git a/doc/bootstrap.md b/doc/bootstrap.md
deleted file mode 100644
index b84fd24b11..0000000000
--- a/doc/bootstrap.md
+++ /dev/null
@@ -1,56 +0,0 @@
-### Bootstrap the Blockchain Synchronization
-
-Normally the Bitcoin client will download the transaction and network information, called the blockchain, from the network by syncing with the other clients. This process can take quite some time as the [Bitcoin blockchain](https://blockchain.info/charts/blocks-size) is growing bigger and bigger for each day. Luckily there is a safe and fast way to speed up this process. We'll show you how to bootstrap your blockchain to bring your client up to speed in just a few simple steps.
-
-### Requirements
-
-- A fresh install of the Bitcoin client software.
-
-### Download the blockchain via BitTorrent
-
-Jeff Garzik, Bitcoin Core developer, offers an [torrent file](https://bitcointalk.org/index.php?topic=145386.0) for bootstrapping purposes that is updated often. BitTorrent is a protocol that speeds up the downloading of large files by using the other clients in the network. Examples of free and safe open source clients are [Deluge](http://deluge-torrent.org/) or [qBittorrent](http://www.qbittorrent.org/). A guide to installing and configuring the torrent clients can be found [here](http://dev.deluge-torrent.org/wiki/UserGuide) for Deluge and [here](http://qbforums.shiki.hu/) for qBittorrent. A further in-depth tutorial on BitTorrent can be found [here](http://www.howtogeek.com/howto/31846/bittorrent-for-beginners-how-get-started-downloading-torrents/).
-
-With the client installed we'll proceed to download the blockchain torrent file. Use the following magnet link:
-
- magnet:?xt=urn:btih:2d4e6c1f96c5d5fb260dff92aea4e600227f1aea&dn=bootstrap.dat&tr=udp://tracker.openbittorrent.com:80&tr=udp://tracker.publicbt.com:80&tr=udp://tracker.ccc.de:80&tr=udp://tracker.istole.it:80
-
- or go to [Jeff Garzik's topic](https://bitcointalk.org/index.php?topic=145386.0) for a signed magnet link. Alternatively you can use the [.torrent file](http://sourceforge.net/projects/bitcoin/files/Bitcoin/blockchain/bootstrap.dat.torrent/download) found on SourceForge.
-
-![Fig1](img/bootstrap1.png)
-
-The download page should look like this, with a countdown to the download. If it does not work click the direct download link.
-
-The torrent client installed will recognize the download of the torrent file. Save the bootstrap.dat file to the folder you use for downloads. The image below shows the torrent download in qBittorrent, with current speed and ETA highlighted.
-
-![Fig2](img/bootstrap2.png)
-
-### Importing the blockchain
-Exit the Bitcoin client software if you have it running. Be sure not to have an actively used wallet in use. We are going to copy the download of the blockchain to the Bitcoin client data directory. You should run the client software at least once so it can generate the data directory. Copy the downloaded bootstrap.dat file into the Bitcoin data folder.
-
-**For Windows users:**
-Open explorer, and type into the address bar:
-
- %APPDATA%\Bitcoin
-
-This will open up the data folder. It should look like the image below. Copy over the bootstrap.dat from your download folder to this directory.
-![Fig4](img/bootstrap4.png)
-
-**For OSX users:**
-Open Finder by pressing Press [shift] + [cmd] + [g] and enter:
-
- ~/Library/Application Support/Bitcoin/
-
-**For Linux users:**
-The directory is hidden in your User folder. Go to:
-
- ~/.bitcoin/
-
-### Importing the blockchain
-Now start the Bitcoin client software. It should show "Importing blocks from disk" like the image below.
-![Fig5](img/bootstrap5.png)
-
-Wait until the import finishes. The client will download the last days not covered by the import. Congratulations you have successfully imported the blockchain!
-
-### Is this safe?
-
-Yes, the above method is safe. The download contains only raw blockchain data and the client verifies this on import. Do not download the blockchain from unofficial sources, especially if they provide `*.rev` and `*.sst` files. These files are not verified and can contain malicious edits.
diff --git a/doc/build-osx.md b/doc/build-osx.md
index c41820f2b1..d6e93cb23d 100644
--- a/doc/build-osx.md
+++ b/doc/build-osx.md
@@ -21,12 +21,6 @@ Xcode 4.3 or later, you'll need to install its command line tools. This can
be done in `Xcode > Preferences > Downloads > Components` and generally must
be re-done or updated every time Xcode is updated.
-There's also an assumption that you already have `git` installed. If
-not, it's the path of least resistance to install [Github for Mac](https://mac.github.com/)
-(OS X 10.7+) or
-[Git for OS X](https://code.google.com/p/git-osx-installer/). It is also
-available via Homebrew.
-
You will also need to install [Homebrew](http://brew.sh) in order to install library
dependencies.
@@ -38,7 +32,9 @@ Instructions: Homebrew
#### Install dependencies using Homebrew
- brew install autoconf automake libtool boost miniupnpc openssl pkg-config protobuf qt
+ brew install autoconf automake libtool boost miniupnpc openssl pkg-config protobuf qt5
+
+NOTE: Building with Qt4 is still supported, however, could result in a broken UI. As such, building with Qt5 is recommended.
#### Installing berkeley-db4 using Homebrew
@@ -46,7 +42,7 @@ The homebrew package for berkeley-db4 has been broken for some time. It will in
Running this command takes you into brew's interactive mode, which allows you to configure, make, and install by hand:
```
-$ brew install https://raw.github.com/mxcl/homebrew/master/Library/Formula/berkeley-db4.rb -–without-java
+$ brew install https://raw.github.com/homebrew/homebrew/master/Library/Formula/berkeley-db4.rb -–without-java
```
The rest of these commands are run inside brew interactive mode:
@@ -73,7 +69,7 @@ After exiting, you'll get a warning that the install is keg-only, which means it
2. Build bitcoind:
./autogen.sh
- ./configure
+ ./configure --with-gui=qt5
make
3. It is also a good idea to build and run the unit tests:
@@ -115,7 +111,7 @@ All dependencies should be compiled with these flags:
-arch x86_64
-isysroot $(xcode-select --print-path)/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.7.sdk
-Once dependencies are compiled, see release-process.md for how the Bitcoin-Qt.app
+Once dependencies are compiled, see [doc/release-process.md](release-process.md) for how the Bitcoin-Qt.app
bundle is packaged and signed to create the .dmg disk image that is distributed.
Running
diff --git a/doc/build-unix.md b/doc/build-unix.md
index 8ddee3b757..0984f689a8 100644
--- a/doc/build-unix.md
+++ b/doc/build-unix.md
@@ -159,7 +159,7 @@ tar -xzvf db-4.8.30.NC.tar.gz
# Build the library and install to our prefix
cd db-4.8.30.NC/build_unix/
-# Note: Do a static build so that it can be embedded into the exectuable, instead of having to find a .so at runtime
+# Note: Do a static build so that it can be embedded into the executable, instead of having to find a .so at runtime
../dist/configure --enable-cxx --disable-shared --with-pic --prefix=$BDB_PREFIX
make install
@@ -196,7 +196,7 @@ Hardening enables the following features:
* Position Independent Executable
Build position independent code to take advantage of Address Space Layout Randomization
offered by some kernels. An attacker who is able to cause execution of code at an arbitrary
- memory location is thwarted if he doesn't know where anything useful is located.
+ memory location is thwarted if he or she doesn't know where anything useful is located.
The stack and heap are randomly located by default but this allows the code section to be
randomly located as well.
diff --git a/doc/gitian-building.md b/doc/gitian-building.md
index 1312979cac..25d3b8390c 100644
--- a/doc/gitian-building.md
+++ b/doc/gitian-building.md
@@ -24,7 +24,7 @@ Table of Contents
- [Connecting to the VM](#connecting-to-the-vm)
- [Setting up Debian for gitian building](#setting-up-debian-for-gitian-building)
- [Installing gitian](#installing-gitian)
-- [Setting up gitian images](#setting-up-gitian-images)
+- [Setting up the gitian image](#setting-up-the-gitian-image)
- [Getting and building the inputs](#getting-and-building-the-inputs)
- [Building Bitcoin](#building-bitcoin)
- [Building an alternative repository](#building-an-alternative-repository)
@@ -74,11 +74,11 @@ In the VirtualBox GUI click "Create" and choose the following parameters in the
- Disk size: at least 40GB; as low as 20GB *may* be possible, but better to err on the safe side
- Push the `Create` button
-Get the [Debian 7.4 net installer](http://ftp.at.debian.org/debian-jigdo/current/amd64/iso-cd/debian-7.4.0-amd64-netinst.iso) (a more recent minor version should also work, see also [Debian Network installation](https://www.debian.org/CD/netinst/)).
+Get the [Debian 7.7 net installer](http://cdimage.debian.org/debian-cd/7.7.0/amd64/iso-cd/debian-7.7.0-amd64-netinst.iso) (a more recent minor version should also work, see also [Debian Network installation](https://www.debian.org/CD/netinst/)).
This DVD image can be validated using a SHA256 hashing tool, for example on
Unixy OSes by entering the following in a terminal:
- echo "b712a141bc60269db217d3b3e456179bd6b181645f90e4aac9c42ed63de492e9 debian-7.4.0-amd64-netinst.iso" | sha256sum -c
+ echo "d440e85b4121f94608748139f25dbce1ad36771348b002fe07d4d44b9d9e623f debian-7.7.0-amd64-netinst.iso" | sha256sum -c
# (must return OK)
After creating the VM, we need to configure it.
@@ -109,7 +109,7 @@ Then start the VM. On the first launch you will be asked for a CD or DVD image.
Installing Debian
------------------
-In this section it will be explained how to install Debian on the newly created VM.
+This section will explain how to install Debian on the newly created VM.
- Choose the non-graphical installer. We do not need the graphical environment, it will only increase installation time and disk usage.
@@ -277,24 +277,21 @@ cd ..
**Note**: When sudo asks for a password, enter the password for the user *debian* not for *root*.
-Clone the git repositories for bitcoin and gitian and then checkout the bitcoin version that you want to build.
+Clone the git repositories for bitcoin and gitian.
```bash
git clone https://github.com/devrandom/gitian-builder.git
git clone https://github.com/bitcoin/bitcoin
-cd bitcoin
-git checkout v${VERSION}
-cd ..
```
-Setting up gitian images
+Setting up the gitian image
-------------------------
-Gitian needs virtual images of the operating system to build in.
-Currently this is Ubuntu Precise for x86_64.
-These images will be copied and used every time that a build is started to
+Gitian needs a virtual image of the operating system to build in.
+Currently this is Ubuntu Precise x86_64.
+This image will be copied and used every time that a build is started to
make sure that the build is deterministic.
-Creating the images will take a while, but only has to be done once.
+Creating the image will take a while, but only has to be done once.
Execute the following as user `debian`:
@@ -303,7 +300,7 @@ cd gitian-builder
bin/make-base-vm --lxc --arch amd64 --suite precise
```
-There will be a lot of warnings printed during build of the images. These can be ignored.
+There will be a lot of warnings printed during build of the image. These can be ignored.
**Note**: When sudo asks for a password, enter the password for the user *debian* not for *root*.
@@ -322,13 +319,14 @@ To build Bitcoin (for Linux, OSX and Windows) just follow the steps under 'perfo
gitian builds' in [doc/release-process.md](release-process.md) in the bitcoin repository.
This may take a long time as it also builds the dependencies needed for each descriptor.
-These dependencies will be cached after a successful build to avoid rebuilding them when possible.
+These dependencies will be cached after a successful build to avoid rebuilding them where possible.
At any time you can check the package installation and build progress with
```bash
tail -f var/install.log
tail -f var/build.log
+```
Output from `gbuild` will look something like
@@ -382,9 +380,9 @@ When you execute `gsign` you will get an error from GPG, which can be ignored. C
in `gitian.sigs` to your signing machine and do
```bash
- gpg --detach-sign ${VERSION}-linux/${SIGNER}/bitcoin-build.assert
- gpg --detach-sign ${VERSION}-win/${SIGNER}/bitcoin-build.assert
- gpg --detach-sign ${VERSION}-osx/${SIGNER}/bitcoin-build.assert
+ gpg --detach-sign ${VERSION}-linux/${SIGNER}/bitcoin-linux-build.assert
+ gpg --detach-sign ${VERSION}-win/${SIGNER}/bitcoin-win-build.assert
+ gpg --detach-sign ${VERSION}-osx-unsigned/${SIGNER}/bitcoin-osx-build.assert
```
This will create the `.sig` files that can be committed together with the `.assert` files to assert your
diff --git a/doc/release-process.md b/doc/release-process.md
index eb2eb619bd..363465d827 100644
--- a/doc/release-process.md
+++ b/doc/release-process.md
@@ -44,11 +44,11 @@ Release Process
Register and download the Apple SDK: (see OSX Readme for details)
- https://developer.apple.com/downloads/download.action?path=Developer_Tools/xcode_4.6.3/xcode4630916281a.dmg
+ https://developer.apple.com/downloads/download.action?path=Developer_Tools/xcode_6.1.1/xcode_6.1.1.dmg
- Using a Mac, create a tarball for the 10.7 SDK and copy it to the inputs directory:
+ Using a Mac, create a tarball for the 10.9 SDK and copy it to the inputs directory:
- tar -C /Volumes/Xcode/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/ -czf MacOSX10.7.sdk.tar.gz MacOSX10.7.sdk
+ tar -C /Volumes/Xcode/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/ -czf MacOSX10.9.sdk.tar.gz MacOSX10.9.sdk
###Optional: Seed the Gitian sources cache
diff --git a/pkg.m4 b/pkg.m4
deleted file mode 100644
index c5b26b52e6..0000000000
--- a/pkg.m4
+++ /dev/null
@@ -1,214 +0,0 @@
-# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*-
-# serial 1 (pkg-config-0.24)
-#
-# Copyright © 2004 Scott James Remnant <scott@netsplit.com>.
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-#
-# As a special exception to the GNU General Public License, if you
-# distribute this file as part of a program that contains a
-# configuration script generated by Autoconf, you may include it under
-# the same distribution terms that you use for the rest of that program.
-
-# PKG_PROG_PKG_CONFIG([MIN-VERSION])
-# ----------------------------------
-AC_DEFUN([PKG_PROG_PKG_CONFIG],
-[m4_pattern_forbid([^_?PKG_[A-Z_]+$])
-m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$])
-m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$])
-AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])
-AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path])
-AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path])
-
-if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
- AC_PATH_TOOL([PKG_CONFIG], [pkg-config])
-fi
-if test -n "$PKG_CONFIG"; then
- _pkg_min_version=m4_default([$1], [0.9.0])
- AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version])
- if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
- AC_MSG_RESULT([yes])
- else
- AC_MSG_RESULT([no])
- PKG_CONFIG=""
- fi
-fi[]dnl
-])# PKG_PROG_PKG_CONFIG
-
-# PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
-#
-# Check to see whether a particular set of modules exists. Similar
-# to PKG_CHECK_MODULES(), but does not set variables or print errors.
-#
-# Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG])
-# only at the first occurence in configure.ac, so if the first place
-# it's called might be skipped (such as if it is within an "if", you
-# have to call PKG_CHECK_EXISTS manually
-# --------------------------------------------------------------
-AC_DEFUN([PKG_CHECK_EXISTS],
-[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
-if test -n "$PKG_CONFIG" && \
- AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then
- m4_default([$2], [:])
-m4_ifvaln([$3], [else
- $3])dnl
-fi])
-
-# _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES])
-# ---------------------------------------------
-m4_define([_PKG_CONFIG],
-[if test -n "$$1"; then
- pkg_cv_[]$1="$$1"
- elif test -n "$PKG_CONFIG"; then
- PKG_CHECK_EXISTS([$3],
- [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`
- test "x$?" != "x0" && pkg_failed=yes ],
- [pkg_failed=yes])
- else
- pkg_failed=untried
-fi[]dnl
-])# _PKG_CONFIG
-
-# _PKG_SHORT_ERRORS_SUPPORTED
-# -----------------------------
-AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED],
-[AC_REQUIRE([PKG_PROG_PKG_CONFIG])
-if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
- _pkg_short_errors_supported=yes
-else
- _pkg_short_errors_supported=no
-fi[]dnl
-])# _PKG_SHORT_ERRORS_SUPPORTED
-
-
-# PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
-# [ACTION-IF-NOT-FOUND])
-#
-#
-# Note that if there is a possibility the first call to
-# PKG_CHECK_MODULES might not happen, you should be sure to include an
-# explicit call to PKG_PROG_PKG_CONFIG in your configure.ac
-#
-#
-# --------------------------------------------------------------
-AC_DEFUN([PKG_CHECK_MODULES],
-[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
-AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl
-AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl
-
-pkg_failed=no
-AC_MSG_CHECKING([for $1])
-
-_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2])
-_PKG_CONFIG([$1][_LIBS], [libs], [$2])
-
-m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS
-and $1[]_LIBS to avoid the need to call pkg-config.
-See the pkg-config man page for more details.])
-
-if test $pkg_failed = yes; then
- AC_MSG_RESULT([no])
- _PKG_SHORT_ERRORS_SUPPORTED
- if test $_pkg_short_errors_supported = yes; then
- $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1`
- else
- $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1`
- fi
- # Put the nasty error message in config.log where it belongs
- echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD
-
- m4_default([$4], [AC_MSG_ERROR(
-[Package requirements ($2) were not met:
-
-$$1_PKG_ERRORS
-
-Consider adjusting the PKG_CONFIG_PATH environment variable if you
-installed software in a non-standard prefix.
-
-_PKG_TEXT])[]dnl
- ])
-elif test $pkg_failed = untried; then
- AC_MSG_RESULT([no])
- m4_default([$4], [AC_MSG_FAILURE(
-[The pkg-config script could not be found or is too old. Make sure it
-is in your PATH or set the PKG_CONFIG environment variable to the full
-path to pkg-config.
-
-_PKG_TEXT
-
-To get pkg-config, see <http://pkg-config.freedesktop.org/>.])[]dnl
- ])
-else
- $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS
- $1[]_LIBS=$pkg_cv_[]$1[]_LIBS
- AC_MSG_RESULT([yes])
- $3
-fi[]dnl
-])# PKG_CHECK_MODULES
-
-
-# PKG_INSTALLDIR(DIRECTORY)
-# -------------------------
-# Substitutes the variable pkgconfigdir as the location where a module
-# should install pkg-config .pc files. By default the directory is
-# $libdir/pkgconfig, but the default can be changed by passing
-# DIRECTORY. The user can override through the --with-pkgconfigdir
-# parameter.
-AC_DEFUN([PKG_INSTALLDIR],
-[m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])])
-m4_pushdef([pkg_description],
- [pkg-config installation directory @<:@]pkg_default[@:>@])
-AC_ARG_WITH([pkgconfigdir],
- [AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],,
- [with_pkgconfigdir=]pkg_default)
-AC_SUBST([pkgconfigdir], [$with_pkgconfigdir])
-m4_popdef([pkg_default])
-m4_popdef([pkg_description])
-]) dnl PKG_INSTALLDIR
-
-
-# PKG_NOARCH_INSTALLDIR(DIRECTORY)
-# -------------------------
-# Substitutes the variable noarch_pkgconfigdir as the location where a
-# module should install arch-independent pkg-config .pc files. By
-# default the directory is $datadir/pkgconfig, but the default can be
-# changed by passing DIRECTORY. The user can override through the
-# --with-noarch-pkgconfigdir parameter.
-AC_DEFUN([PKG_NOARCH_INSTALLDIR],
-[m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])])
-m4_pushdef([pkg_description],
- [pkg-config arch-independent installation directory @<:@]pkg_default[@:>@])
-AC_ARG_WITH([noarch-pkgconfigdir],
- [AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],,
- [with_noarch_pkgconfigdir=]pkg_default)
-AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir])
-m4_popdef([pkg_default])
-m4_popdef([pkg_description])
-]) dnl PKG_NOARCH_INSTALLDIR
-
-
-# PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE,
-# [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
-# -------------------------------------------
-# Retrieves the value of the pkg-config variable for the given module.
-AC_DEFUN([PKG_CHECK_VAR],
-[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
-AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl
-
-_PKG_CONFIG([$1], [variable="][$3]["], [$2])
-AS_VAR_COPY([$1], [pkg_cv_][$1])
-
-AS_VAR_IF([$1], [""], [$5], [$4])dnl
-])# PKG_CHECK_VAR
diff --git a/qa/rpc-tests/README.md b/qa/rpc-tests/README.md
index 3e916a7688..02170d13ec 100644
--- a/qa/rpc-tests/README.md
+++ b/qa/rpc-tests/README.md
@@ -12,7 +12,7 @@ Base class for new regression tests.
### [listtransactions.py](listtransactions.py)
Tests for the listtransactions RPC call.
-### [util.py](util.sh)
+### [util.py](util.py)
Generally useful functions.
Bash-based tests, to be ported to Python:
diff --git a/qa/rpc-tests/bipdersig.py b/qa/rpc-tests/bipdersig.py
new file mode 100755
index 0000000000..9f2cc84601
--- /dev/null
+++ b/qa/rpc-tests/bipdersig.py
@@ -0,0 +1,90 @@
+#!/usr/bin/env python2
+# Copyright (c) 2014 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 the BIP66 changeover logic
+#
+
+from test_framework import BitcoinTestFramework
+from bitcoinrpc.authproxy import AuthServiceProxy, JSONRPCException
+from util import *
+import os
+import shutil
+
+class BIP66Test(BitcoinTestFramework):
+
+ def setup_network(self):
+ self.nodes = []
+ self.nodes.append(start_node(0, self.options.tmpdir, []))
+ self.nodes.append(start_node(1, self.options.tmpdir, ["-blockversion=2"]))
+ self.nodes.append(start_node(2, self.options.tmpdir, ["-blockversion=3"]))
+ connect_nodes(self.nodes[1], 0)
+ connect_nodes(self.nodes[2], 0)
+ self.is_network_split = False
+ self.sync_all()
+
+ def run_test(self):
+ cnt = self.nodes[0].getblockcount()
+
+ # Mine some old-version blocks
+ self.nodes[1].setgenerate(True, 100)
+ self.sync_all()
+ if (self.nodes[0].getblockcount() != cnt + 100):
+ raise AssertionError("Failed to mine 100 version=2 blocks")
+
+ # Mine 750 new-version blocks
+ for i in xrange(15):
+ self.nodes[2].setgenerate(True, 50)
+ self.sync_all()
+ if (self.nodes[0].getblockcount() != cnt + 850):
+ raise AssertionError("Failed to mine 750 version=3 blocks")
+
+ # TODO: check that new DERSIG rules are not enforced
+
+ # Mine 1 new-version block
+ self.nodes[2].setgenerate(True, 1)
+ self.sync_all()
+ if (self.nodes[0].getblockcount() != cnt + 851):
+ raise AssertionFailure("Failed to mine a version=3 blocks")
+
+ # TODO: check that new DERSIG rules are enforced
+
+ # Mine 198 new-version blocks
+ for i in xrange(2):
+ self.nodes[2].setgenerate(True, 99)
+ self.sync_all()
+ if (self.nodes[0].getblockcount() != cnt + 1049):
+ raise AssertionError("Failed to mine 198 version=3 blocks")
+
+ # Mine 1 old-version block
+ self.nodes[1].setgenerate(True, 1)
+ self.sync_all()
+ if (self.nodes[0].getblockcount() != cnt + 1050):
+ raise AssertionError("Failed to mine a version=2 block after 949 version=3 blocks")
+
+ # Mine 1 new-version blocks
+ self.nodes[2].setgenerate(True, 1)
+ self.sync_all()
+ if (self.nodes[0].getblockcount() != cnt + 1051):
+ raise AssertionError("Failed to mine a version=3 block")
+
+ # Mine 1 old-version blocks
+ try:
+ self.nodes[1].setgenerate(True, 1)
+ raise AssertionError("Succeeded to mine a version=2 block after 950 version=3 blocks")
+ except JSONRPCException:
+ pass
+ self.sync_all()
+ if (self.nodes[0].getblockcount() != cnt + 1051):
+ raise AssertionError("Accepted a version=2 block after 950 version=3 blocks")
+
+ # Mine 1 new-version blocks
+ self.nodes[2].setgenerate(True, 1)
+ self.sync_all()
+ if (self.nodes[0].getblockcount() != cnt + 1052):
+ raise AssertionError("Failed to mine a version=3 block")
+
+if __name__ == '__main__':
+ BIP66Test().main()
diff --git a/qa/rpc-tests/getblocktemplate_proposals.py b/qa/rpc-tests/getblocktemplate_proposals.py
index 22fe2ce044..f65162002d 100755
--- a/qa/rpc-tests/getblocktemplate_proposals.py
+++ b/qa/rpc-tests/getblocktemplate_proposals.py
@@ -95,6 +95,7 @@ class GetBlockTemplateProposalTest(BitcoinTestFramework):
def run_test(self):
node = self.nodes[0]
+ node.setgenerate(True, 1) # Mine a block to leave initial block download
tmpl = node.getblocktemplate()
if 'coinbasetxn' not in tmpl:
rawcoinbase = encodeUNum(tmpl['height'])
diff --git a/qa/rpc-tests/httpbasics.py b/qa/rpc-tests/httpbasics.py
index 85e85e7f0f..24533741e5 100755
--- a/qa/rpc-tests/httpbasics.py
+++ b/qa/rpc-tests/httpbasics.py
@@ -21,6 +21,9 @@ except ImportError:
import urlparse
class HTTPBasicsTest (BitcoinTestFramework):
+ def setup_nodes(self):
+ return start_nodes(4, self.options.tmpdir, extra_args=[['-rpckeepalive=1'], ['-rpckeepalive=0'], [], []])
+
def run_test(self):
#################################################
@@ -32,13 +35,13 @@ class HTTPBasicsTest (BitcoinTestFramework):
conn = httplib.HTTPConnection(url.hostname, url.port)
conn.connect()
- conn.request('GET', '/', '{"method": "getbestblockhash"}', headers)
+ conn.request('POST', '/', '{"method": "getbestblockhash"}', headers)
out1 = conn.getresponse().read();
assert_equal('"error":null' in out1, True)
assert_equal(conn.sock!=None, True) #according to http/1.1 connection must still be open!
#send 2nd request without closing connection
- conn.request('GET', '/', '{"method": "getchaintips"}', headers)
+ conn.request('POST', '/', '{"method": "getchaintips"}', headers)
out2 = conn.getresponse().read();
assert_equal('"error":null' in out1, True) #must also response with a correct json-rpc message
assert_equal(conn.sock!=None, True) #according to http/1.1 connection must still be open!
@@ -49,13 +52,13 @@ class HTTPBasicsTest (BitcoinTestFramework):
conn = httplib.HTTPConnection(url.hostname, url.port)
conn.connect()
- conn.request('GET', '/', '{"method": "getbestblockhash"}', headers)
+ conn.request('POST', '/', '{"method": "getbestblockhash"}', headers)
out1 = conn.getresponse().read();
assert_equal('"error":null' in out1, True)
assert_equal(conn.sock!=None, True) #according to http/1.1 connection must still be open!
#send 2nd request without closing connection
- conn.request('GET', '/', '{"method": "getchaintips"}', headers)
+ conn.request('POST', '/', '{"method": "getchaintips"}', headers)
out2 = conn.getresponse().read();
assert_equal('"error":null' in out1, True) #must also response with a correct json-rpc message
assert_equal(conn.sock!=None, True) #according to http/1.1 connection must still be open!
@@ -66,11 +69,34 @@ class HTTPBasicsTest (BitcoinTestFramework):
conn = httplib.HTTPConnection(url.hostname, url.port)
conn.connect()
- conn.request('GET', '/', '{"method": "getbestblockhash"}', headers)
+ conn.request('POST', '/', '{"method": "getbestblockhash"}', headers)
out1 = conn.getresponse().read();
assert_equal('"error":null' in out1, True)
assert_equal(conn.sock!=None, False) #now the connection must be closed after the response
+ #node1 (2nd node) is running with disabled keep-alive option
+ urlNode1 = urlparse.urlparse(self.nodes[1].url)
+ authpair = urlNode1.username + ':' + urlNode1.password
+ headers = {"Authorization": "Basic " + base64.b64encode(authpair)}
+
+ conn = httplib.HTTPConnection(urlNode1.hostname, urlNode1.port)
+ conn.connect()
+ conn.request('POST', '/', '{"method": "getbestblockhash"}', headers)
+ out1 = conn.getresponse().read();
+ assert_equal('"error":null' in out1, True)
+ assert_equal(conn.sock!=None, False) #connection must be closed because keep-alive was set to false
+
+ #node2 (third node) is running with standard keep-alive parameters which means keep-alive is off
+ urlNode2 = urlparse.urlparse(self.nodes[2].url)
+ authpair = urlNode2.username + ':' + urlNode2.password
+ headers = {"Authorization": "Basic " + base64.b64encode(authpair)}
+
+ conn = httplib.HTTPConnection(urlNode2.hostname, urlNode2.port)
+ conn.connect()
+ conn.request('POST', '/', '{"method": "getbestblockhash"}', headers)
+ out1 = conn.getresponse().read();
+ assert_equal('"error":null' in out1, True)
+ assert_equal(conn.sock!=None, True) #connection must be closed because bitcoind should use keep-alive by default
if __name__ == '__main__':
HTTPBasicsTest ().main ()
diff --git a/qa/rpc-tests/test_framework.py b/qa/rpc-tests/test_framework.py
index 6c4ec073c2..4c8a11b821 100755
--- a/qa/rpc-tests/test_framework.py
+++ b/qa/rpc-tests/test_framework.py
@@ -33,8 +33,11 @@ class BitcoinTestFramework(object):
print("Initializing test directory "+self.options.tmpdir)
initialize_chain(self.options.tmpdir)
+ def setup_nodes(self):
+ return start_nodes(4, self.options.tmpdir)
+
def setup_network(self, split = False):
- self.nodes = start_nodes(4, self.options.tmpdir)
+ self.nodes = self.setup_nodes()
# Connect the nodes as a "chain". This allows us
# to split the network between nodes 1 and 2 to get
diff --git a/qa/rpc-tests/wallet.py b/qa/rpc-tests/wallet.py
index f280ac380e..3e63493dc6 100755
--- a/qa/rpc-tests/wallet.py
+++ b/qa/rpc-tests/wallet.py
@@ -61,7 +61,7 @@ class WalletTest (BitcoinTestFramework):
walletinfo = self.nodes[0].getwalletinfo()
assert_equal(walletinfo['immature_balance'], 0)
- # Have node0 mine a block, thus he will collect his own fee.
+ # Have node0 mine a block, thus they will collect their own fee.
self.nodes[0].setgenerate(True, 1)
self.sync_all()
diff --git a/src/Makefile.am b/src/Makefile.am
index 1f9a1621a7..009c3c5196 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -209,14 +209,12 @@ crypto_libbitcoin_crypto_a_SOURCES = \
crypto/sha256.cpp \
crypto/sha512.cpp \
crypto/hmac_sha256.cpp \
- crypto/rfc6979_hmac_sha256.cpp \
crypto/hmac_sha512.cpp \
crypto/ripemd160.cpp \
crypto/common.h \
crypto/sha256.h \
crypto/sha512.h \
crypto/hmac_sha256.h \
- crypto/rfc6979_hmac_sha256.h \
crypto/hmac_sha512.h \
crypto/sha1.h \
crypto/ripemd160.h
@@ -293,6 +291,14 @@ nodist_libbitcoin_util_a_SOURCES = $(srcdir)/obj/build.h
#
# bitcoind binary #
+bitcoind_SOURCES = bitcoind.cpp
+bitcoind_CPPFLAGS = $(BITCOIN_INCLUDES)
+bitcoind_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+
+if TARGET_WINDOWS
+bitcoind_SOURCES += bitcoind-res.rc
+endif
+
bitcoind_LDADD = \
$(LIBBITCOIN_SERVER) \
$(LIBBITCOIN_COMMON) \
@@ -306,51 +312,43 @@ bitcoind_LDADD = \
if ENABLE_WALLET
bitcoind_LDADD += libbitcoin_wallet.a
endif
-bitcoind_SOURCES = bitcoind.cpp
+
+bitcoind_LDADD += $(BOOST_LIBS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS)
#
+# bitcoin-cli binary #
+bitcoin_cli_SOURCES = bitcoin-cli.cpp
+bitcoin_cli_CPPFLAGS = $(BITCOIN_INCLUDES)
+bitcoin_cli_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+
if TARGET_WINDOWS
-bitcoind_SOURCES += bitcoind-res.rc
+bitcoin_cli_SOURCES += bitcoin-cli-res.rc
endif
-bitcoind_LDADD += $(BOOST_LIBS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS)
-bitcoind_CPPFLAGS = $(BITCOIN_INCLUDES)
-bitcoind_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
-
-# bitcoin-cli binary #
bitcoin_cli_LDADD = \
$(LIBBITCOIN_CLI) \
$(LIBBITCOIN_UTIL) \
- $(BOOST_LIBS) \
- $(SSL_LIBS) \
- $(CRYPTO_LIBS)
-
-bitcoin_cli_SOURCES = \
- bitcoin-cli.cpp
+ $(LIBSECP256K1)
-bitcoin_cli_CPPFLAGS = $(BITCOIN_INCLUDES)
+bitcoin_cli_LDADD += $(BOOST_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS)
#
# bitcoin-tx binary #
+bitcoin_tx_SOURCES = bitcoin-tx.cpp
+bitcoin_tx_CPPFLAGS = $(BITCOIN_INCLUDES)
+bitcoin_tx_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+
bitcoin_tx_LDADD = \
$(LIBBITCOIN_UNIVALUE) \
$(LIBBITCOIN_COMMON) \
$(LIBBITCOIN_UTIL) \
$(LIBBITCOIN_CRYPTO) \
- $(LIBSECP256K1) \
- $(BOOST_LIBS) \
- $(CRYPTO_LIBS)
+ $(LIBSECP256K1)
-bitcoin_tx_SOURCES = bitcoin-tx.cpp
-bitcoin_tx_CPPFLAGS = $(BITCOIN_INCLUDES)
+bitcoin_tx_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS)
#
-bitcoin_tx_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
-
-if TARGET_WINDOWS
-bitcoin_cli_SOURCES += bitcoin-cli-res.rc
-endif
-bitcoin_cli_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+# bitcoinconsensus library #
if BUILD_BITCOIN_LIBS
include_HEADERS = script/bitcoinconsensus.h
libbitcoinconsensus_la_SOURCES = \
@@ -378,10 +376,12 @@ endif
libbitcoinconsensus_la_LDFLAGS = -no-undefined $(RELDFLAGS)
libbitcoinconsensus_la_LIBADD = $(CRYPTO_LIBS)
libbitcoinconsensus_la_CPPFLAGS = $(CRYPTO_CFLAGS) -I$(builddir)/obj -DBUILD_BITCOIN_INTERNAL
+
if USE_LIBSECP256K1
libbitcoinconsensus_la_LIBADD += secp256k1/libsecp256k1.la
endif
endif
+#
CLEANFILES = leveldb/libleveldb.a leveldb/libmemenv.a *.gcda *.gcno
diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include
index cdd8f8d08d..31fe3a9f69 100644
--- a/src/Makefile.qt.include
+++ b/src/Makefile.qt.include
@@ -314,8 +314,7 @@ BITCOIN_QT_CPP += \
qt/walletview.cpp
endif
-RES_IMAGES = \
- qt/res/images/about.png
+RES_IMAGES =
RES_MOVIES = $(wildcard qt/res/movies/spinner-*.png)
diff --git a/src/Makefile.test.include b/src/Makefile.test.include
index 710956a72b..90494439fa 100644
--- a/src/Makefile.test.include
+++ b/src/Makefile.test.include
@@ -20,8 +20,6 @@ EXTRA_DIST += \
JSON_TEST_FILES = \
test/data/script_valid.json \
test/data/base58_keys_valid.json \
- test/data/sig_canonical.json \
- test/data/sig_noncanonical.json \
test/data/base58_encode_decode.json \
test/data/base58_keys_invalid.json \
test/data/script_invalid.json \
diff --git a/src/alert.cpp b/src/alert.cpp
index 370d0cecc6..323939913b 100644
--- a/src/alert.cpp
+++ b/src/alert.cpp
@@ -149,7 +149,7 @@ bool CAlert::CheckSignature() const
{
CPubKey key(Params().AlertKey());
if (!key.Verify(Hash(vchMsg.begin(), vchMsg.end()), vchSig))
- return error("CAlert::CheckSignature() : verify signature failed");
+ return error("CAlert::CheckSignature(): verify signature failed");
// Now unserialize the data
CDataStream sMsg(vchMsg, SER_NETWORK, PROTOCOL_VERSION);
diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp
index 01ace1e2b2..c1622cf5d3 100644
--- a/src/bitcoin-tx.cpp
+++ b/src/bitcoin-tx.cpp
@@ -436,7 +436,7 @@ static void MutateTxSign(CMutableTransaction& tx, const string& flagStr)
BOOST_FOREACH(const CTransaction& txv, txVariants) {
txin.scriptSig = CombineSignatures(prevPubKey, mergedTx, i, txin.scriptSig, txv.vin[i].scriptSig);
}
- if (!VerifyScript(txin.scriptSig, prevPubKey, STANDARD_SCRIPT_VERIFY_FLAGS, SignatureChecker(mergedTx, i)))
+ if (!VerifyScript(txin.scriptSig, prevPubKey, STANDARD_SCRIPT_VERIFY_FLAGS, MutableTransactionSignatureChecker(&mergedTx, i)))
fComplete = false;
}
diff --git a/src/chainparams.cpp b/src/chainparams.cpp
index d32d96c56b..1fd3b01681 100644
--- a/src/chainparams.cpp
+++ b/src/chainparams.cpp
@@ -156,11 +156,11 @@ public:
vSeeds.push_back(CDNSSeedData("bitcoinstats.com", "seed.bitcoinstats.com"));
vSeeds.push_back(CDNSSeedData("xf2.org", "bitseed.xf2.org"));
- base58Prefixes[PUBKEY_ADDRESS] = boost::assign::list_of(0);
- base58Prefixes[SCRIPT_ADDRESS] = boost::assign::list_of(5);
- base58Prefixes[SECRET_KEY] = boost::assign::list_of(128);
- base58Prefixes[EXT_PUBLIC_KEY] = boost::assign::list_of(0x04)(0x88)(0xB2)(0x1E);
- base58Prefixes[EXT_SECRET_KEY] = boost::assign::list_of(0x04)(0x88)(0xAD)(0xE4);
+ base58Prefixes[PUBKEY_ADDRESS] = std::vector<unsigned char>(1,0);
+ base58Prefixes[SCRIPT_ADDRESS] = std::vector<unsigned char>(1,5);
+ base58Prefixes[SECRET_KEY] = std::vector<unsigned char>(1,128);
+ base58Prefixes[EXT_PUBLIC_KEY] = boost::assign::list_of(0x04)(0x88)(0xB2)(0x1E).convert_to_container<std::vector<unsigned char> >();
+ base58Prefixes[EXT_SECRET_KEY] = boost::assign::list_of(0x04)(0x88)(0xAD)(0xE4).convert_to_container<std::vector<unsigned char> >();
convertSeed6(vFixedSeeds, pnSeed6_main, ARRAYLEN(pnSeed6_main));
@@ -214,11 +214,11 @@ public:
vSeeds.push_back(CDNSSeedData("bluematt.me", "testnet-seed.bluematt.me"));
vSeeds.push_back(CDNSSeedData("bitcoin.schildbach.de", "testnet-seed.bitcoin.schildbach.de"));
- base58Prefixes[PUBKEY_ADDRESS] = boost::assign::list_of(111);
- base58Prefixes[SCRIPT_ADDRESS] = boost::assign::list_of(196);
- base58Prefixes[SECRET_KEY] = boost::assign::list_of(239);
- base58Prefixes[EXT_PUBLIC_KEY] = boost::assign::list_of(0x04)(0x35)(0x87)(0xCF);
- base58Prefixes[EXT_SECRET_KEY] = boost::assign::list_of(0x04)(0x35)(0x83)(0x94);
+ base58Prefixes[PUBKEY_ADDRESS] = std::vector<unsigned char>(1,111);
+ base58Prefixes[SCRIPT_ADDRESS] = std::vector<unsigned char>(1,196);
+ base58Prefixes[SECRET_KEY] = std::vector<unsigned char>(1,239);
+ base58Prefixes[EXT_PUBLIC_KEY] = boost::assign::list_of(0x04)(0x35)(0x87)(0xCF).convert_to_container<std::vector<unsigned char> >();
+ base58Prefixes[EXT_SECRET_KEY] = boost::assign::list_of(0x04)(0x35)(0x83)(0x94).convert_to_container<std::vector<unsigned char> >();
convertSeed6(vFixedSeeds, pnSeed6_test, ARRAYLEN(pnSeed6_test));
diff --git a/src/checkqueue.h b/src/checkqueue.h
index b8e2a17c76..6f6b97e3a7 100644
--- a/src/checkqueue.h
+++ b/src/checkqueue.h
@@ -81,7 +81,7 @@ private:
fAllOk &= fOk;
nTodo -= nNow;
if (nTodo == 0 && !fMaster)
- // We processed the last element; inform the master he can exit and return the result
+ // We processed the last element; inform the master he or she can exit and return the result
condMaster.notify_one();
} else {
// first iteration
@@ -161,7 +161,12 @@ public:
{
}
- friend class CCheckQueueControl<T>;
+ bool IsIdle()
+ {
+ boost::unique_lock<boost::mutex> lock(mutex);
+ return (nTotal == nIdle && nTodo == 0 && fAllOk == true);
+ }
+
};
/**
@@ -180,9 +185,8 @@ public:
{
// passed queue is supposed to be unused, or NULL
if (pqueue != NULL) {
- assert(pqueue->nTotal == pqueue->nIdle);
- assert(pqueue->nTodo == 0);
- assert(pqueue->fAllOk == true);
+ bool isIdle = pqueue->IsIdle();
+ assert(isIdle);
}
}
diff --git a/src/crypter.cpp b/src/crypter.cpp
index 00f7f7f1bd..75d84dbf13 100644
--- a/src/crypter.cpp
+++ b/src/crypter.cpp
@@ -102,7 +102,7 @@ bool CCrypter::Decrypt(const std::vector<unsigned char>& vchCiphertext, CKeyingM
}
-bool EncryptSecret(const CKeyingMaterial& vMasterKey, const CKeyingMaterial &vchPlaintext, const uint256& nIV, std::vector<unsigned char> &vchCiphertext)
+static bool EncryptSecret(const CKeyingMaterial& vMasterKey, const CKeyingMaterial &vchPlaintext, const uint256& nIV, std::vector<unsigned char> &vchCiphertext)
{
CCrypter cKeyCrypter;
std::vector<unsigned char> chIV(WALLET_CRYPTO_KEY_SIZE);
@@ -112,7 +112,7 @@ bool EncryptSecret(const CKeyingMaterial& vMasterKey, const CKeyingMaterial &vch
return cKeyCrypter.Encrypt(*((const CKeyingMaterial*)&vchPlaintext), vchCiphertext);
}
-bool DecryptSecret(const CKeyingMaterial& vMasterKey, const std::vector<unsigned char>& vchCiphertext, const uint256& nIV, CKeyingMaterial& vchPlaintext)
+static bool DecryptSecret(const CKeyingMaterial& vMasterKey, const std::vector<unsigned char>& vchCiphertext, const uint256& nIV, CKeyingMaterial& vchPlaintext)
{
CCrypter cKeyCrypter;
std::vector<unsigned char> chIV(WALLET_CRYPTO_KEY_SIZE);
@@ -122,6 +122,19 @@ bool DecryptSecret(const CKeyingMaterial& vMasterKey, const std::vector<unsigned
return cKeyCrypter.Decrypt(vchCiphertext, *((CKeyingMaterial*)&vchPlaintext));
}
+static bool DecryptKey(const CKeyingMaterial& vMasterKey, const std::vector<unsigned char>& vchCryptedSecret, const CPubKey& vchPubKey, CKey& key)
+{
+ CKeyingMaterial vchSecret;
+ if(!DecryptSecret(vMasterKey, vchCryptedSecret, vchPubKey.GetHash(), vchSecret))
+ return false;
+
+ if (vchSecret.size() != 32)
+ return false;
+
+ key.Set(vchSecret.begin(), vchSecret.end(), vchPubKey.IsCompressed());
+ return key.VerifyPubKey(vchPubKey);
+}
+
bool CCryptoKeyStore::SetCrypted()
{
LOCK(cs_KeyStore);
@@ -161,20 +174,8 @@ bool CCryptoKeyStore::Unlock(const CKeyingMaterial& vMasterKeyIn)
{
const CPubKey &vchPubKey = (*mi).second.first;
const std::vector<unsigned char> &vchCryptedSecret = (*mi).second.second;
- CKeyingMaterial vchSecret;
- if(!DecryptSecret(vMasterKeyIn, vchCryptedSecret, vchPubKey.GetHash(), vchSecret))
- {
- keyFail = true;
- break;
- }
- if (vchSecret.size() != 32)
- {
- keyFail = true;
- break;
- }
CKey key;
- key.Set(vchSecret.begin(), vchSecret.end(), vchPubKey.IsCompressed());
- if (key.GetPubKey() != vchPubKey)
+ if (!DecryptKey(vMasterKeyIn, vchCryptedSecret, vchPubKey, key))
{
keyFail = true;
break;
@@ -243,13 +244,7 @@ bool CCryptoKeyStore::GetKey(const CKeyID &address, CKey& keyOut) const
{
const CPubKey &vchPubKey = (*mi).second.first;
const std::vector<unsigned char> &vchCryptedSecret = (*mi).second.second;
- CKeyingMaterial vchSecret;
- if (!DecryptSecret(vMasterKey, vchCryptedSecret, vchPubKey.GetHash(), vchSecret))
- return false;
- if (vchSecret.size() != 32)
- return false;
- keyOut.Set(vchSecret.begin(), vchSecret.end(), vchPubKey.IsCompressed());
- return true;
+ return DecryptKey(vMasterKey, vchCryptedSecret, vchPubKey, keyOut);
}
}
return false;
diff --git a/src/crypter.h b/src/crypter.h
index 7b4c2f2613..cbaf1562f0 100644
--- a/src/crypter.h
+++ b/src/crypter.h
@@ -107,9 +107,6 @@ public:
}
};
-bool EncryptSecret(const CKeyingMaterial& vMasterKey, const CKeyingMaterial &vchPlaintext, const uint256& nIV, std::vector<unsigned char> &vchCiphertext);
-bool DecryptSecret(const CKeyingMaterial& vMasterKey, const std::vector<unsigned char>& vchCiphertext, const uint256& nIV, CKeyingMaterial& vchPlaintext);
-
/** Keystore which keeps the private keys encrypted.
* It derives from the basic key store, which is used if no encryption is active.
*/
diff --git a/src/crypto/rfc6979_hmac_sha256.cpp b/src/crypto/rfc6979_hmac_sha256.cpp
deleted file mode 100644
index a8c971c3ba..0000000000
--- a/src/crypto/rfc6979_hmac_sha256.cpp
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright (c) 2014 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 "crypto/rfc6979_hmac_sha256.h"
-
-#include <string.h>
-
-#include <algorithm>
-
-static const unsigned char zero[1] = {0x00};
-static const unsigned char one[1] = {0x01};
-
-RFC6979_HMAC_SHA256::RFC6979_HMAC_SHA256(const unsigned char* key, size_t keylen, const unsigned char* msg, size_t msglen) : retry(false)
-{
- memset(V, 0x01, sizeof(V));
- memset(K, 0x00, sizeof(K));
-
- CHMAC_SHA256(K, sizeof(K)).Write(V, sizeof(V)).Write(zero, sizeof(zero)).Write(key, keylen).Write(msg, msglen).Finalize(K);
- CHMAC_SHA256(K, sizeof(K)).Write(V, sizeof(V)).Finalize(V);
- CHMAC_SHA256(K, sizeof(K)).Write(V, sizeof(V)).Write(one, sizeof(one)).Write(key, keylen).Write(msg, msglen).Finalize(K);
- CHMAC_SHA256(K, sizeof(K)).Write(V, sizeof(V)).Finalize(V);
-}
-
-RFC6979_HMAC_SHA256::~RFC6979_HMAC_SHA256()
-{
- memset(V, 0x01, sizeof(V));
- memset(K, 0x00, sizeof(K));
-}
-
-void RFC6979_HMAC_SHA256::Generate(unsigned char* output, size_t outputlen)
-{
- if (retry) {
- CHMAC_SHA256(K, sizeof(K)).Write(V, sizeof(V)).Write(zero, sizeof(zero)).Finalize(K);
- CHMAC_SHA256(K, sizeof(K)).Write(V, sizeof(V)).Finalize(V);
- }
-
- while (outputlen > 0) {
- CHMAC_SHA256(K, sizeof(K)).Write(V, sizeof(V)).Finalize(V);
- size_t len = std::min(outputlen, sizeof(V));
- memcpy(output, V, len);
- output += len;
- outputlen -= len;
- }
-
- retry = true;
-}
diff --git a/src/crypto/rfc6979_hmac_sha256.h b/src/crypto/rfc6979_hmac_sha256.h
deleted file mode 100644
index f3a54a5d11..0000000000
--- a/src/crypto/rfc6979_hmac_sha256.h
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright (c) 2014 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_RFC6979_HMAC_SHA256_H
-#define BITCOIN_RFC6979_HMAC_SHA256_H
-
-#include "crypto/hmac_sha256.h"
-
-#include <stdint.h>
-#include <stdlib.h>
-
-/** The RFC 6979 PRNG using HMAC-SHA256. */
-class RFC6979_HMAC_SHA256
-{
-private:
- unsigned char V[CHMAC_SHA256::OUTPUT_SIZE];
- unsigned char K[CHMAC_SHA256::OUTPUT_SIZE];
- bool retry;
-
-public:
- /**
- * Construct a new RFC6979 PRNG, using the given key and message.
- * The message is assumed to be already hashed.
- */
- RFC6979_HMAC_SHA256(const unsigned char* key, size_t keylen, const unsigned char* msg, size_t msglen);
-
- /**
- * Generate a byte array.
- */
- void Generate(unsigned char* output, size_t outputlen);
-
- ~RFC6979_HMAC_SHA256();
-};
-
-#endif // BITCOIN_RFC6979_HMAC_SHA256_H
diff --git a/src/db.cpp b/src/db.cpp
index fcc177f1cc..a7f885135b 100644
--- a/src/db.cpp
+++ b/src/db.cpp
@@ -43,7 +43,7 @@ void CDBEnv::EnvShutdown()
fDbEnvInit = false;
int ret = dbenv.close(0);
if (ret != 0)
- LogPrintf("CDBEnv::EnvShutdown : Error %d shutting down database environment: %s\n", ret, DbEnv::strerror(ret));
+ LogPrintf("CDBEnv::EnvShutdown: Error %d shutting down database environment: %s\n", ret, DbEnv::strerror(ret));
if (!fMockDb)
DbEnv(0).remove(path.string().c_str(), 0);
}
@@ -75,7 +75,7 @@ bool CDBEnv::Open(const boost::filesystem::path& pathIn)
boost::filesystem::path pathLogDir = path / "database";
TryCreateDirectory(pathLogDir);
boost::filesystem::path pathErrorFile = path / "db.log";
- LogPrintf("CDBEnv::Open : LogDir=%s ErrorFile=%s\n", pathLogDir.string(), pathErrorFile.string());
+ LogPrintf("CDBEnv::Open: LogDir=%s ErrorFile=%s\n", pathLogDir.string(), pathErrorFile.string());
unsigned int nEnvFlags = 0;
if (GetBoolArg("-privdb", true))
@@ -102,7 +102,7 @@ bool CDBEnv::Open(const boost::filesystem::path& pathIn)
nEnvFlags,
S_IRUSR | S_IWUSR);
if (ret != 0)
- return error("CDBEnv::Open : Error %d opening database environment: %s\n", ret, DbEnv::strerror(ret));
+ return error("CDBEnv::Open: Error %d opening database environment: %s\n", ret, DbEnv::strerror(ret));
fDbEnvInit = true;
fMockDb = false;
@@ -112,7 +112,7 @@ bool CDBEnv::Open(const boost::filesystem::path& pathIn)
void CDBEnv::MakeMock()
{
if (fDbEnvInit)
- throw runtime_error("CDBEnv::MakeMock : Already initialized");
+ throw runtime_error("CDBEnv::MakeMock: Already initialized");
boost::this_thread::interruption_point();
@@ -135,7 +135,7 @@ void CDBEnv::MakeMock()
DB_PRIVATE,
S_IRUSR | S_IWUSR);
if (ret > 0)
- throw runtime_error(strprintf("CDBEnv::MakeMock : Error %d opening database environment.", ret));
+ throw runtime_error(strprintf("CDBEnv::MakeMock: Error %d opening database environment.", ret));
fDbEnvInit = true;
fMockDb = true;
@@ -172,14 +172,14 @@ bool CDBEnv::Salvage(std::string strFile, bool fAggressive, std::vector<CDBEnv::
Db db(&dbenv, 0);
int result = db.verify(strFile.c_str(), NULL, &strDump, flags);
if (result == DB_VERIFY_BAD) {
- LogPrintf("CDBEnv::Salvage : Database salvage found errors, all data may not be recoverable.\n");
+ LogPrintf("CDBEnv::Salvage: Database salvage found errors, all data may not be recoverable.\n");
if (!fAggressive) {
- LogPrintf("CDBEnv::Salvage : Rerun with aggressive mode to ignore errors and continue.\n");
+ LogPrintf("CDBEnv::Salvage: Rerun with aggressive mode to ignore errors and continue.\n");
return false;
}
}
if (result != 0 && result != DB_VERIFY_BAD) {
- LogPrintf("CDBEnv::Salvage : Database salvage failed with result %d.\n", result);
+ LogPrintf("CDBEnv::Salvage: Database salvage failed with result %d.\n", result);
return false;
}
@@ -217,10 +217,11 @@ void CDBEnv::CheckpointLSN(const std::string& strFile)
}
-CDB::CDB(const std::string& strFilename, const char* pszMode) : pdb(NULL), activeTxn(NULL)
+CDB::CDB(const std::string& strFilename, const char* pszMode, bool fFlushOnCloseIn) : pdb(NULL), activeTxn(NULL)
{
int ret;
fReadOnly = (!strchr(pszMode, '+') && !strchr(pszMode, 'w'));
+ fFlushOnClose = fFlushOnCloseIn;
if (strFilename.empty())
return;
@@ -232,7 +233,7 @@ CDB::CDB(const std::string& strFilename, const char* pszMode) : pdb(NULL), activ
{
LOCK(bitdb.cs_db);
if (!bitdb.Open(GetDataDir()))
- throw runtime_error("CDB : Failed to open database environment.");
+ throw runtime_error("CDB: Failed to open database environment.");
strFile = strFilename;
++bitdb.mapFileUseCount[strFile];
@@ -245,7 +246,7 @@ CDB::CDB(const std::string& strFilename, const char* pszMode) : pdb(NULL), activ
DbMpoolFile* mpf = pdb->get_mpf();
ret = mpf->set_flags(DB_MPOOL_NOFILE, 1);
if (ret != 0)
- throw runtime_error(strprintf("CDB : Failed to configure for no temp file backing for database %s", strFile));
+ throw runtime_error(strprintf("CDB: Failed to configure for no temp file backing for database %s", strFile));
}
ret = pdb->open(NULL, // Txn pointer
@@ -260,7 +261,7 @@ CDB::CDB(const std::string& strFilename, const char* pszMode) : pdb(NULL), activ
pdb = NULL;
--bitdb.mapFileUseCount[strFile];
strFile = "";
- throw runtime_error(strprintf("CDB : Error %d, can't open database %s", ret, strFile));
+ throw runtime_error(strprintf("CDB: Error %d, can't open database %s", ret, strFile));
}
if (fCreate && !Exists(string("version"))) {
@@ -297,7 +298,8 @@ void CDB::Close()
activeTxn = NULL;
pdb = NULL;
- Flush();
+ if (fFlushOnClose)
+ Flush();
{
LOCK(bitdb.cs_db);
@@ -340,7 +342,7 @@ bool CDB::Rewrite(const string& strFile, const char* pszSkip)
bitdb.mapFileUseCount.erase(strFile);
bool fSuccess = true;
- LogPrintf("CDB::Rewrite : Rewriting %s...\n", strFile);
+ LogPrintf("CDB::Rewrite: Rewriting %s...\n", strFile);
string strFileRes = strFile + ".rewrite";
{ // surround usage of db with extra {}
CDB db(strFile.c_str(), "r");
@@ -353,7 +355,7 @@ bool CDB::Rewrite(const string& strFile, const char* pszSkip)
DB_CREATE, // Flags
0);
if (ret > 0) {
- LogPrintf("CDB::Rewrite : Can't create database file %s\n", strFileRes);
+ LogPrintf("CDB::Rewrite: Can't create database file %s\n", strFileRes);
fSuccess = false;
}
@@ -402,7 +404,7 @@ bool CDB::Rewrite(const string& strFile, const char* pszSkip)
fSuccess = false;
}
if (!fSuccess)
- LogPrintf("CDB::Rewrite : Failed to rewrite database file %s\n", strFileRes);
+ LogPrintf("CDB::Rewrite: Failed to rewrite database file %s\n", strFileRes);
return fSuccess;
}
}
@@ -416,7 +418,7 @@ void CDBEnv::Flush(bool fShutdown)
{
int64_t nStart = GetTimeMillis();
// Flush log data to the actual data file on all files that are not in use
- LogPrint("db", "CDBEnv::Flush : Flush(%s)%s\n", fShutdown ? "true" : "false", fDbEnvInit ? "" : " database not started");
+ LogPrint("db", "CDBEnv::Flush: Flush(%s)%s\n", fShutdown ? "true" : "false", fDbEnvInit ? "" : " database not started");
if (!fDbEnvInit)
return;
{
@@ -425,21 +427,21 @@ void CDBEnv::Flush(bool fShutdown)
while (mi != mapFileUseCount.end()) {
string strFile = (*mi).first;
int nRefCount = (*mi).second;
- LogPrint("db", "CDBEnv::Flush : Flushing %s (refcount = %d)...\n", strFile, nRefCount);
+ LogPrint("db", "CDBEnv::Flush: Flushing %s (refcount = %d)...\n", strFile, nRefCount);
if (nRefCount == 0) {
// Move log data to the dat file
CloseDb(strFile);
- LogPrint("db", "CDBEnv::Flush : %s checkpoint\n", strFile);
+ LogPrint("db", "CDBEnv::Flush: %s checkpoint\n", strFile);
dbenv.txn_checkpoint(0, 0, 0);
- LogPrint("db", "CDBEnv::Flush : %s detach\n", strFile);
+ LogPrint("db", "CDBEnv::Flush: %s detach\n", strFile);
if (!fMockDb)
dbenv.lsn_reset(strFile.c_str(), 0);
- LogPrint("db", "CDBEnv::Flush : %s closed\n", strFile);
+ LogPrint("db", "CDBEnv::Flush: %s closed\n", strFile);
mapFileUseCount.erase(mi++);
} else
mi++;
}
- LogPrint("db", "CDBEnv::Flush : Flush(%s)%s took %15dms\n", fShutdown ? "true" : "false", fDbEnvInit ? "" : " database not started", GetTimeMillis() - nStart);
+ LogPrint("db", "CDBEnv::Flush: Flush(%s)%s took %15dms\n", fShutdown ? "true" : "false", fDbEnvInit ? "" : " database not started", GetTimeMillis() - nStart);
if (fShutdown) {
char** listp;
if (mapFileUseCount.empty()) {
diff --git a/src/db.h b/src/db.h
index 393978633f..d208907c89 100644
--- a/src/db.h
+++ b/src/db.h
@@ -97,8 +97,9 @@ protected:
std::string strFile;
DbTxn* activeTxn;
bool fReadOnly;
+ bool fFlushOnClose;
- explicit CDB(const std::string& strFilename, const char* pszMode = "r+");
+ explicit CDB(const std::string& strFilename, const char* pszMode = "r+", bool fFlushOnCloseIn=true);
~CDB() { Close(); }
public:
diff --git a/src/ecwrapper.cpp b/src/ecwrapper.cpp
index c29390eb98..5e3aec25ba 100644
--- a/src/ecwrapper.cpp
+++ b/src/ecwrapper.cpp
@@ -117,10 +117,34 @@ bool CECKey::SetPubKey(const unsigned char* pubkey, size_t size) {
}
bool CECKey::Verify(const uint256 &hash, const std::vector<unsigned char>& vchSig) {
- // -1 = error, 0 = bad sig, 1 = good
- if (ECDSA_verify(0, (unsigned char*)&hash, sizeof(hash), &vchSig[0], vchSig.size(), pkey) != 1)
+ if (vchSig.empty())
return false;
- return true;
+
+ // New versions of OpenSSL will reject non-canonical DER signatures. de/re-serialize first.
+ unsigned char *norm_der = NULL;
+ ECDSA_SIG *norm_sig = ECDSA_SIG_new();
+ const unsigned char* sigptr = &vchSig[0];
+ assert(norm_sig);
+ if (d2i_ECDSA_SIG(&norm_sig, &sigptr, vchSig.size()) == NULL)
+ {
+ /* As of OpenSSL 1.0.0p d2i_ECDSA_SIG frees and nulls the pointer on
+ * error. But OpenSSL's own use of this function redundantly frees the
+ * result. As ECDSA_SIG_free(NULL) is a no-op, and in the absence of a
+ * clear contract for the function behaving the same way is more
+ * conservative.
+ */
+ ECDSA_SIG_free(norm_sig);
+ return false;
+ }
+ int derlen = i2d_ECDSA_SIG(norm_sig, &norm_der);
+ ECDSA_SIG_free(norm_sig);
+ if (derlen <= 0)
+ return false;
+
+ // -1 = error, 0 = bad sig, 1 = good
+ bool ret = ECDSA_verify(0, (unsigned char*)&hash, sizeof(hash), norm_der, derlen, pkey) == 1;
+ OPENSSL_free(norm_der);
+ return ret;
}
bool CECKey::Recover(const uint256 &hash, const unsigned char *p64, int rec)
diff --git a/src/init.cpp b/src/init.cpp
index 03d67f0aa3..c8f32d8bfd 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -111,7 +111,28 @@ bool ShutdownRequested()
return fRequestShutdown;
}
+class CCoinsViewErrorCatcher : public CCoinsViewBacked
+{
+public:
+ CCoinsViewErrorCatcher(CCoinsView* view) : CCoinsViewBacked(view) {}
+ bool GetCoins(const uint256 &txid, CCoins &coins) const {
+ try {
+ return CCoinsViewBacked::GetCoins(txid, coins);
+ } catch(const std::runtime_error& e) {
+ uiInterface.ThreadSafeMessageBox(_("Error reading from database, shutting down."), "", CClientUIInterface::MSG_ERROR);
+ LogPrintf("Error reading from database: %s\n", e.what());
+ // Starting the shutdown sequence and returning false to the caller would be
+ // interpreted as 'entry not found' (as opposed to unable to read data), and
+ // could lead to invalid interpration. Just exit immediately, as we can't
+ // continue anyway, and all writes should be atomic.
+ abort();
+ }
+ }
+ // Writes do not need similar protection, as failure to write is handled by the caller.
+};
+
static CCoinsViewDB *pcoinsdbview = NULL;
+static CCoinsViewErrorCatcher *pcoinscatcher = NULL;
void Shutdown()
{
@@ -154,6 +175,8 @@ void Shutdown()
}
delete pcoinsTip;
pcoinsTip = NULL;
+ delete pcoinscatcher;
+ pcoinscatcher = NULL;
delete pcoinsdbview;
pcoinsdbview = NULL;
delete pblocktree;
@@ -211,6 +234,26 @@ bool static Bind(const CService &addr, unsigned int flags) {
return true;
}
+void OnRPCStopped()
+{
+ cvBlockChange.notify_all();
+ LogPrint("rpc", "RPC stopped.\n");
+}
+
+void OnRPCPreCommand(const CRPCCommand& cmd)
+{
+#ifdef ENABLE_WALLET
+ if (cmd.reqWallet && !pwalletMain)
+ throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Method not found (disabled)");
+#endif
+
+ // Observe safe mode
+ string strWarning = GetWarnings("rpc");
+ if (strWarning != "" && !GetBoolArg("-disablesafemode", false) &&
+ !cmd.okSafeMode)
+ throw JSONRPCError(RPC_FORBIDDEN_BY_SAFE_MODE, string("Safe mode: ") + strWarning);
+}
+
std::string HelpMessage(HelpMessageMode mode)
{
// When adding new options to the categories, please keep and ensure alphabetical ordering.
@@ -357,6 +400,7 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += " -rpcport=<port> " + strprintf(_("Listen for JSON-RPC connections on <port> (default: %u or testnet: %u)"), 8332, 18332) + "\n";
strUsage += " -rpcallowip=<ip> " + _("Allow JSON-RPC connections from specified source. Valid for <ip> are a single IP (e.g. 1.2.3.4), a network/netmask (e.g. 1.2.3.4/255.255.255.0) or a network/CIDR (e.g. 1.2.3.4/24). This option can be specified multiple times") + "\n";
strUsage += " -rpcthreads=<n> " + strprintf(_("Set the number of threads to service RPC calls (default: %d)"), 4) + "\n";
+ strUsage += " -rpckeepalive " + strprintf(_("RPC support for HTTP persistent connections (default: %d)"), 1) + "\n";
strUsage += "\n" + _("RPC SSL options: (see the Bitcoin Wiki for SSL setup instructions)") + "\n";
strUsage += " -rpcssl " + _("Use OpenSSL (https) for JSON-RPC connections") + "\n";
@@ -778,6 +822,8 @@ bool AppInit2(boost::thread_group& threadGroup)
if (fServer)
{
uiInterface.InitMessage.connect(SetRPCWarmupStatus);
+ RPCServer::OnStopped(&OnRPCStopped);
+ RPCServer::OnPreCommand(&OnRPCPreCommand);
StartRPCThreads();
}
@@ -953,7 +999,7 @@ bool AppInit2(boost::thread_group& threadGroup)
} catch (const boost::filesystem::filesystem_error& e) {
// Note: hardlink creation failing is not a disaster, it just means
// blocks will get re-downloaded from peers.
- LogPrintf("Error hardlinking blk%04u.dat : %s\n", i, e.what());
+ LogPrintf("Error hardlinking blk%04u.dat: %s\n", i, e.what());
break;
}
}
@@ -990,11 +1036,13 @@ bool AppInit2(boost::thread_group& threadGroup)
UnloadBlockIndex();
delete pcoinsTip;
delete pcoinsdbview;
+ delete pcoinscatcher;
delete pblocktree;
pblocktree = new CBlockTreeDB(nBlockTreeDBCache, false, fReindex);
pcoinsdbview = new CCoinsViewDB(nCoinDBCache, false, fReindex);
- pcoinsTip = new CCoinsViewCache(pcoinsdbview);
+ pcoinscatcher = new CCoinsViewErrorCatcher(pcoinsdbview);
+ pcoinsTip = new CCoinsViewCache(pcoinscatcher);
if (fReindex)
pblocktree->WriteReindexing(true);
@@ -1185,6 +1233,8 @@ bool AppInit2(boost::thread_group& threadGroup)
// Restore wallet transaction metadata after -zapwallettxes=1
if (GetBoolArg("-zapwallettxes", false) && GetArg("-zapwallettxes", "1") != "2")
{
+ CWalletDB walletdb(strWalletFile);
+
BOOST_FOREACH(const CWalletTx& wtxOld, vWtx)
{
uint256 hash = wtxOld.GetHash();
@@ -1200,7 +1250,7 @@ bool AppInit2(boost::thread_group& threadGroup)
copyTo->fFromMe = copyFrom->fFromMe;
copyTo->strFromAccount = copyFrom->strFromAccount;
copyTo->nOrderPos = copyFrom->nOrderPos;
- copyTo->WriteToDisk();
+ copyTo->WriteToDisk(&walletdb);
}
}
}
@@ -1226,6 +1276,11 @@ bool AppInit2(boost::thread_group& threadGroup)
vImportFiles.push_back(strFile);
}
threadGroup.create_thread(boost::bind(&ThreadImport, vImportFiles));
+ if (chainActive.Tip() == NULL) {
+ LogPrintf("Waiting for genesis block to be imported...\n");
+ while (!fRequestShutdown && chainActive.Tip() == NULL)
+ MilliSleep(10);
+ }
// ********************************************************* Step 10: start node
diff --git a/src/key.cpp b/src/key.cpp
index 2235c271d1..d8319db1a3 100644
--- a/src/key.cpp
+++ b/src/key.cpp
@@ -6,7 +6,6 @@
#include "arith_uint256.h"
#include "crypto/hmac_sha512.h"
-#include "crypto/rfc6979_hmac_sha256.h"
#include "eccryptoverify.h"
#include "pubkey.h"
#include "random.h"
@@ -74,23 +73,28 @@ CPubKey CKey::GetPubKey() const {
return result;
}
+extern "C"
+{
+static int secp256k1_nonce_function_test_case(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, unsigned int attempt, const void *data)
+{
+ const uint32_t *test_case = static_cast<const uint32_t*>(data);
+ uint256 nonce;
+ secp256k1_nonce_function_rfc6979(nonce.begin(), msg32, key32, attempt, NULL);
+ nonce = ArithToUint256(UintToArith256(nonce) + *test_case);
+ memcpy(nonce32, nonce.begin(), 32);
+ return 1;
+}
+}
+
bool CKey::Sign(const uint256 &hash, std::vector<unsigned char>& vchSig, uint32_t test_case) const {
if (!fValid)
return false;
vchSig.resize(72);
- RFC6979_HMAC_SHA256 prng(begin(), 32, (unsigned char*)&hash, 32);
- do {
- uint256 nonce;
- prng.Generate((unsigned char*)&nonce, 32);
- nonce = ArithToUint256(UintToArith256(nonce) + test_case);
- int nSigLen = 72;
- int ret = secp256k1_ecdsa_sign((const unsigned char*)&hash, (unsigned char*)&vchSig[0], &nSigLen, begin(), (unsigned char*)&nonce);
- nonce = uint256();
- if (ret) {
- vchSig.resize(nSigLen);
- return true;
- }
- } while(true);
+ int nSigLen = 72;
+ int ret = secp256k1_ecdsa_sign(hash.begin(), (unsigned char*)&vchSig[0], &nSigLen, begin(), test_case == 0 ? secp256k1_nonce_function_rfc6979 : secp256k1_nonce_function_test_case, test_case == 0 ? NULL : &test_case);
+ assert(ret);
+ vchSig.resize(nSigLen);
+ return true;
}
bool CKey::VerifyPubKey(const CPubKey& pubkey) const {
@@ -101,7 +105,7 @@ bool CKey::VerifyPubKey(const CPubKey& pubkey) const {
std::string str = "Bitcoin key verification\n";
GetRandBytes(rnd, sizeof(rnd));
uint256 hash;
- CHash256().Write((unsigned char*)str.data(), str.size()).Write(rnd, sizeof(rnd)).Finalize((unsigned char*)&hash);
+ CHash256().Write((unsigned char*)str.data(), str.size()).Write(rnd, sizeof(rnd)).Finalize(hash.begin());
std::vector<unsigned char> vchSig;
Sign(hash, vchSig);
return pubkey.Verify(hash, vchSig);
@@ -112,15 +116,8 @@ bool CKey::SignCompact(const uint256 &hash, std::vector<unsigned char>& vchSig)
return false;
vchSig.resize(65);
int rec = -1;
- RFC6979_HMAC_SHA256 prng(begin(), 32, (unsigned char*)&hash, 32);
- do {
- uint256 nonce;
- prng.Generate((unsigned char*)&nonce, 32);
- int ret = secp256k1_ecdsa_sign_compact((const unsigned char*)&hash, &vchSig[1], begin(), (unsigned char*)&nonce, &rec);
- nonce = uint256();
- if (ret)
- break;
- } while(true);
+ int ret = secp256k1_ecdsa_sign_compact(hash.begin(), &vchSig[1], begin(), secp256k1_nonce_function_rfc6979, NULL, &rec);
+ assert(ret);
assert(rec != -1);
vchSig[0] = 27 + rec + (fCompressed ? 4 : 0);
return true;
diff --git a/src/keystore.cpp b/src/keystore.cpp
index 482125a39a..7531737e04 100644
--- a/src/keystore.cpp
+++ b/src/keystore.cpp
@@ -7,8 +7,6 @@
#include "crypter.h"
#include "key.h"
-#include "script/script.h"
-#include "script/standard.h"
#include "util.h"
#include <boost/foreach.hpp>
@@ -36,7 +34,7 @@ bool CBasicKeyStore::AddKeyPubKey(const CKey& key, const CPubKey &pubkey)
bool CBasicKeyStore::AddCScript(const CScript& redeemScript)
{
if (redeemScript.size() > MAX_SCRIPT_ELEMENT_SIZE)
- return error("CBasicKeyStore::AddCScript() : redeemScripts > %i bytes are invalid", MAX_SCRIPT_ELEMENT_SIZE);
+ return error("CBasicKeyStore::AddCScript(): redeemScripts > %i bytes are invalid", MAX_SCRIPT_ELEMENT_SIZE);
LOCK(cs_KeyStore);
mapScripts[CScriptID(redeemScript)] = redeemScript;
diff --git a/src/keystore.h b/src/keystore.h
index 6655264d72..4a4b6d20af 100644
--- a/src/keystore.h
+++ b/src/keystore.h
@@ -8,14 +8,13 @@
#include "key.h"
#include "pubkey.h"
+#include "script/script.h"
+#include "script/standard.h"
#include "sync.h"
#include <boost/signals2/signal.hpp>
#include <boost/variant.hpp>
-class CScript;
-class CScriptID;
-
/** A virtual base class for key stores */
class CKeyStore
{
diff --git a/src/main.cpp b/src/main.cpp
index 2e9d954458..43e5a2d024 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -139,9 +139,14 @@ namespace {
uint256 hash;
CBlockIndex *pindex; //! Optional.
int64_t nTime; //! Time of "getdata" request in microseconds.
+ int nValidatedQueuedBefore; //! Number of blocks queued with validated headers (globally) at the time this one is requested.
+ bool fValidatedHeaders; //! Whether this block has validated headers at the time of request.
};
map<uint256, pair<NodeId, list<QueuedBlock>::iterator> > mapBlocksInFlight;
+ /** Number of blocks in flight with validated headers. */
+ int nQueuedValidatedHeaders = 0;
+
/** Number of preferable block download peers. */
int nPreferredDownload = 0;
@@ -323,6 +328,7 @@ void MarkBlockAsReceived(const uint256& hash) {
map<uint256, pair<NodeId, list<QueuedBlock>::iterator> >::iterator itInFlight = mapBlocksInFlight.find(hash);
if (itInFlight != mapBlocksInFlight.end()) {
CNodeState *state = State(itInFlight->second.first);
+ nQueuedValidatedHeaders -= itInFlight->second.second->fValidatedHeaders;
state->vBlocksInFlight.erase(itInFlight->second.second);
state->nBlocksInFlight--;
state->nStallingSince = 0;
@@ -338,7 +344,8 @@ void MarkBlockAsInFlight(NodeId nodeid, const uint256& hash, CBlockIndex *pindex
// Make sure it's not listed somewhere already.
MarkBlockAsReceived(hash);
- QueuedBlock newentry = {hash, pindex, GetTimeMicros()};
+ QueuedBlock newentry = {hash, pindex, GetTimeMicros(), nQueuedValidatedHeaders, pindex != NULL};
+ nQueuedValidatedHeaders += newentry.fValidatedHeaders;
list<QueuedBlock>::iterator it = state->vBlocksInFlight.insert(state->vBlocksInFlight.end(), newentry);
state->nBlocksInFlight++;
mapBlocksInFlight[hash] = std::make_pair(nodeid, it);
@@ -737,7 +744,7 @@ bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs)
// non-standard. Note that this EvalScript() call will
// be quick, because if there are any operations
// beside "push data" in the scriptSig
- // IsStandard() will have already returned false
+ // IsStandardTx() will have already returned false
// and this method isn't called.
vector<vector<unsigned char> > stack;
if (!EvalScript(stack, tx.vin[i].scriptSig, SCRIPT_VERIFY_NONE, BaseSignatureChecker()))
@@ -813,14 +820,14 @@ bool CheckTransaction(const CTransaction& tx, CValidationState &state)
{
// Basic checks that don't depend on any context
if (tx.vin.empty())
- return state.DoS(10, error("CheckTransaction() : vin empty"),
+ return state.DoS(10, error("CheckTransaction(): vin empty"),
REJECT_INVALID, "bad-txns-vin-empty");
if (tx.vout.empty())
- return state.DoS(10, error("CheckTransaction() : vout empty"),
+ return state.DoS(10, error("CheckTransaction(): vout empty"),
REJECT_INVALID, "bad-txns-vout-empty");
// Size limits
if (::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION) > MAX_BLOCK_SIZE)
- return state.DoS(100, error("CheckTransaction() : size limits failed"),
+ return state.DoS(100, error("CheckTransaction(): size limits failed"),
REJECT_INVALID, "bad-txns-oversize");
// Check for negative or overflow output values
@@ -828,14 +835,14 @@ bool CheckTransaction(const CTransaction& tx, CValidationState &state)
BOOST_FOREACH(const CTxOut& txout, tx.vout)
{
if (txout.nValue < 0)
- return state.DoS(100, error("CheckTransaction() : txout.nValue negative"),
+ return state.DoS(100, error("CheckTransaction(): txout.nValue negative"),
REJECT_INVALID, "bad-txns-vout-negative");
if (txout.nValue > MAX_MONEY)
- return state.DoS(100, error("CheckTransaction() : txout.nValue too high"),
+ return state.DoS(100, error("CheckTransaction(): txout.nValue too high"),
REJECT_INVALID, "bad-txns-vout-toolarge");
nValueOut += txout.nValue;
if (!MoneyRange(nValueOut))
- return state.DoS(100, error("CheckTransaction() : txout total out of range"),
+ return state.DoS(100, error("CheckTransaction(): txout total out of range"),
REJECT_INVALID, "bad-txns-txouttotal-toolarge");
}
@@ -844,7 +851,7 @@ bool CheckTransaction(const CTransaction& tx, CValidationState &state)
BOOST_FOREACH(const CTxIn& txin, tx.vin)
{
if (vInOutPoints.count(txin.prevout))
- return state.DoS(100, error("CheckTransaction() : duplicate inputs"),
+ return state.DoS(100, error("CheckTransaction(): duplicate inputs"),
REJECT_INVALID, "bad-txns-inputs-duplicate");
vInOutPoints.insert(txin.prevout);
}
@@ -852,14 +859,14 @@ bool CheckTransaction(const CTransaction& tx, CValidationState &state)
if (tx.IsCoinBase())
{
if (tx.vin[0].scriptSig.size() < 2 || tx.vin[0].scriptSig.size() > 100)
- return state.DoS(100, error("CheckTransaction() : coinbase script size"),
+ return state.DoS(100, error("CheckTransaction(): coinbase script size"),
REJECT_INVALID, "bad-cb-length");
}
else
{
BOOST_FOREACH(const CTxIn& txin, tx.vin)
if (txin.prevout.IsNull())
- return state.DoS(10, error("CheckTransaction() : prevout is null"),
+ return state.DoS(10, error("CheckTransaction(): prevout is null"),
REJECT_INVALID, "bad-txns-prevout-null");
}
@@ -897,7 +904,7 @@ CAmount GetMinRelayFee(const CTransaction& tx, unsigned int nBytes, bool fAllowF
bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransaction &tx, bool fLimitFree,
- bool* pfMissingInputs, bool fRejectInsaneFee)
+ bool* pfMissingInputs, bool fRejectAbsurdFee)
{
AssertLockHeld(cs_main);
if (pfMissingInputs)
@@ -915,7 +922,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
string reason;
if (Params().RequireStandard() && !IsStandardTx(tx, reason))
return state.DoS(0,
- error("AcceptToMemoryPool : nonstandard transaction: %s", reason),
+ error("AcceptToMemoryPool: nonstandard transaction: %s", reason),
REJECT_NONSTANDARD, reason);
// Only accept nLockTime-using transactions that can be mined in the next
@@ -935,7 +942,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
// timestamp applications where it matters.
if (!IsFinalTx(tx, chainActive.Height() + 1))
return state.DoS(0,
- error("AcceptToMemoryPool : non-final"),
+ error("AcceptToMemoryPool: non-final"),
REJECT_NONSTANDARD, "non-final");
// is it already in the memory pool?
@@ -984,7 +991,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
// are the actual inputs available?
if (!view.HaveInputs(tx))
- return state.Invalid(error("AcceptToMemoryPool : inputs already spent"),
+ return state.Invalid(error("AcceptToMemoryPool: inputs already spent"),
REJECT_DUPLICATE, "bad-txns-inputs-spent");
// Bring the best block into scope
@@ -1009,7 +1016,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
nSigOps += GetP2SHSigOpCount(tx, view);
if (nSigOps > MAX_STANDARD_TX_SIGOPS)
return state.DoS(0,
- error("AcceptToMemoryPool : too many sigops %s, %d > %d",
+ error("AcceptToMemoryPool: too many sigops %s, %d > %d",
hash.ToString(), nSigOps, MAX_STANDARD_TX_SIGOPS),
REJECT_NONSTANDARD, "bad-txns-too-many-sigops");
@@ -1023,7 +1030,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
// Don't accept it if it can't get into a block
CAmount txMinFee = GetMinRelayFee(tx, nSize, true);
if (fLimitFree && nFees < txMinFee)
- return state.DoS(0, error("AcceptToMemoryPool : not enough fees %s, %d < %d",
+ return state.DoS(0, error("AcceptToMemoryPool: not enough fees %s, %d < %d",
hash.ToString(), nFees, txMinFee),
REJECT_INSUFFICIENTFEE, "insufficient fee");
@@ -1050,14 +1057,14 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
// -limitfreerelay unit is thousand-bytes-per-minute
// At default rate it would take over a month to fill 1GB
if (dFreeCount >= GetArg("-limitfreerelay", 15)*10*1000)
- return state.DoS(0, error("AcceptToMemoryPool : free transaction rejected by rate limiter"),
+ return state.DoS(0, error("AcceptToMemoryPool: free transaction rejected by rate limiter"),
REJECT_INSUFFICIENTFEE, "rate limited free transaction");
LogPrint("mempool", "Rate limit dFreeCount: %g => %g\n", dFreeCount, dFreeCount+nSize);
dFreeCount += nSize;
}
- if (fRejectInsaneFee && nFees > ::minRelayTxFee.GetFee(nSize) * 10000)
- return error("AcceptToMemoryPool: insane fees %s, %d > %d",
+ if (fRejectAbsurdFee && nFees > ::minRelayTxFee.GetFee(nSize) * 10000)
+ return error("AcceptToMemoryPool: absurdly high fees %s, %d > %d",
hash.ToString(),
nFees, ::minRelayTxFee.GetFee(nSize) * 10000);
@@ -1116,11 +1123,11 @@ bool GetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock
fseek(file.Get(), postx.nTxOffset, SEEK_CUR);
file >> txOut;
} catch (const std::exception& e) {
- return error("%s : Deserialize or I/O error - %s", __func__, e.what());
+ return error("%s: Deserialize or I/O error - %s", __func__, e.what());
}
hashBlock = header.GetHash();
if (txOut.GetHash() != hash)
- return error("%s : txid mismatch", __func__);
+ return error("%s: txid mismatch", __func__);
return true;
}
}
@@ -1169,7 +1176,7 @@ bool WriteBlockToDisk(CBlock& block, CDiskBlockPos& pos)
// Open history file to append
CAutoFile fileout(OpenBlockFile(pos), SER_DISK, CLIENT_VERSION);
if (fileout.IsNull())
- return error("WriteBlockToDisk : OpenBlockFile failed");
+ return error("WriteBlockToDisk: OpenBlockFile failed");
// Write index header
unsigned int nSize = fileout.GetSerializeSize(block);
@@ -1178,7 +1185,7 @@ bool WriteBlockToDisk(CBlock& block, CDiskBlockPos& pos)
// Write block
long fileOutPos = ftell(fileout.Get());
if (fileOutPos < 0)
- return error("WriteBlockToDisk : ftell failed");
+ return error("WriteBlockToDisk: ftell failed");
pos.nPos = (unsigned int)fileOutPos;
fileout << block;
@@ -1192,19 +1199,19 @@ bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos)
// Open history file to read
CAutoFile filein(OpenBlockFile(pos, true), SER_DISK, CLIENT_VERSION);
if (filein.IsNull())
- return error("ReadBlockFromDisk : OpenBlockFile failed");
+ return error("ReadBlockFromDisk: OpenBlockFile failed");
// Read block
try {
filein >> block;
}
catch (const std::exception& e) {
- return error("%s : Deserialize or I/O error - %s", __func__, e.what());
+ return error("%s: Deserialize or I/O error - %s", __func__, e.what());
}
// Check the header
if (!CheckProofOfWork(block.GetHash(), block.nBits))
- return error("ReadBlockFromDisk : Errors in block header");
+ return error("ReadBlockFromDisk: Errors in block header");
return true;
}
@@ -1214,7 +1221,7 @@ bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex)
if (!ReadBlockFromDisk(block, pindex->GetBlockPos()))
return false;
if (block.GetHash() != pindex->GetBlockHash())
- return error("ReadBlockFromDisk(CBlock&, CBlockIndex*) : GetHash() doesn't match index");
+ return error("ReadBlockFromDisk(CBlock&, CBlockIndex*): GetHash() doesn't match index");
return true;
}
@@ -1415,8 +1422,8 @@ void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCach
bool CScriptCheck::operator()() {
const CScript &scriptSig = ptxTo->vin[nIn].scriptSig;
- if (!VerifyScript(scriptSig, scriptPubKey, nFlags, CachingSignatureChecker(*ptxTo, nIn, cacheStore), &error)) {
- return ::error("CScriptCheck() : %s:%d VerifySignature failed: %s", ptxTo->GetHash().ToString(), nIn, ScriptErrorString(error));
+ if (!VerifyScript(scriptSig, scriptPubKey, nFlags, CachingTransactionSignatureChecker(ptxTo, nIn, cacheStore), &error)) {
+ return ::error("CScriptCheck(): %s:%d VerifySignature failed: %s", ptxTo->GetHash().ToString(), nIn, ScriptErrorString(error));
}
return true;
}
@@ -1431,7 +1438,7 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsVi
// This doesn't trigger the DoS code on purpose; if it did, it would make it easier
// for an attacker to attempt to split the network.
if (!inputs.HaveInputs(tx))
- return state.Invalid(error("CheckInputs() : %s inputs unavailable", tx.GetHash().ToString()));
+ return state.Invalid(error("CheckInputs(): %s inputs unavailable", tx.GetHash().ToString()));
// While checking, GetBestBlock() refers to the parent block.
// This is also true for mempool checks.
@@ -1449,31 +1456,31 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsVi
if (coins->IsCoinBase()) {
if (nSpendHeight - coins->nHeight < COINBASE_MATURITY)
return state.Invalid(
- error("CheckInputs() : tried to spend coinbase at depth %d", nSpendHeight - coins->nHeight),
+ error("CheckInputs(): tried to spend coinbase at depth %d", nSpendHeight - coins->nHeight),
REJECT_INVALID, "bad-txns-premature-spend-of-coinbase");
}
// Check for negative or overflow input values
nValueIn += coins->vout[prevout.n].nValue;
if (!MoneyRange(coins->vout[prevout.n].nValue) || !MoneyRange(nValueIn))
- return state.DoS(100, error("CheckInputs() : txin values out of range"),
+ return state.DoS(100, error("CheckInputs(): txin values out of range"),
REJECT_INVALID, "bad-txns-inputvalues-outofrange");
}
if (nValueIn < tx.GetValueOut())
- return state.DoS(100, error("CheckInputs() : %s value in (%s) < value out (%s)",
+ return state.DoS(100, error("CheckInputs(): %s value in (%s) < value out (%s)",
tx.GetHash().ToString(), FormatMoney(nValueIn), FormatMoney(tx.GetValueOut())),
REJECT_INVALID, "bad-txns-in-belowout");
// Tally transaction fees
CAmount nTxFee = nValueIn - tx.GetValueOut();
if (nTxFee < 0)
- return state.DoS(100, error("CheckInputs() : %s nTxFee < 0", tx.GetHash().ToString()),
+ return state.DoS(100, error("CheckInputs(): %s nTxFee < 0", tx.GetHash().ToString()),
REJECT_INVALID, "bad-txns-fee-negative");
nFees += nTxFee;
if (!MoneyRange(nFees))
- return state.DoS(100, error("CheckInputs() : nFees out of range"),
+ return state.DoS(100, error("CheckInputs(): nFees out of range"),
REJECT_INVALID, "bad-txns-fee-outofrange");
// The first loop above does all the inexpensive checks.
@@ -1530,7 +1537,7 @@ bool UndoWriteToDisk(const CBlockUndo& blockundo, CDiskBlockPos& pos, const uint
// Open history file to append
CAutoFile fileout(OpenUndoFile(pos), SER_DISK, CLIENT_VERSION);
if (fileout.IsNull())
- return error("%s : OpenUndoFile failed", __func__);
+ return error("%s: OpenUndoFile failed", __func__);
// Write index header
unsigned int nSize = fileout.GetSerializeSize(blockundo);
@@ -1539,7 +1546,7 @@ bool UndoWriteToDisk(const CBlockUndo& blockundo, CDiskBlockPos& pos, const uint
// Write undo data
long fileOutPos = ftell(fileout.Get());
if (fileOutPos < 0)
- return error("%s : ftell failed", __func__);
+ return error("%s: ftell failed", __func__);
pos.nPos = (unsigned int)fileOutPos;
fileout << blockundo;
@@ -1557,7 +1564,7 @@ bool UndoReadFromDisk(CBlockUndo& blockundo, const CDiskBlockPos& pos, const uin
// Open history file to read
CAutoFile filein(OpenUndoFile(pos, true), SER_DISK, CLIENT_VERSION);
if (filein.IsNull())
- return error("%s : OpenBlockFile failed", __func__);
+ return error("%s: OpenBlockFile failed", __func__);
// Read block
uint256 hashChecksum;
@@ -1566,7 +1573,7 @@ bool UndoReadFromDisk(CBlockUndo& blockundo, const CDiskBlockPos& pos, const uin
filein >> hashChecksum;
}
catch (const std::exception& e) {
- return error("%s : Deserialize or I/O error - %s", __func__, e.what());
+ return error("%s: Deserialize or I/O error - %s", __func__, e.what());
}
// Verify checksum
@@ -1574,7 +1581,7 @@ bool UndoReadFromDisk(CBlockUndo& blockundo, const CDiskBlockPos& pos, const uin
hasher << hashBlock;
hasher << blockundo;
if (hashChecksum != hasher.GetHash())
- return error("%s : Checksum mismatch", __func__);
+ return error("%s: Checksum mismatch", __func__);
return true;
}
@@ -1593,12 +1600,12 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex
CBlockUndo blockUndo;
CDiskBlockPos pos = pindex->GetUndoPos();
if (pos.IsNull())
- return error("DisconnectBlock() : no undo data available");
+ return error("DisconnectBlock(): no undo data available");
if (!UndoReadFromDisk(blockUndo, pos, pindex->pprev->GetBlockHash()))
- return error("DisconnectBlock() : failure reading undo data");
+ return error("DisconnectBlock(): failure reading undo data");
if (blockUndo.vtxundo.size() + 1 != block.vtx.size())
- return error("DisconnectBlock() : block and undo data inconsistent");
+ return error("DisconnectBlock(): block and undo data inconsistent");
// undo transactions in reverse order
for (int i = block.vtx.size() - 1; i >= 0; i--) {
@@ -1621,7 +1628,7 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex
if (outsBlock.nVersion < 0)
outs->nVersion = outsBlock.nVersion;
if (*outs != outsBlock)
- fClean = fClean && error("DisconnectBlock() : added transaction mismatch? database corrupted");
+ fClean = fClean && error("DisconnectBlock(): added transaction mismatch? database corrupted");
// remove outputs
outs->Clear();
@@ -1631,7 +1638,7 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex
if (i > 0) { // not coinbases
const CTxUndo &txundo = blockUndo.vtxundo[i-1];
if (txundo.vprevout.size() != tx.vin.size())
- return error("DisconnectBlock() : transaction and undo data inconsistent");
+ return error("DisconnectBlock(): transaction and undo data inconsistent");
for (unsigned int j = tx.vin.size(); j-- > 0;) {
const COutPoint &out = tx.vin[j].prevout;
const CTxInUndo &undo = txundo.vprevout[j];
@@ -1639,17 +1646,17 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex
if (undo.nHeight != 0) {
// undo data contains height: this is the last output of the prevout tx being spent
if (!coins->IsPruned())
- fClean = fClean && error("DisconnectBlock() : undo data overwriting existing transaction");
+ fClean = fClean && error("DisconnectBlock(): undo data overwriting existing transaction");
coins->Clear();
coins->fCoinBase = undo.fCoinBase;
coins->nHeight = undo.nHeight;
coins->nVersion = undo.nVersion;
} else {
if (coins->IsPruned())
- fClean = fClean && error("DisconnectBlock() : undo data adding output to missing transaction");
+ fClean = fClean && error("DisconnectBlock(): undo data adding output to missing transaction");
}
if (coins->IsAvailable(out.n))
- fClean = fClean && error("DisconnectBlock() : undo data overwriting existing output");
+ fClean = fClean && error("DisconnectBlock(): undo data overwriting existing output");
if (coins->vout.size() < out.n+1)
coins->vout.resize(out.n+1);
coins->vout[out.n] = undo.txout;
@@ -1746,7 +1753,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
BOOST_FOREACH(const CTransaction& tx, block.vtx) {
const CCoins* coins = view.AccessCoins(tx.GetHash());
if (coins && !coins->IsPruned())
- return state.DoS(100, error("ConnectBlock() : tried to overwrite transaction"),
+ return state.DoS(100, error("ConnectBlock(): tried to overwrite transaction"),
REJECT_INVALID, "bad-txns-BIP30");
}
}
@@ -1757,6 +1764,11 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
unsigned int flags = fStrictPayToScriptHash ? SCRIPT_VERIFY_P2SH : SCRIPT_VERIFY_NONE;
+ // Start enforcing the DERSIG (BIP66) rules, for block.nVersion=3 blocks, when 75% of the network has upgraded:
+ if (block.nVersion >= 3 && IsSuperMajority(3, pindex->pprev, Params().EnforceBlockUpgradeMajority())) {
+ flags |= SCRIPT_VERIFY_DERSIG;
+ }
+
CBlockUndo blockundo;
CCheckQueueControl<CScriptCheck> control(fScriptChecks && nScriptCheckThreads ? &scriptcheckqueue : NULL);
@@ -1776,13 +1788,13 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
nInputs += tx.vin.size();
nSigOps += GetLegacySigOpCount(tx);
if (nSigOps > MAX_BLOCK_SIGOPS)
- return state.DoS(100, error("ConnectBlock() : too many sigops"),
+ return state.DoS(100, error("ConnectBlock(): too many sigops"),
REJECT_INVALID, "bad-blk-sigops");
if (!tx.IsCoinBase())
{
if (!view.HaveInputs(tx))
- return state.DoS(100, error("ConnectBlock() : inputs missing/spent"),
+ return state.DoS(100, error("ConnectBlock(): inputs missing/spent"),
REJECT_INVALID, "bad-txns-inputs-missingorspent");
if (fStrictPayToScriptHash)
@@ -1792,7 +1804,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
// an incredibly-expensive-to-validate block.
nSigOps += GetP2SHSigOpCount(tx, view);
if (nSigOps > MAX_BLOCK_SIGOPS)
- return state.DoS(100, error("ConnectBlock() : too many sigops"),
+ return state.DoS(100, error("ConnectBlock(): too many sigops"),
REJECT_INVALID, "bad-blk-sigops");
}
@@ -1818,7 +1830,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
if (block.vtx[0].GetValueOut() > GetBlockValue(pindex->nHeight, nFees))
return state.DoS(100,
- error("ConnectBlock() : coinbase pays too much (actual=%d vs limit=%d)",
+ error("ConnectBlock(): coinbase pays too much (actual=%d vs limit=%d)",
block.vtx[0].GetValueOut(), GetBlockValue(pindex->nHeight, nFees)),
REJECT_INVALID, "bad-cb-amount");
@@ -1836,7 +1848,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
if (pindex->GetUndoPos().IsNull()) {
CDiskBlockPos pos;
if (!FindUndoPos(state, pindex->nFile, pos, ::GetSerializeSize(blockundo, SER_DISK, CLIENT_VERSION) + 40))
- return error("ConnectBlock() : FindUndoPos failed");
+ return error("ConnectBlock(): FindUndoPos failed");
if (!UndoWriteToDisk(blockundo, pos, pindex->pprev->GetBlockHash()))
return state.Abort("Failed to write undo data");
@@ -1988,7 +2000,7 @@ bool static DisconnectTip(CValidationState &state) {
{
CCoinsViewCache view(pcoinsTip);
if (!DisconnectBlock(block, state, pindexDelete, view))
- return error("DisconnectTip() : DisconnectBlock %s failed", pindexDelete->GetBlockHash().ToString());
+ return error("DisconnectTip(): DisconnectBlock %s failed", pindexDelete->GetBlockHash().ToString());
assert(view.Flush());
}
LogPrint("bench", "- Disconnect block: %.2fms\n", (GetTimeMicros() - nStart) * 0.001);
@@ -2048,7 +2060,7 @@ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, CBlock *
if (!rv) {
if (state.IsInvalid())
InvalidBlockFound(pindexNew, state);
- return error("ConnectTip() : ConnectBlock %s failed", pindexNew->GetBlockHash().ToString());
+ return error("ConnectTip(): ConnectBlock %s failed", pindexNew->GetBlockHash().ToString());
}
mapBlockSource.erase(inv.hash);
nTime3 = GetTimeMicros(); nTimeConnectTotal += nTime3 - nTime2;
@@ -2485,12 +2497,12 @@ bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, bool f
{
// Check proof of work matches claimed amount
if (fCheckPOW && !CheckProofOfWork(block.GetHash(), block.nBits))
- return state.DoS(50, error("CheckBlockHeader() : proof of work failed"),
+ return state.DoS(50, error("CheckBlockHeader(): proof of work failed"),
REJECT_INVALID, "high-hash");
// Check timestamp
if (block.GetBlockTime() > GetAdjustedTime() + 2 * 60 * 60)
- return state.Invalid(error("CheckBlockHeader() : block timestamp too far in the future"),
+ return state.Invalid(error("CheckBlockHeader(): block timestamp too far in the future"),
REJECT_INVALID, "time-too-new");
return true;
@@ -2510,14 +2522,14 @@ bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW, bo
bool mutated;
uint256 hashMerkleRoot2 = block.BuildMerkleTree(&mutated);
if (block.hashMerkleRoot != hashMerkleRoot2)
- return state.DoS(100, error("CheckBlock() : hashMerkleRoot mismatch"),
+ return state.DoS(100, error("CheckBlock(): hashMerkleRoot mismatch"),
REJECT_INVALID, "bad-txnmrklroot", true);
// Check for merkle tree malleability (CVE-2012-2459): repeating sequences
// of transactions in a block without affecting the merkle root of a block,
// while still invalidating it.
if (mutated)
- return state.DoS(100, error("CheckBlock() : duplicate transaction"),
+ return state.DoS(100, error("CheckBlock(): duplicate transaction"),
REJECT_INVALID, "bad-txns-duplicate", true);
}
@@ -2527,22 +2539,22 @@ bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW, bo
// Size limits
if (block.vtx.empty() || block.vtx.size() > MAX_BLOCK_SIZE || ::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION) > MAX_BLOCK_SIZE)
- return state.DoS(100, error("CheckBlock() : size limits failed"),
+ return state.DoS(100, error("CheckBlock(): size limits failed"),
REJECT_INVALID, "bad-blk-length");
// First transaction must be coinbase, the rest must not be
if (block.vtx.empty() || !block.vtx[0].IsCoinBase())
- return state.DoS(100, error("CheckBlock() : first tx is not coinbase"),
+ return state.DoS(100, error("CheckBlock(): first tx is not coinbase"),
REJECT_INVALID, "bad-cb-missing");
for (unsigned int i = 1; i < block.vtx.size(); i++)
if (block.vtx[i].IsCoinBase())
- return state.DoS(100, error("CheckBlock() : more than one coinbase"),
+ return state.DoS(100, error("CheckBlock(): more than one coinbase"),
REJECT_INVALID, "bad-cb-multiple");
// Check transactions
BOOST_FOREACH(const CTransaction& tx, block.vtx)
if (!CheckTransaction(tx, state))
- return error("CheckBlock() : CheckTransaction failed");
+ return error("CheckBlock(): CheckTransaction failed");
unsigned int nSigOps = 0;
BOOST_FOREACH(const CTransaction& tx, block.vtx)
@@ -2550,7 +2562,7 @@ bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW, bo
nSigOps += GetLegacySigOpCount(tx);
}
if (nSigOps > MAX_BLOCK_SIGOPS)
- return state.DoS(100, error("CheckBlock() : out-of-bounds SigOpCount"),
+ return state.DoS(100, error("CheckBlock(): out-of-bounds SigOpCount"),
REJECT_INVALID, "bad-blk-sigops", true);
return true;
@@ -2569,28 +2581,35 @@ bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& sta
// Check proof of work
if ((!Params().SkipProofOfWorkCheck()) &&
(block.nBits != GetNextWorkRequired(pindexPrev, &block)))
- return state.DoS(100, error("%s : incorrect proof of work", __func__),
+ return state.DoS(100, error("%s: incorrect proof of work", __func__),
REJECT_INVALID, "bad-diffbits");
// Check timestamp against prev
if (block.GetBlockTime() <= pindexPrev->GetMedianTimePast())
- return state.Invalid(error("%s : block's timestamp is too early", __func__),
+ return state.Invalid(error("%s: block's timestamp is too early", __func__),
REJECT_INVALID, "time-too-old");
// Check that the block chain matches the known block chain up to a checkpoint
if (!Checkpoints::CheckBlock(nHeight, hash))
- return state.DoS(100, error("%s : rejected by checkpoint lock-in at %d", __func__, nHeight),
+ return state.DoS(100, error("%s: rejected by checkpoint lock-in at %d", __func__, nHeight),
REJECT_CHECKPOINT, "checkpoint mismatch");
// Don't accept any forks from the main chain prior to last checkpoint
CBlockIndex* pcheckpoint = Checkpoints::GetLastCheckpoint();
if (pcheckpoint && nHeight < pcheckpoint->nHeight)
- return state.DoS(100, error("%s : forked chain older than last checkpoint (height %d)", __func__, nHeight));
+ return state.DoS(100, error("%s: forked chain older than last checkpoint (height %d)", __func__, nHeight));
// Reject block.nVersion=1 blocks when 95% (75% on testnet) of the network has upgraded:
if (block.nVersion < 2 && IsSuperMajority(2, pindexPrev, Params().RejectBlockOutdatedMajority()))
{
- return state.Invalid(error("%s : rejected nVersion=1 block", __func__),
+ return state.Invalid(error("%s: rejected nVersion=1 block", __func__),
+ REJECT_OBSOLETE, "bad-version");
+ }
+
+ // Reject block.nVersion=2 blocks when 95% (75% on testnet) of the network has upgraded:
+ if (block.nVersion < 3 && IsSuperMajority(3, pindexPrev, Params().RejectBlockOutdatedMajority()))
+ {
+ return state.Invalid(error("%s : rejected nVersion=2 block", __func__),
REJECT_OBSOLETE, "bad-version");
}
@@ -2604,7 +2623,7 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIn
// Check that all transactions are finalized
BOOST_FOREACH(const CTransaction& tx, block.vtx)
if (!IsFinalTx(tx, nHeight, block.GetBlockTime())) {
- return state.DoS(10, error("%s : contains a non-final transaction", __func__), REJECT_INVALID, "bad-txns-nonfinal");
+ return state.DoS(10, error("%s: contains a non-final transaction", __func__), REJECT_INVALID, "bad-txns-nonfinal");
}
// Enforce block.nVersion=2 rule that the coinbase starts with serialized block height
@@ -2614,7 +2633,7 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIn
CScript expect = CScript() << nHeight;
if (block.vtx[0].vin[0].scriptSig.size() < expect.size() ||
!std::equal(expect.begin(), expect.end(), block.vtx[0].vin[0].scriptSig.begin())) {
- return state.DoS(100, error("%s : block height mismatch in coinbase", __func__), REJECT_INVALID, "bad-cb-height");
+ return state.DoS(100, error("%s: block height mismatch in coinbase", __func__), REJECT_INVALID, "bad-cb-height");
}
}
@@ -2634,7 +2653,7 @@ bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, CBloc
if (ppindex)
*ppindex = pindex;
if (pindex->nStatus & BLOCK_FAILED_MASK)
- return state.Invalid(error("%s : block is marked invalid", __func__), 0, "duplicate");
+ return state.Invalid(error("%s: block is marked invalid", __func__), 0, "duplicate");
return true;
}
@@ -2646,10 +2665,10 @@ bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, CBloc
if (hash != Params().HashGenesisBlock()) {
BlockMap::iterator mi = mapBlockIndex.find(block.hashPrevBlock);
if (mi == mapBlockIndex.end())
- return state.DoS(10, error("%s : prev block not found", __func__), 0, "bad-prevblk");
+ return state.DoS(10, error("%s: prev block not found", __func__), 0, "bad-prevblk");
pindexPrev = (*mi).second;
if (pindexPrev->nStatus & BLOCK_FAILED_MASK)
- return state.DoS(100, error("%s : prev block invalid", __func__), REJECT_INVALID, "bad-prevblk");
+ return state.DoS(100, error("%s: prev block invalid", __func__), REJECT_INVALID, "bad-prevblk");
}
if (!ContextualCheckBlockHeader(block, state, pindexPrev))
@@ -2675,7 +2694,7 @@ bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex** ppindex,
if (pindex->nStatus & BLOCK_HAVE_DATA) {
// TODO: deal better with duplicate blocks.
- // return state.DoS(20, error("AcceptBlock() : already have block %d %s", pindex->nHeight, pindex->GetBlockHash().ToString()), REJECT_DUPLICATE, "duplicate");
+ // return state.DoS(20, error("AcceptBlock(): already have block %d %s", pindex->nHeight, pindex->GetBlockHash().ToString()), REJECT_DUPLICATE, "duplicate");
return true;
}
@@ -2696,12 +2715,12 @@ bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex** ppindex,
if (dbp != NULL)
blockPos = *dbp;
if (!FindBlockPos(state, blockPos, nBlockSize+8, nHeight, block.GetBlockTime(), dbp != NULL))
- return error("AcceptBlock() : FindBlockPos failed");
+ return error("AcceptBlock(): FindBlockPos failed");
if (dbp == NULL)
if (!WriteBlockToDisk(block, blockPos))
return state.Abort("Failed to write block");
if (!ReceivedBlockTransactions(block, state, pindex, blockPos))
- return error("AcceptBlock() : ReceivedBlockTransactions failed");
+ return error("AcceptBlock(): ReceivedBlockTransactions failed");
} catch (const std::runtime_error& e) {
return state.Abort(std::string("System error: ") + e.what());
}
@@ -2732,7 +2751,7 @@ bool ProcessNewBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDis
LOCK(cs_main);
MarkBlockAsReceived(pblock->GetHash());
if (!checked) {
- return error("%s : CheckBlock FAILED", __func__);
+ return error("%s: CheckBlock FAILED", __func__);
}
// Store to disk
@@ -2742,11 +2761,11 @@ bool ProcessNewBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDis
mapBlockSource[pindex->GetBlockHash()] = pfrom->GetId();
}
if (!ret)
- return error("%s : AcceptBlock FAILED", __func__);
+ return error("%s: AcceptBlock FAILED", __func__);
}
if (!ActivateBestChain(state, pblock))
- return error("%s : ActivateBestChain failed", __func__);
+ return error("%s: ActivateBestChain failed", __func__);
return true;
}
@@ -2852,7 +2871,7 @@ CBlockIndex * InsertBlockIndex(uint256 hash)
// Create new
CBlockIndex* pindexNew = new CBlockIndex();
if (!pindexNew)
- throw runtime_error("LoadBlockIndex() : new CBlockIndex failed");
+ throw runtime_error("LoadBlockIndex(): new CBlockIndex failed");
mi = mapBlockIndex.insert(make_pair(hash, pindexNew)).first;
pindexNew->phashBlock = &((*mi).first);
@@ -2998,24 +3017,24 @@ bool CVerifyDB::VerifyDB(CCoinsView *coinsview, int nCheckLevel, int nCheckDepth
CBlock block;
// check level 0: read from disk
if (!ReadBlockFromDisk(block, pindex))
- return error("VerifyDB() : *** ReadBlockFromDisk failed at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString());
+ return error("VerifyDB(): *** ReadBlockFromDisk failed at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString());
// check level 1: verify block validity
if (nCheckLevel >= 1 && !CheckBlock(block, state))
- return error("VerifyDB() : *** found bad block at %d, hash=%s\n", pindex->nHeight, pindex->GetBlockHash().ToString());
+ return error("VerifyDB(): *** found bad block at %d, hash=%s\n", pindex->nHeight, pindex->GetBlockHash().ToString());
// check level 2: verify undo validity
if (nCheckLevel >= 2 && pindex) {
CBlockUndo undo;
CDiskBlockPos pos = pindex->GetUndoPos();
if (!pos.IsNull()) {
if (!UndoReadFromDisk(undo, pos, pindex->pprev->GetBlockHash()))
- return error("VerifyDB() : *** found bad undo data at %d, hash=%s\n", pindex->nHeight, pindex->GetBlockHash().ToString());
+ return error("VerifyDB(): *** found bad undo data at %d, hash=%s\n", pindex->nHeight, pindex->GetBlockHash().ToString());
}
}
// check level 3: check for inconsistencies during memory-only disconnect of tip blocks
if (nCheckLevel >= 3 && pindex == pindexState && (coins.GetCacheSize() + pcoinsTip->GetCacheSize()) <= nCoinCacheSize) {
bool fClean = true;
if (!DisconnectBlock(block, state, pindex, coins, &fClean))
- return error("VerifyDB() : *** irrecoverable inconsistency in block data at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString());
+ return error("VerifyDB(): *** irrecoverable inconsistency in block data at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString());
pindexState = pindex->pprev;
if (!fClean) {
nGoodTransactions = 0;
@@ -3027,7 +3046,7 @@ bool CVerifyDB::VerifyDB(CCoinsView *coinsview, int nCheckLevel, int nCheckDepth
return true;
}
if (pindexFailure)
- return error("VerifyDB() : *** coin database inconsistencies found (last %i blocks, %i good transactions before that)\n", chainActive.Height() - pindexFailure->nHeight + 1, nGoodTransactions);
+ return error("VerifyDB(): *** coin database inconsistencies found (last %i blocks, %i good transactions before that)\n", chainActive.Height() - pindexFailure->nHeight + 1, nGoodTransactions);
// check level 4: try reconnecting blocks
if (nCheckLevel >= 4) {
@@ -3038,9 +3057,9 @@ bool CVerifyDB::VerifyDB(CCoinsView *coinsview, int nCheckLevel, int nCheckDepth
pindex = chainActive.Next(pindex);
CBlock block;
if (!ReadBlockFromDisk(block, pindex))
- return error("VerifyDB() : *** ReadBlockFromDisk failed at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString());
+ return error("VerifyDB(): *** ReadBlockFromDisk failed at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString());
if (!ConnectBlock(block, state, pindex, coins))
- return error("VerifyDB() : *** found unconnectable block at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString());
+ return error("VerifyDB(): *** found unconnectable block at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString());
}
}
@@ -3086,18 +3105,18 @@ bool InitBlockIndex() {
CDiskBlockPos blockPos;
CValidationState state;
if (!FindBlockPos(state, blockPos, nBlockSize+8, 0, block.GetBlockTime()))
- return error("LoadBlockIndex() : FindBlockPos failed");
+ return error("LoadBlockIndex(): FindBlockPos failed");
if (!WriteBlockToDisk(block, blockPos))
- return error("LoadBlockIndex() : writing genesis block to disk failed");
+ return error("LoadBlockIndex(): writing genesis block to disk failed");
CBlockIndex *pindex = AddToBlockIndex(block);
if (!ReceivedBlockTransactions(block, state, pindex, blockPos))
- return error("LoadBlockIndex() : genesis block not accepted");
+ return error("LoadBlockIndex(): genesis block not accepted");
if (!ActivateBestChain(state, &block))
- return error("LoadBlockIndex() : genesis block cannot be activated");
+ return error("LoadBlockIndex(): genesis block cannot be activated");
// Force a chainstate write so that when we VerifyDB in a moment, it doesn't check stale data
return FlushStateToDisk(state, FLUSH_STATE_ALWAYS);
} catch (const std::runtime_error& e) {
- return error("LoadBlockIndex() : failed to initialize block database: %s", e.what());
+ return error("LoadBlockIndex(): failed to initialize block database: %s", e.what());
}
}
@@ -3197,7 +3216,7 @@ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp)
}
}
} catch (const std::exception& e) {
- LogPrintf("%s : Deserialize or I/O error - %s", __func__, e.what());
+ LogPrintf("%s: Deserialize or I/O error - %s", __func__, e.what());
}
}
} catch (const std::runtime_error& e) {
@@ -3261,7 +3280,7 @@ string GetWarnings(string strFor)
return strStatusBar;
else if (strFor == "rpc")
return strRPC;
- assert(!"GetWarnings() : invalid parameter");
+ assert(!"GetWarnings(): invalid parameter");
return "error";
}
@@ -3431,7 +3450,7 @@ void static ProcessGetData(CNode* pfrom)
bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, int64_t nTimeReceived)
{
RandAddSeedPerfmon();
- LogPrint("net", "received: %s (%u bytes) peer=%d\n", strCommand, vRecv.size(), pfrom->id);
+ LogPrint("net", "received: %s (%u bytes) peer=%d\n", SanitizeString(strCommand), vRecv.size(), pfrom->id);
if (mapArgs.count("-dropmessagestest") && GetRand(atoi(mapArgs["-dropmessagestest"])) == 0)
{
LogPrintf("dropmessagestest DROPPING RECV MESSAGE\n");
@@ -3828,7 +3847,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
vWorkQueue.push_back(inv.hash);
vEraseQueue.push_back(inv.hash);
- LogPrint("mempool", "AcceptToMemoryPool: peer=%d %s : accepted %s (poolsz %u)\n",
+ LogPrint("mempool", "AcceptToMemoryPool: peer=%d %s: accepted %s (poolsz %u)\n",
pfrom->id, pfrom->cleanSubVer,
tx.GetHash().ToString(),
mempool.mapTx.size());
@@ -4266,7 +4285,7 @@ bool ProcessMessages(CNode* pfrom)
// Scan for message start
if (memcmp(msg.hdr.pchMessageStart, Params().MessageStart(), MESSAGE_START_SIZE) != 0) {
- LogPrintf("PROCESSMESSAGE: INVALID MESSAGESTART %s peer=%d\n", msg.hdr.GetCommand(), pfrom->id);
+ LogPrintf("PROCESSMESSAGE: INVALID MESSAGESTART %s peer=%d\n", SanitizeString(msg.hdr.GetCommand()), pfrom->id);
fOk = false;
break;
}
@@ -4275,7 +4294,7 @@ bool ProcessMessages(CNode* pfrom)
CMessageHeader& hdr = msg.hdr;
if (!hdr.IsValid())
{
- LogPrintf("PROCESSMESSAGE: ERRORS IN HEADER %s peer=%d\n", hdr.GetCommand(), pfrom->id);
+ LogPrintf("PROCESSMESSAGE: ERRORS IN HEADER %s peer=%d\n", SanitizeString(hdr.GetCommand()), pfrom->id);
continue;
}
string strCommand = hdr.GetCommand();
@@ -4290,8 +4309,8 @@ bool ProcessMessages(CNode* pfrom)
memcpy(&nChecksum, &hash, sizeof(nChecksum));
if (nChecksum != hdr.nChecksum)
{
- LogPrintf("ProcessMessages(%s, %u bytes) : CHECKSUM ERROR nChecksum=%08x hdr.nChecksum=%08x\n",
- strCommand, nMessageSize, nChecksum, hdr.nChecksum);
+ LogPrintf("ProcessMessages(%s, %u bytes): CHECKSUM ERROR nChecksum=%08x hdr.nChecksum=%08x\n",
+ SanitizeString(strCommand), nMessageSize, nChecksum, hdr.nChecksum);
continue;
}
@@ -4308,12 +4327,12 @@ bool ProcessMessages(CNode* pfrom)
if (strstr(e.what(), "end of data"))
{
// Allow exceptions from under-length message on vRecv
- LogPrintf("ProcessMessages(%s, %u bytes) : Exception '%s' caught, normally caused by a message being shorter than its stated length\n", strCommand, nMessageSize, e.what());
+ LogPrintf("ProcessMessages(%s, %u bytes): Exception '%s' caught, normally caused by a message being shorter than its stated length\n", SanitizeString(strCommand), nMessageSize, e.what());
}
else if (strstr(e.what(), "size too large"))
{
// Allow exceptions from over-long size
- LogPrintf("ProcessMessages(%s, %u bytes) : Exception '%s' caught\n", strCommand, nMessageSize, e.what());
+ LogPrintf("ProcessMessages(%s, %u bytes): Exception '%s' caught\n", SanitizeString(strCommand), nMessageSize, e.what());
}
else
{
@@ -4330,7 +4349,7 @@ bool ProcessMessages(CNode* pfrom)
}
if (!fRet)
- LogPrintf("ProcessMessage(%s, %u bytes) FAILED peer=%d\n", strCommand, nMessageSize, pfrom->id);
+ LogPrintf("ProcessMessage(%s, %u bytes) FAILED peer=%d\n", SanitizeString(strCommand), nMessageSize, pfrom->id);
break;
}
@@ -4527,6 +4546,15 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
LogPrintf("Peer=%d is stalling block download, disconnecting\n", pto->id);
pto->fDisconnect = true;
}
+ // In case there is a block that has been in flight from this peer for (2 + 0.5 * N) times the block interval
+ // (with N the number of validated blocks that were in flight at the time it was requested), disconnect due to
+ // timeout. We compensate for in-flight blocks to prevent killing off peers due to our own downstream link
+ // being saturated. We only count validated in-flight blocks so peers can't advertize nonexisting block hashes
+ // to unreasonably increase our timeout.
+ if (!pto->fDisconnect && state.vBlocksInFlight.size() > 0 && state.vBlocksInFlight.front().nTime < nNow - 500000 * Params().TargetSpacing() * (4 + state.vBlocksInFlight.front().nValidatedQueuedBefore)) {
+ LogPrintf("Timeout downloading block %s from peer=%d, disconnecting\n", state.vBlocksInFlight.front().hash.ToString(), pto->id);
+ pto->fDisconnect = true;
+ }
//
// Message: getdata (blocks)
diff --git a/src/main.h b/src/main.h
index 2b260a665b..936cd43e99 100644
--- a/src/main.h
+++ b/src/main.h
@@ -45,7 +45,6 @@ class CScriptCheck;
class CValidationInterface;
class CValidationState;
-struct CBlockTemplate;
struct CNodeStateStats;
/** Default for -blockmaxsize and -blockminsize, which control the range of sizes the mining code will create **/
@@ -206,7 +205,7 @@ void FlushStateToDisk();
/** (try to) add transaction to memory pool **/
bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransaction &tx, bool fLimitFree,
- bool* pfMissingInputs, bool fRejectInsaneFee=false);
+ bool* pfMissingInputs, bool fRejectAbsurdFee=false);
struct CNodeStateStats {
@@ -513,17 +512,6 @@ extern CCoinsViewCache *pcoinsTip;
/** Global variable that points to the active block tree (protected by cs_main) */
extern CBlockTreeDB *pblocktree;
-struct CBlockTemplate
-{
- CBlock block;
- std::vector<CAmount> vTxFees;
- std::vector<int64_t> vTxSigOps;
-};
-
-
-
-
-
class CValidationInterface {
protected:
diff --git a/src/miner.cpp b/src/miner.cpp
index 87cb158333..e359654d7b 100644
--- a/src/miner.cpp
+++ b/src/miner.cpp
@@ -6,7 +6,6 @@
#include "miner.h"
#include "amount.h"
-#include "primitives/block.h"
#include "primitives/transaction.h"
#include "hash.h"
#include "main.h"
@@ -333,7 +332,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
CValidationState state;
if (!TestBlockValidity(state, *pblock, pindexPrev, false, false))
- throw std::runtime_error("CreateNewBlock() : TestBlockValidity failed");
+ throw std::runtime_error("CreateNewBlock(): TestBlockValidity failed");
}
return pblocktemplate.release();
@@ -363,8 +362,6 @@ void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int&
//
// Internal miner
//
-double dHashesPerSec = 0.0;
-int64_t nHPSTimerStart = 0;
//
// ScanHash scans nonces looking for a hash with at least some zero bits.
@@ -394,10 +391,8 @@ bool static ScanHash(const CBlockHeader *pblock, uint32_t& nNonce, uint256 *phas
return true;
// If nothing found after trying for a while, return -1
- if ((nNonce & 0xffff) == 0)
- return false;
if ((nNonce & 0xfff) == 0)
- boost::this_thread::interruption_point();
+ return false;
}
}
@@ -420,7 +415,7 @@ static bool ProcessBlockFound(CBlock* pblock, CWallet& wallet, CReserveKey& rese
{
LOCK(cs_main);
if (pblock->hashPrevBlock != chainActive.Tip()->GetBlockHash())
- return error("BitcoinMiner : generated block is stale");
+ return error("BitcoinMiner: generated block is stale");
}
// Remove key from key pool
@@ -435,7 +430,7 @@ static bool ProcessBlockFound(CBlock* pblock, CWallet& wallet, CReserveKey& rese
// Process this block the same as if we had received it from another node
CValidationState state;
if (!ProcessNewBlock(state, NULL, pblock))
- return error("BitcoinMiner : ProcessNewBlock, block not accepted");
+ return error("BitcoinMiner: ProcessNewBlock, block not accepted");
return true;
}
@@ -484,14 +479,9 @@ void static BitcoinMiner(CWallet *pwallet)
arith_uint256 hashTarget = arith_uint256().SetCompact(pblock->nBits);
uint256 hash;
uint32_t nNonce = 0;
- uint32_t nOldNonce = 0;
while (true) {
- bool fFound = ScanHash(pblock, nNonce, &hash);
- uint32_t nHashesDone = nNonce - nOldNonce;
- nOldNonce = nNonce;
-
// Check if something found
- if (fFound)
+ if (ScanHash(pblock, nNonce, &hash))
{
if (UintToArith256(hash) <= hashTarget)
{
@@ -513,35 +503,6 @@ void static BitcoinMiner(CWallet *pwallet)
}
}
- // Meter hashes/sec
- static int64_t nHashCounter;
- if (nHPSTimerStart == 0)
- {
- nHPSTimerStart = GetTimeMillis();
- nHashCounter = 0;
- }
- else
- nHashCounter += nHashesDone;
- if (GetTimeMillis() - nHPSTimerStart > 4000)
- {
- static CCriticalSection cs;
- {
- LOCK(cs);
- if (GetTimeMillis() - nHPSTimerStart > 4000)
- {
- dHashesPerSec = 1000.0 * nHashCounter / (GetTimeMillis() - nHPSTimerStart);
- nHPSTimerStart = GetTimeMillis();
- nHashCounter = 0;
- static int64_t nLogTime;
- if (GetTime() - nLogTime > 30 * 60)
- {
- nLogTime = GetTime();
- LogPrintf("hashmeter %6.0f khash/s\n", dHashesPerSec/1000.0);
- }
- }
- }
- }
-
// Check for stop or if block needs to be rebuilt
boost::this_thread::interruption_point();
// Regtest mode doesn't require peers
diff --git a/src/miner.h b/src/miner.h
index 3c08b030f6..5d5c9c86c7 100644
--- a/src/miner.h
+++ b/src/miner.h
@@ -6,16 +6,21 @@
#ifndef BITCOIN_MINER_H
#define BITCOIN_MINER_H
+#include "primitives/block.h"
+
#include <stdint.h>
-class CBlock;
-class CBlockHeader;
class CBlockIndex;
class CReserveKey;
class CScript;
class CWallet;
-struct CBlockTemplate;
+struct CBlockTemplate
+{
+ CBlock block;
+ std::vector<CAmount> vTxFees;
+ std::vector<int64_t> vTxSigOps;
+};
/** Run the miner threads */
void GenerateBitcoins(bool fGenerate, CWallet* pwallet, int nThreads);
@@ -26,7 +31,4 @@ CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey);
void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& nExtraNonce);
void UpdateTime(CBlockHeader* block, const CBlockIndex* pindexPrev);
-extern double dHashesPerSec;
-extern int64_t nHPSTimerStart;
-
#endif // BITCOIN_MINER_H
diff --git a/src/net.cpp b/src/net.cpp
index 8cf2d0ffec..3c3666615e 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -157,56 +157,6 @@ CAddress GetLocalAddress(const CNetAddr *paddrPeer)
return ret;
}
-bool RecvLine(SOCKET hSocket, string& strLine)
-{
- strLine = "";
- while (true)
- {
- char c;
- int nBytes = recv(hSocket, &c, 1, 0);
- if (nBytes > 0)
- {
- if (c == '\n')
- continue;
- if (c == '\r')
- return true;
- strLine += c;
- if (strLine.size() >= 9000)
- return true;
- }
- else if (nBytes <= 0)
- {
- boost::this_thread::interruption_point();
- if (nBytes < 0)
- {
- int nErr = WSAGetLastError();
- if (nErr == WSAEMSGSIZE)
- continue;
- if (nErr == WSAEWOULDBLOCK || nErr == WSAEINTR || nErr == WSAEINPROGRESS)
- {
- MilliSleep(10);
- continue;
- }
- }
- if (!strLine.empty())
- return true;
- if (nBytes == 0)
- {
- // socket closed
- LogPrint("net", "socket closed\n");
- return false;
- }
- else
- {
- // socket error
- int nErr = WSAGetLastError();
- LogPrint("net", "recv failed: %s\n", NetworkErrorString(nErr));
- return false;
- }
- }
- }
-}
-
int GetnScore(const CService& addr)
{
LOCK(cs_mapLocalHost);
@@ -1070,7 +1020,7 @@ void ThreadMapPort()
catch (const boost::thread_interrupted&)
{
r = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, port.c_str(), "TCP", 0);
- LogPrintf("UPNP_DeletePortMapping() returned : %d\n", r);
+ LogPrintf("UPNP_DeletePortMapping() returned: %d\n", r);
freeUPNPDevlist(devlist); devlist = 0;
FreeUPNPUrls(&urls);
throw;
@@ -1847,21 +1797,21 @@ bool CAddrDB::Write(const CAddrMan& addr)
FILE *file = fopen(pathTmp.string().c_str(), "wb");
CAutoFile fileout(file, SER_DISK, CLIENT_VERSION);
if (fileout.IsNull())
- return error("%s : Failed to open file %s", __func__, pathTmp.string());
+ return error("%s: Failed to open file %s", __func__, pathTmp.string());
// Write and commit header, data
try {
fileout << ssPeers;
}
catch (const std::exception& e) {
- return error("%s : Serialize or I/O error - %s", __func__, e.what());
+ return error("%s: Serialize or I/O error - %s", __func__, e.what());
}
FileCommit(fileout.Get());
fileout.fclose();
// replace existing peers.dat, if any, with new peers.dat.XXXX
if (!RenameOver(pathTmp, pathAddr))
- return error("%s : Rename-into-place failed", __func__);
+ return error("%s: Rename-into-place failed", __func__);
return true;
}
@@ -1872,7 +1822,7 @@ bool CAddrDB::Read(CAddrMan& addr)
FILE *file = fopen(pathAddr.string().c_str(), "rb");
CAutoFile filein(file, SER_DISK, CLIENT_VERSION);
if (filein.IsNull())
- return error("%s : Failed to open file %s", __func__, pathAddr.string());
+ return error("%s: Failed to open file %s", __func__, pathAddr.string());
// use file size to size memory buffer
int fileSize = boost::filesystem::file_size(pathAddr);
@@ -1890,7 +1840,7 @@ bool CAddrDB::Read(CAddrMan& addr)
filein >> hashIn;
}
catch (const std::exception& e) {
- return error("%s : Deserialize or I/O error - %s", __func__, e.what());
+ return error("%s: Deserialize or I/O error - %s", __func__, e.what());
}
filein.fclose();
@@ -1899,7 +1849,7 @@ bool CAddrDB::Read(CAddrMan& addr)
// verify stored checksum matches input data
uint256 hashTmp = Hash(ssPeers.begin(), ssPeers.end());
if (hashIn != hashTmp)
- return error("%s : Checksum mismatch, data corrupted", __func__);
+ return error("%s: Checksum mismatch, data corrupted", __func__);
unsigned char pchMsgTmp[4];
try {
@@ -1908,13 +1858,13 @@ bool CAddrDB::Read(CAddrMan& addr)
// ... verify the network matches ours
if (memcmp(pchMsgTmp, Params().MessageStart(), sizeof(pchMsgTmp)))
- return error("%s : Invalid network magic number", __func__);
+ return error("%s: Invalid network magic number", __func__);
// de-serialize address data into one CAddrMan object
ssPeers >> addr;
}
catch (const std::exception& e) {
- return error("%s : Deserialize or I/O error - %s", __func__, e.what());
+ return error("%s: Deserialize or I/O error - %s", __func__, e.what());
}
return true;
@@ -2021,7 +1971,7 @@ void CNode::BeginMessage(const char* pszCommand) EXCLUSIVE_LOCK_FUNCTION(cs_vSen
ENTER_CRITICAL_SECTION(cs_vSend);
assert(ssSend.size() == 0);
ssSend << CMessageHeader(pszCommand, 0);
- LogPrint("net", "sending: %s ", pszCommand);
+ LogPrint("net", "sending: %s ", SanitizeString(pszCommand));
}
void CNode::AbortMessage() UNLOCK_FUNCTION(cs_vSend)
diff --git a/src/net.h b/src/net.h
index bdb1edd50b..b78665b5c6 100644
--- a/src/net.h
+++ b/src/net.h
@@ -61,7 +61,6 @@ unsigned int ReceiveFloodSize();
unsigned int SendBufferSize();
void AddOneShot(std::string strDest);
-bool RecvLine(SOCKET hSocket, std::string& strLine);
void AddressCurrentlyConnected(const CService& addr);
CNode* FindNode(const CNetAddr& ip);
CNode* FindNode(const std::string& addrName);
diff --git a/src/pow.cpp b/src/pow.cpp
index 90bbff0a33..e49f0d104c 100644
--- a/src/pow.cpp
+++ b/src/pow.cpp
@@ -89,11 +89,11 @@ bool CheckProofOfWork(uint256 hash, unsigned int nBits)
// Check range
if (fNegative || bnTarget == 0 || fOverflow || bnTarget > Params().ProofOfWorkLimit())
- return error("CheckProofOfWork() : nBits below minimum work");
+ return error("CheckProofOfWork(): nBits below minimum work");
// Check proof of work matches claimed amount
if (UintToArith256(hash) > bnTarget)
- return error("CheckProofOfWork() : hash doesn't match nBits");
+ return error("CheckProofOfWork(): hash doesn't match nBits");
return true;
}
diff --git a/src/primitives/block.h b/src/primitives/block.h
index d77ab162e0..c7ed6f723a 100644
--- a/src/primitives/block.h
+++ b/src/primitives/block.h
@@ -24,7 +24,7 @@ class CBlockHeader
{
public:
// header
- static const int32_t CURRENT_VERSION=2;
+ static const int32_t CURRENT_VERSION=3;
int32_t nVersion;
uint256 hashPrevBlock;
uint256 hashMerkleRoot;
diff --git a/src/primitives/transaction.cpp b/src/primitives/transaction.cpp
index 848d4d3e60..606dbea798 100644
--- a/src/primitives/transaction.cpp
+++ b/src/primitives/transaction.cpp
@@ -94,7 +94,7 @@ CAmount CTransaction::GetValueOut() const
{
nValueOut += it->nValue;
if (!MoneyRange(it->nValue) || !MoneyRange(nValueOut))
- throw std::runtime_error("CTransaction::GetValueOut() : value out of range");
+ throw std::runtime_error("CTransaction::GetValueOut(): value out of range");
}
return nValueOut;
}
diff --git a/src/protocol.cpp b/src/protocol.cpp
index 2dfded43be..74ac706d60 100644
--- a/src/protocol.cpp
+++ b/src/protocol.cpp
@@ -66,7 +66,7 @@ bool CMessageHeader::IsValid() const
// Message size
if (nMessageSize > MAX_SIZE)
{
- LogPrintf("CMessageHeader::IsValid() : (%s, %u bytes) nMessageSize > MAX_SIZE\n", GetCommand(), nMessageSize);
+ LogPrintf("CMessageHeader::IsValid(): (%s, %u bytes) nMessageSize > MAX_SIZE\n", GetCommand(), nMessageSize);
return false;
}
@@ -117,7 +117,7 @@ CInv::CInv(const std::string& strType, const uint256& hashIn)
}
}
if (i == ARRAYLEN(ppszTypeName))
- throw std::out_of_range(strprintf("CInv::CInv(string, uint256) : unknown type '%s'", strType));
+ throw std::out_of_range(strprintf("CInv::CInv(string, uint256): unknown type '%s'", strType));
hash = hashIn;
}
@@ -134,7 +134,7 @@ bool CInv::IsKnownType() const
const char* CInv::GetCommand() const
{
if (!IsKnownType())
- throw std::out_of_range(strprintf("CInv::GetCommand() : type=%d unknown type", type));
+ throw std::out_of_range(strprintf("CInv::GetCommand(): type=%d unknown type", type));
return ppszTypeName[type];
}
diff --git a/src/qt/addresstablemodel.cpp b/src/qt/addresstablemodel.cpp
index bfb5bf3fec..162ecdba4e 100644
--- a/src/qt/addresstablemodel.cpp
+++ b/src/qt/addresstablemodel.cpp
@@ -114,7 +114,7 @@ public:
case CT_NEW:
if(inModel)
{
- qWarning() << "AddressTablePriv::updateEntry : Warning: Got CT_NEW, but entry is already in model";
+ qWarning() << "AddressTablePriv::updateEntry: Warning: Got CT_NEW, but entry is already in model";
break;
}
parent->beginInsertRows(QModelIndex(), lowerIndex, lowerIndex);
@@ -124,7 +124,7 @@ public:
case CT_UPDATED:
if(!inModel)
{
- qWarning() << "AddressTablePriv::updateEntry : Warning: Got CT_UPDATED, but entry is not in model";
+ qWarning() << "AddressTablePriv::updateEntry: Warning: Got CT_UPDATED, but entry is not in model";
break;
}
lower->type = newEntryType;
@@ -134,7 +134,7 @@ public:
case CT_DELETED:
if(!inModel)
{
- qWarning() << "AddressTablePriv::updateEntry : Warning: Got CT_DELETED, but entry is not in model";
+ qWarning() << "AddressTablePriv::updateEntry: Warning: Got CT_DELETED, but entry is not in model";
break;
}
parent->beginRemoveRows(QModelIndex(), lowerIndex, upperIndex-1);
diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp
index 1adf4e00cb..73c684e489 100644
--- a/src/qt/bitcoin.cpp
+++ b/src/qt/bitcoin.cpp
@@ -89,10 +89,24 @@ static std::string Translate(const char* psz)
return QCoreApplication::translate("bitcoin-core", psz).toStdString();
}
+static QString GetLangTerritory()
+{
+ QSettings settings;
+ // Get desired locale (e.g. "de_DE")
+ // 1) System default language
+ QString lang_territory = QLocale::system().name();
+ // 2) Language from QSettings
+ QString lang_territory_qsettings = settings.value("language", "").toString();
+ if(!lang_territory_qsettings.isEmpty())
+ lang_territory = lang_territory_qsettings;
+ // 3) -lang command line argument
+ lang_territory = QString::fromStdString(GetArg("-lang", lang_territory.toStdString()));
+ return lang_territory;
+}
+
/** Set up translations */
static void initTranslations(QTranslator &qtTranslatorBase, QTranslator &qtTranslator, QTranslator &translatorBase, QTranslator &translator)
{
- QSettings settings;
// Remove old translators
QApplication::removeTranslator(&qtTranslatorBase);
@@ -102,13 +116,7 @@ static void initTranslations(QTranslator &qtTranslatorBase, QTranslator &qtTrans
// Get desired locale (e.g. "de_DE")
// 1) System default language
- QString lang_territory = QLocale::system().name();
- // 2) Language from QSettings
- QString lang_territory_qsettings = settings.value("language", "").toString();
- if(!lang_territory_qsettings.isEmpty())
- lang_territory = lang_territory_qsettings;
- // 3) -lang command line argument
- lang_territory = QString::fromStdString(GetArg("-lang", lang_territory.toStdString()));
+ QString lang_territory = GetLangTerritory();
// Convert to "de" only by truncating "_DE"
QString lang = lang_territory;
@@ -498,8 +506,6 @@ int main(int argc, char *argv[])
Q_INIT_RESOURCE(bitcoin);
Q_INIT_RESOURCE(bitcoin_locale);
- GUIUtil::SubstituteFonts();
-
BitcoinApplication app(argc, argv);
#if QT_VERSION > 0x050100
// Generate high-dpi pixmaps
@@ -521,6 +527,7 @@ int main(int argc, char *argv[])
QApplication::setOrganizationName(QAPP_ORG_NAME);
QApplication::setOrganizationDomain(QAPP_ORG_DOMAIN);
QApplication::setApplicationName(QAPP_APP_NAME_DEFAULT);
+ GUIUtil::SubstituteFonts(GetLangTerritory());
/// 4. Initialization of translations, so that intro dialog is in user's language
// Now that QSettings are accessible, initialize translations
diff --git a/src/qt/bitcoin.qrc b/src/qt/bitcoin.qrc
index bcaf95d91c..63af146fd0 100644
--- a/src/qt/bitcoin.qrc
+++ b/src/qt/bitcoin.qrc
@@ -46,9 +46,6 @@
<file alias="about_qt">res/icons/about_qt.png</file>
<file alias="verify">res/icons/verify.png</file>
</qresource>
- <qresource prefix="/images">
- <file alias="about">res/images/about.png</file>
- </qresource>
<qresource prefix="/movies">
<file alias="spinner-000">res/movies/spinner-000.png</file>
<file alias="spinner-001">res/movies/spinner-001.png</file>
diff --git a/src/qt/bitcoinamountfield.cpp b/src/qt/bitcoinamountfield.cpp
index fdb9bcd6d6..d31a1e018b 100644
--- a/src/qt/bitcoinamountfield.cpp
+++ b/src/qt/bitcoinamountfield.cpp
@@ -20,6 +20,7 @@
class AmountSpinBox: public QAbstractSpinBox
{
Q_OBJECT
+
public:
explicit AmountSpinBox(QWidget *parent):
QAbstractSpinBox(parent),
@@ -72,23 +73,6 @@ public:
setValue(val);
}
- StepEnabled stepEnabled() const
- {
- StepEnabled rv = 0;
- if(text().isEmpty()) // Allow step-up with empty field
- return StepUpEnabled;
- bool valid = false;
- CAmount val = value(&valid);
- if(valid)
- {
- if(val > 0)
- rv |= StepDownEnabled;
- if(val < BitcoinUnits::maxMoney())
- rv |= StepUpEnabled;
- }
- return rv;
- }
-
void setDisplayUnit(int unit)
{
bool valid = false;
@@ -139,6 +123,7 @@ public:
}
return cachedMinimumSizeHint;
}
+
private:
int currentUnit;
CAmount singleStep;
@@ -179,6 +164,26 @@ protected:
return QAbstractSpinBox::event(event);
}
+ StepEnabled stepEnabled() const
+ {
+ if (isReadOnly()) // Disable steps when AmountSpinBox is read-only
+ return StepNone;
+ if (text().isEmpty()) // Allow step-up with empty field
+ return StepUpEnabled;
+
+ StepEnabled rv = 0;
+ bool valid = false;
+ CAmount val = value(&valid);
+ if(valid)
+ {
+ if(val > 0)
+ rv |= StepDownEnabled;
+ if(val < BitcoinUnits::maxMoney())
+ rv |= StepUpEnabled;
+ }
+ return rv;
+ }
+
signals:
void valueChanged();
};
@@ -273,7 +278,6 @@ void BitcoinAmountField::setValue(const CAmount& value)
void BitcoinAmountField::setReadOnly(bool fReadOnly)
{
amount->setReadOnly(fReadOnly);
- unit->setEnabled(!fReadOnly);
}
void BitcoinAmountField::unitChanged(int idx)
diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp
index 2810eae052..09f784387e 100644
--- a/src/qt/bitcoingui.cpp
+++ b/src/qt/bitcoingui.cpp
@@ -76,12 +76,14 @@ BitcoinGUI::BitcoinGUI(const NetworkStyle *networkStyle, QWidget *parent) :
historyAction(0),
quitAction(0),
sendCoinsAction(0),
+ sendCoinsMenuAction(0),
usedSendingAddressesAction(0),
usedReceivingAddressesAction(0),
signMessageAction(0),
verifyMessageAction(0),
aboutAction(0),
receiveCoinsAction(0),
+ receiveCoinsMenuAction(0),
optionsAction(0),
toggleHideAction(0),
encryptWalletAction(0),
@@ -162,6 +164,9 @@ BitcoinGUI::BitcoinGUI(const NetworkStyle *networkStyle, QWidget *parent) :
// Create status bar
statusBar();
+
+ // Disable size grip because it looks ugly and nobody needs it
+ statusBar()->setSizeGripEnabled(false);
// Status bar notification icons
QFrame *frameBlocks = new QFrame();
@@ -256,6 +261,10 @@ void BitcoinGUI::createActions(const NetworkStyle *networkStyle)
sendCoinsAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_2));
tabGroup->addAction(sendCoinsAction);
+ sendCoinsMenuAction = new QAction(TextColorIcon(":/icons/send"), sendCoinsAction->text(), this);
+ sendCoinsMenuAction->setStatusTip(sendCoinsAction->statusTip());
+ sendCoinsMenuAction->setToolTip(sendCoinsMenuAction->statusTip());
+
receiveCoinsAction = new QAction(SingleColorIcon(":/icons/receiving_addresses"), tr("&Receive"), this);
receiveCoinsAction->setStatusTip(tr("Request payments (generates QR codes and bitcoin: URIs)"));
receiveCoinsAction->setToolTip(receiveCoinsAction->statusTip());
@@ -263,6 +272,10 @@ void BitcoinGUI::createActions(const NetworkStyle *networkStyle)
receiveCoinsAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_3));
tabGroup->addAction(receiveCoinsAction);
+ receiveCoinsMenuAction = new QAction(TextColorIcon(":/icons/receiving_addresses"), receiveCoinsAction->text(), this);
+ receiveCoinsMenuAction->setStatusTip(receiveCoinsAction->statusTip());
+ receiveCoinsMenuAction->setToolTip(receiveCoinsMenuAction->statusTip());
+
historyAction = new QAction(SingleColorIcon(":/icons/history"), tr("&Transactions"), this);
historyAction->setStatusTip(tr("Browse transaction history"));
historyAction->setToolTip(historyAction->statusTip());
@@ -277,8 +290,12 @@ void BitcoinGUI::createActions(const NetworkStyle *networkStyle)
connect(overviewAction, SIGNAL(triggered()), this, SLOT(gotoOverviewPage()));
connect(sendCoinsAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized()));
connect(sendCoinsAction, SIGNAL(triggered()), this, SLOT(gotoSendCoinsPage()));
+ connect(sendCoinsMenuAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized()));
+ connect(sendCoinsMenuAction, SIGNAL(triggered()), this, SLOT(gotoSendCoinsPage()));
connect(receiveCoinsAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized()));
connect(receiveCoinsAction, SIGNAL(triggered()), this, SLOT(gotoReceiveCoinsPage()));
+ connect(receiveCoinsMenuAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized()));
+ connect(receiveCoinsMenuAction, SIGNAL(triggered()), this, SLOT(gotoReceiveCoinsPage()));
connect(historyAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized()));
connect(historyAction, SIGNAL(triggered()), this, SLOT(gotoHistoryPage()));
#endif // ENABLE_WALLET
@@ -475,7 +492,9 @@ void BitcoinGUI::setWalletActionsEnabled(bool enabled)
{
overviewAction->setEnabled(enabled);
sendCoinsAction->setEnabled(enabled);
+ sendCoinsMenuAction->setEnabled(enabled);
receiveCoinsAction->setEnabled(enabled);
+ receiveCoinsMenuAction->setEnabled(enabled);
historyAction->setEnabled(enabled);
encryptWalletAction->setEnabled(enabled);
backupWalletAction->setEnabled(enabled);
@@ -522,8 +541,8 @@ void BitcoinGUI::createTrayIconMenu()
// Configuration of the tray icon (or dock icon) icon menu
trayIconMenu->addAction(toggleHideAction);
trayIconMenu->addSeparator();
- trayIconMenu->addAction(sendCoinsAction);
- trayIconMenu->addAction(receiveCoinsAction);
+ trayIconMenu->addAction(sendCoinsMenuAction);
+ trayIconMenu->addAction(receiveCoinsMenuAction);
trayIconMenu->addSeparator();
trayIconMenu->addAction(signMessageAction);
trayIconMenu->addAction(verifyMessageAction);
diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h
index 7509a00734..3216a7398e 100644
--- a/src/qt/bitcoingui.h
+++ b/src/qt/bitcoingui.h
@@ -90,12 +90,14 @@ private:
QAction *historyAction;
QAction *quitAction;
QAction *sendCoinsAction;
+ QAction *sendCoinsMenuAction;
QAction *usedSendingAddressesAction;
QAction *usedReceivingAddressesAction;
QAction *signMessageAction;
QAction *verifyMessageAction;
QAction *aboutAction;
QAction *receiveCoinsAction;
+ QAction *receiveCoinsMenuAction;
QAction *optionsAction;
QAction *toggleHideAction;
QAction *encryptWalletAction;
diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp
index 493cdd6dd2..03d94f2e13 100644
--- a/src/qt/clientmodel.cpp
+++ b/src/qt/clientmodel.cpp
@@ -212,14 +212,14 @@ static void ShowProgress(ClientModel *clientmodel, const std::string &title, int
static void NotifyNumConnectionsChanged(ClientModel *clientmodel, int newNumConnections)
{
- // Too noisy: qDebug() << "NotifyNumConnectionsChanged : " + QString::number(newNumConnections);
+ // Too noisy: qDebug() << "NotifyNumConnectionsChanged: " + QString::number(newNumConnections);
QMetaObject::invokeMethod(clientmodel, "updateNumConnections", Qt::QueuedConnection,
Q_ARG(int, newNumConnections));
}
static void NotifyAlertChanged(ClientModel *clientmodel, const uint256 &hash, ChangeType status)
{
- qDebug() << "NotifyAlertChanged : " + QString::fromStdString(hash.GetHex()) + " status=" + QString::number(status);
+ qDebug() << "NotifyAlertChanged: " + QString::fromStdString(hash.GetHex()) + " status=" + QString::number(status);
QMetaObject::invokeMethod(clientmodel, "updateAlert", Qt::QueuedConnection,
Q_ARG(QString, QString::fromStdString(hash.GetHex())),
Q_ARG(int, status));
diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp
index 8422f316f9..3f4f082b8c 100644
--- a/src/qt/coincontroldialog.cpp
+++ b/src/qt/coincontroldialog.cpp
@@ -117,6 +117,10 @@ CoinControlDialog::CoinControlDialog(QWidget *parent) :
// (un)select all
connect(ui->pushButtonSelectAll, SIGNAL(clicked()), this, SLOT(buttonSelectAllClicked()));
+ // change coin control first column label due Qt4 bug.
+ // see https://github.com/bitcoin/bitcoin/issues/5716
+ ui->treeWidget->headerItem()->setText(COLUMN_CHECKBOX, QString());
+
ui->treeWidget->setColumnWidth(COLUMN_CHECKBOX, 84);
ui->treeWidget->setColumnWidth(COLUMN_AMOUNT, 100);
ui->treeWidget->setColumnWidth(COLUMN_LABEL, 170);
@@ -304,19 +308,19 @@ void CoinControlDialog::clipboardAmount()
// copy label "Fee" to clipboard
void CoinControlDialog::clipboardFee()
{
- GUIUtil::setClipboard(ui->labelCoinControlFee->text().left(ui->labelCoinControlFee->text().indexOf(" ")).replace("~", ""));
+ GUIUtil::setClipboard(ui->labelCoinControlFee->text().left(ui->labelCoinControlFee->text().indexOf(" ")).replace(ASYMP_UTF8, ""));
}
// copy label "After fee" to clipboard
void CoinControlDialog::clipboardAfterFee()
{
- GUIUtil::setClipboard(ui->labelCoinControlAfterFee->text().left(ui->labelCoinControlAfterFee->text().indexOf(" ")).replace("~", ""));
+ GUIUtil::setClipboard(ui->labelCoinControlAfterFee->text().left(ui->labelCoinControlAfterFee->text().indexOf(" ")).replace(ASYMP_UTF8, ""));
}
// copy label "Bytes" to clipboard
void CoinControlDialog::clipboardBytes()
{
- GUIUtil::setClipboard(ui->labelCoinControlBytes->text().replace("~", ""));
+ GUIUtil::setClipboard(ui->labelCoinControlBytes->text().replace(ASYMP_UTF8, ""));
}
// copy label "Priority" to clipboard
@@ -334,7 +338,7 @@ void CoinControlDialog::clipboardLowOutput()
// copy label "Change" to clipboard
void CoinControlDialog::clipboardChange()
{
- GUIUtil::setClipboard(ui->labelCoinControlChange->text().left(ui->labelCoinControlChange->text().indexOf(" ")).replace("~", ""));
+ GUIUtil::setClipboard(ui->labelCoinControlChange->text().left(ui->labelCoinControlChange->text().indexOf(" ")).replace(ASYMP_UTF8, ""));
}
// treeview: sort
@@ -600,16 +604,16 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog)
l2->setText(BitcoinUnits::formatWithUnit(nDisplayUnit, nAmount)); // Amount
l3->setText(BitcoinUnits::formatWithUnit(nDisplayUnit, nPayFee)); // Fee
l4->setText(BitcoinUnits::formatWithUnit(nDisplayUnit, nAfterFee)); // After Fee
- l5->setText(((nBytes > 0) ? "~" : "") + QString::number(nBytes)); // Bytes
+ l5->setText(((nBytes > 0) ? ASYMP_UTF8 : "") + QString::number(nBytes)); // Bytes
l6->setText(sPriorityLabel); // Priority
l7->setText(fDust ? tr("yes") : tr("no")); // Dust
l8->setText(BitcoinUnits::formatWithUnit(nDisplayUnit, nChange)); // Change
if (nPayFee > 0 && !(payTxFee.GetFeePerK() > 0 && fPayAtLeastCustomFee && nBytes < 1000))
{
- l3->setText("~" + l3->text());
- l4->setText("~" + l4->text());
+ l3->setText(ASYMP_UTF8 + l3->text());
+ l4->setText(ASYMP_UTF8 + l4->text());
if (nChange > 0)
- l8->setText("~" + l8->text());
+ l8->setText(ASYMP_UTF8 + l8->text());
}
// turn labels "red"
diff --git a/src/qt/coincontroldialog.h b/src/qt/coincontroldialog.h
index 0974443066..5a91876f1f 100644
--- a/src/qt/coincontroldialog.h
+++ b/src/qt/coincontroldialog.h
@@ -25,6 +25,8 @@ namespace Ui {
class CoinControlDialog;
}
+#define ASYMP_UTF8 "\xE2\x89\x88"
+
class CoinControlDialog : public QDialog
{
Q_OBJECT
diff --git a/src/qt/coincontroltreewidget.cpp b/src/qt/coincontroltreewidget.cpp
index 6cbcf7128d..5dcbf0c3f1 100644
--- a/src/qt/coincontroltreewidget.cpp
+++ b/src/qt/coincontroltreewidget.cpp
@@ -17,7 +17,8 @@ void CoinControlTreeWidget::keyPressEvent(QKeyEvent *event)
{
event->ignore();
int COLUMN_CHECKBOX = 0;
- this->currentItem()->setCheckState(COLUMN_CHECKBOX, ((this->currentItem()->checkState(COLUMN_CHECKBOX) == Qt::Checked) ? Qt::Unchecked : Qt::Checked));
+ if(this->currentItem())
+ this->currentItem()->setCheckState(COLUMN_CHECKBOX, ((this->currentItem()->checkState(COLUMN_CHECKBOX) == Qt::Checked) ? Qt::Unchecked : Qt::Checked));
}
else if (event->key() == Qt::Key_Escape) // press esc -> close dialog
{
@@ -29,4 +30,4 @@ void CoinControlTreeWidget::keyPressEvent(QKeyEvent *event)
{
this->QTreeWidget::keyPressEvent(event);
}
-} \ No newline at end of file
+}
diff --git a/src/qt/forms/helpmessagedialog.ui b/src/qt/forms/helpmessagedialog.ui
index 9ace9afd79..dc7df9d6c8 100644
--- a/src/qt/forms/helpmessagedialog.ui
+++ b/src/qt/forms/helpmessagedialog.ui
@@ -6,31 +6,76 @@
<rect>
<x>0</x>
<y>0</y>
- <width>585</width>
- <height>225</height>
+ <width>780</width>
+ <height>400</height>
</rect>
</property>
- <property name="font">
- <font>
- <pointsize>10</pointsize>
- </font>
- </property>
<property name="windowTitle">
<string notr="true">Bitcoin Core - Command-line options</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_2">
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <property name="leftMargin">
+ <number>12</number>
+ </property>
+ <property name="topMargin">
+ <number>12</number>
+ </property>
+ <property name="rightMargin">
+ <number>12</number>
+ </property>
+ <property name="bottomMargin">
+ <number>12</number>
+ </property>
<item>
- <widget class="QLabel" name="graphic">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Ignored">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
+ <layout class="QVBoxLayout" name="verticalLayoutLogo" stretch="0,0">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>4</number>
</property>
- <property name="pixmap">
- <pixmap resource="../bitcoin.qrc">:/images/about</pixmap>
+ <property name="rightMargin">
+ <number>0</number>
</property>
- </widget>
+ <item>
+ <widget class="QLabel" name="aboutLogo">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Ignored">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>100</width>
+ <height>100</height>
+ </size>
+ </property>
+ <property name="pixmap">
+ <pixmap resource="../bitcoin.qrc">:/icons/bitcoin</pixmap>
+ </property>
+ <property name="scaledContents">
+ <bool>true</bool>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QFrame" name="frame">
+ <property name="frameShape">
+ <enum>QFrame::NoFrame</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Raised</enum>
+ </property>
+ </widget>
+ </item>
+ </layout>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout">
@@ -43,6 +88,9 @@
</item>
<item>
<widget class="QScrollArea" name="scrollArea">
+ <property name="frameShape">
+ <enum>QFrame::NoFrame</enum>
+ </property>
<property name="verticalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOn</enum>
</property>
@@ -50,14 +98,6 @@
<bool>true</bool>
</property>
<widget class="QWidget" name="scrollAreaWidgetContents">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>447</width>
- <height>68</height>
- </rect>
- </property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QLabel" name="aboutMessage">
@@ -83,6 +123,22 @@
</widget>
</item>
<item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Fixed</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>4</width>
+ <height>4</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
<widget class="QDialogButtonBox" name="okButton">
<property name="orientation">
<enum>Qt::Horizontal</enum>
diff --git a/src/qt/forms/signverifymessagedialog.ui b/src/qt/forms/signverifymessagedialog.ui
index 40b2da3228..92f6430c51 100644
--- a/src/qt/forms/signverifymessagedialog.ui
+++ b/src/qt/forms/signverifymessagedialog.ui
@@ -30,7 +30,7 @@
<item>
<widget class="QLabel" name="infoLabel_SM">
<property name="text">
- <string>You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to.</string>
+ <string>You can sign messages/agreements with your addresses to prove you can receive bitcoins sent to them. Be careful not to sign anything vague or random, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to.</string>
</property>
<property name="textFormat">
<enum>Qt::PlainText</enum>
@@ -237,7 +237,7 @@
<item>
<widget class="QLabel" name="infoLabel_VM">
<property name="text">
- <string>Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack.</string>
+ <string>Enter the receiver's address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. Note that this only proves the signing party receives with the address, it cannot prove sendership of any transaction!</string>
</property>
<property name="textFormat">
<enum>Qt::PlainText</enum>
diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp
index c675235cc2..2a13f43ea4 100644
--- a/src/qt/guiutil.cpp
+++ b/src/qt/guiutil.cpp
@@ -67,6 +67,9 @@ static boost::filesystem::detail::utf8_codecvt_facet utf8;
#if defined(Q_OS_MAC)
extern double NSAppKitVersionNumber;
+#if !defined(NSAppKitVersionNumber10_8)
+#define NSAppKitVersionNumber10_8 1187
+#endif
#if !defined(NSAppKitVersionNumber10_9)
#define NSAppKitVersionNumber10_9 1265
#endif
@@ -383,7 +386,7 @@ void openDebugLogfile()
QDesktopServices::openUrl(QUrl::fromLocalFile(boostPathToQString(pathDebug)));
}
-void SubstituteFonts()
+void SubstituteFonts(const QString& language)
{
#if defined(Q_OS_MAC)
// Background:
@@ -393,12 +396,28 @@ void SubstituteFonts()
// If this fallback is not properly loaded, some characters may fail to
// render correctly.
//
+// The same thing happened with 10.10. .Helvetica Neue DeskInterface is now default.
+//
// Solution: If building with the 10.7 SDK or lower and the user's platform
// is 10.9 or higher at runtime, substitute the correct font. This needs to
// happen before the QApplication is created.
#if defined(MAC_OS_X_VERSION_MAX_ALLOWED) && MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_8
- if (floor(NSAppKitVersionNumber) >= NSAppKitVersionNumber10_9)
- QFont::insertSubstitution(".Lucida Grande UI", "Lucida Grande");
+ if (floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_8)
+ {
+ if (floor(NSAppKitVersionNumber) <= NSAppKitVersionNumber10_9)
+ /* On a 10.9 - 10.9.x system */
+ QFont::insertSubstitution(".Lucida Grande UI", "Lucida Grande");
+ else
+ {
+ /* 10.10 or later system */
+ if (language == "zh_CN" || language == "zh_TW" || language == "zh_HK") // traditional or simplified Chinese
+ QFont::insertSubstitution(".Helvetica Neue DeskInterface", "Heiti SC");
+ else if (language == "ja") // Japanesee
+ QFont::insertSubstitution(".Helvetica Neue DeskInterface", "Songti SC");
+ else
+ QFont::insertSubstitution(".Helvetica Neue DeskInterface", "Lucida Grande");
+ }
+ }
#endif
#endif
}
@@ -696,7 +715,18 @@ LSSharedFileListItemRef findStartupItemInList(LSSharedFileListRef list, CFURLRef
LSSharedFileListItemRef item = (LSSharedFileListItemRef)CFArrayGetValueAtIndex(listSnapshot, i);
UInt32 resolutionFlags = kLSSharedFileListNoUserInteraction | kLSSharedFileListDoNotMountVolumes;
CFURLRef currentItemURL = NULL;
- LSSharedFileListItemResolve(item, resolutionFlags, &currentItemURL, NULL);
+
+#if defined(MAC_OS_X_VERSION_MAX_ALLOWED) && MAC_OS_X_VERSION_MAX_ALLOWED >= 10100
+ if(&LSSharedFileListItemCopyResolvedURL)
+ currentItemURL = LSSharedFileListItemCopyResolvedURL(item, resolutionFlags, NULL);
+#if defined(MAC_OS_X_VERSION_MIN_REQUIRED) && MAC_OS_X_VERSION_MIN_REQUIRED < 10100
+ else
+ LSSharedFileListItemResolve(item, resolutionFlags, &currentItemURL, NULL);
+#endif
+#else
+ LSSharedFileListItemResolve(item, resolutionFlags, &currentItemURL, NULL);
+#endif
+
if(currentItemURL && CFEqual(currentItemURL, findUrl)) {
// found
CFRelease(currentItemURL);
diff --git a/src/qt/guiutil.h b/src/qt/guiutil.h
index a77036a194..bcbb540c37 100644
--- a/src/qt/guiutil.h
+++ b/src/qt/guiutil.h
@@ -107,7 +107,7 @@ namespace GUIUtil
void openDebugLogfile();
// Replace invalid default fonts with known good ones
- void SubstituteFonts();
+ void SubstituteFonts(const QString& language);
/** Qt event filter that intercepts ToolTipChange events, and replaces the tooltip with a rich text
representation if needed. This assures that Qt can word-wrap long tooltip messages.
diff --git a/src/qt/paymentrequestplus.cpp b/src/qt/paymentrequestplus.cpp
index 35846bc153..4c1e898020 100644
--- a/src/qt/paymentrequestplus.cpp
+++ b/src/qt/paymentrequestplus.cpp
@@ -9,6 +9,8 @@
#include "paymentrequestplus.h"
+#include "util.h"
+
#include <stdexcept>
#include <openssl/x509.h>
@@ -30,18 +32,18 @@ bool PaymentRequestPlus::parse(const QByteArray& data)
{
bool parseOK = paymentRequest.ParseFromArray(data.data(), data.size());
if (!parseOK) {
- qWarning() << "PaymentRequestPlus::parse : Error parsing payment request";
+ qWarning() << "PaymentRequestPlus::parse: Error parsing payment request";
return false;
}
if (paymentRequest.payment_details_version() > 1) {
- qWarning() << "PaymentRequestPlus::parse : Received up-version payment details, version=" << paymentRequest.payment_details_version();
+ qWarning() << "PaymentRequestPlus::parse: Received up-version payment details, version=" << paymentRequest.payment_details_version();
return false;
}
parseOK = details.ParseFromString(paymentRequest.serialized_payment_details());
if (!parseOK)
{
- qWarning() << "PaymentRequestPlus::parse : Error parsing payment details";
+ qWarning() << "PaymentRequestPlus::parse: Error parsing payment details";
paymentRequest.Clear();
return false;
}
@@ -81,17 +83,17 @@ bool PaymentRequestPlus::getMerchant(X509_STORE* certStore, QString& merchant) c
digestAlgorithm = EVP_sha1();
}
else if (paymentRequest.pki_type() == "none") {
- qWarning() << "PaymentRequestPlus::getMerchant : Payment request: pki_type == none";
+ qWarning() << "PaymentRequestPlus::getMerchant: Payment request: pki_type == none";
return false;
}
else {
- qWarning() << "PaymentRequestPlus::getMerchant : Payment request: unknown pki_type " << QString::fromStdString(paymentRequest.pki_type());
+ qWarning() << "PaymentRequestPlus::getMerchant: Payment request: unknown pki_type " << QString::fromStdString(paymentRequest.pki_type());
return false;
}
payments::X509Certificates certChain;
if (!certChain.ParseFromString(paymentRequest.pki_data())) {
- qWarning() << "PaymentRequestPlus::getMerchant : Payment request: error parsing pki_data";
+ qWarning() << "PaymentRequestPlus::getMerchant: Payment request: error parsing pki_data";
return false;
}
@@ -101,12 +103,12 @@ bool PaymentRequestPlus::getMerchant(X509_STORE* certStore, QString& merchant) c
QByteArray certData(certChain.certificate(i).data(), certChain.certificate(i).size());
QSslCertificate qCert(certData, QSsl::Der);
if (currentTime < qCert.effectiveDate() || currentTime > qCert.expiryDate()) {
- qWarning() << "PaymentRequestPlus::getMerchant : Payment request: certificate expired or not yet active: " << qCert;
+ qWarning() << "PaymentRequestPlus::getMerchant: Payment request: certificate expired or not yet active: " << qCert;
return false;
}
#if QT_VERSION >= 0x050000
if (qCert.isBlacklisted()) {
- qWarning() << "PaymentRequestPlus::getMerchant : Payment request: certificate blacklisted: " << qCert;
+ qWarning() << "PaymentRequestPlus::getMerchant: Payment request: certificate blacklisted: " << qCert;
return false;
}
#endif
@@ -116,7 +118,7 @@ bool PaymentRequestPlus::getMerchant(X509_STORE* certStore, QString& merchant) c
certs.push_back(cert);
}
if (certs.empty()) {
- qWarning() << "PaymentRequestPlus::getMerchant : Payment request: empty certificate chain";
+ qWarning() << "PaymentRequestPlus::getMerchant: Payment request: empty certificate chain";
return false;
}
@@ -132,7 +134,7 @@ bool PaymentRequestPlus::getMerchant(X509_STORE* certStore, QString& merchant) c
// load the signing cert into it and verify.
X509_STORE_CTX *store_ctx = X509_STORE_CTX_new();
if (!store_ctx) {
- qWarning() << "PaymentRequestPlus::getMerchant : Payment request: error creating X509_STORE_CTX";
+ qWarning() << "PaymentRequestPlus::getMerchant: Payment request: error creating X509_STORE_CTX";
return false;
}
@@ -150,7 +152,13 @@ bool PaymentRequestPlus::getMerchant(X509_STORE* certStore, QString& merchant) c
int result = X509_verify_cert(store_ctx);
if (result != 1) {
int error = X509_STORE_CTX_get_error(store_ctx);
- throw SSLVerifyError(X509_verify_cert_error_string(error));
+ // For testing payment requests, we allow self signed root certs!
+ // This option is just shown in the UI options, if -help-debug is enabled.
+ if (!(error == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT && GetBoolArg("-allowselfsignedrootcertificates", false))) {
+ throw SSLVerifyError(X509_verify_cert_error_string(error));
+ } else {
+ qDebug() << "PaymentRequestPlus::getMerchant: Allowing self signed root certificate, because -allowselfsignedrootcertificates is true.";
+ }
}
X509_NAME *certname = X509_get_subject_name(signing_cert);
@@ -183,7 +191,7 @@ bool PaymentRequestPlus::getMerchant(X509_STORE* certStore, QString& merchant) c
}
catch (const SSLVerifyError& err) {
fResult = false;
- qWarning() << "PaymentRequestPlus::getMerchant : SSL error: " << err.what();
+ qWarning() << "PaymentRequestPlus::getMerchant: SSL error: " << err.what();
}
if (website)
diff --git a/src/qt/paymentserver.cpp b/src/qt/paymentserver.cpp
index 66331ee4b4..a00916bf7f 100644
--- a/src/qt/paymentserver.cpp
+++ b/src/qt/paymentserver.cpp
@@ -97,7 +97,7 @@ static QList<QString> savedPaymentRequests;
static void ReportInvalidCertificate(const QSslCertificate& cert)
{
- qDebug() << "ReportInvalidCertificate : Payment server found an invalid certificate: " << cert.subjectInfo(QSslCertificate::CommonName);
+ qDebug() << "ReportInvalidCertificate: Payment server found an invalid certificate: " << cert.subjectInfo(QSslCertificate::CommonName);
}
//
@@ -124,19 +124,22 @@ void PaymentServer::LoadRootCAs(X509_STORE* _store)
// and get 'I don't like X.509 certificates, don't trust anybody' behavior:
QString certFile = QString::fromStdString(GetArg("-rootcertificates", "-system-"));
- if (certFile.isEmpty())
- return; // Empty store
+ // Empty store
+ if (certFile.isEmpty()) {
+ qDebug() << QString("PaymentServer::%1: Payment request authentication via X.509 certificates disabled.").arg(__func__);
+ return;
+ }
QList<QSslCertificate> certList;
- if (certFile != "-system-")
- {
+ if (certFile != "-system-") {
+ qDebug() << QString("PaymentServer::%1: Using \"%2\" as trusted root certificate.").arg(__func__).arg(certFile);
+
certList = QSslCertificate::fromPath(certFile);
// Use those certificates when fetching payment requests, too:
QSslSocket::setDefaultCaCertificates(certList);
- }
- else
- certList = QSslSocket::systemCaCertificates ();
+ } else
+ certList = QSslSocket::systemCaCertificates();
int nRootCerts = 0;
const QDateTime currentTime = QDateTime::currentDateTime();
@@ -168,7 +171,7 @@ void PaymentServer::LoadRootCAs(X509_STORE* _store)
continue;
}
}
- qWarning() << "PaymentServer::LoadRootCAs : Loaded " << nRootCerts << " root certificates";
+ qWarning() << "PaymentServer::LoadRootCAs: Loaded " << nRootCerts << " root certificates";
// Project for another day:
// Fetch certificate revocation lists, and add them to certStore.
@@ -241,7 +244,7 @@ void PaymentServer::ipcParseCommandLine(int argc, char* argv[])
{
// Printing to debug.log is about the best we can do here, the
// GUI hasn't started yet so we can't pop up a message box.
- qWarning() << "PaymentServer::ipcSendCommandLine : Payment request file does not exist: " << arg;
+ qWarning() << "PaymentServer::ipcSendCommandLine: Payment request file does not exist: " << arg;
}
}
}
@@ -365,10 +368,10 @@ void PaymentServer::initNetManager()
if (optionsModel->getProxySettings(proxy)) {
netManager->setProxy(proxy);
- qDebug() << "PaymentServer::initNetManager : Using SOCKS5 proxy" << proxy.hostName() << ":" << proxy.port();
+ qDebug() << "PaymentServer::initNetManager: Using SOCKS5 proxy" << proxy.hostName() << ":" << proxy.port();
}
else
- qDebug() << "PaymentServer::initNetManager : No active proxy server found.";
+ qDebug() << "PaymentServer::initNetManager: No active proxy server found.";
connect(netManager, SIGNAL(finished(QNetworkReply*)),
this, SLOT(netRequestFinished(QNetworkReply*)));
@@ -412,12 +415,12 @@ void PaymentServer::handleURIOrFile(const QString& s)
if (fetchUrl.isValid())
{
- qDebug() << "PaymentServer::handleURIOrFile : fetchRequest(" << fetchUrl << ")";
+ qDebug() << "PaymentServer::handleURIOrFile: fetchRequest(" << fetchUrl << ")";
fetchRequest(fetchUrl);
}
else
{
- qWarning() << "PaymentServer::handleURIOrFile : Invalid URL: " << fetchUrl;
+ qWarning() << "PaymentServer::handleURIOrFile: Invalid URL: " << fetchUrl;
emit message(tr("URI handling"),
tr("Payment request fetch URL is invalid: %1").arg(fetchUrl.toString()),
CClientUIInterface::ICON_WARNING);
@@ -518,27 +521,23 @@ bool PaymentServer::processPaymentRequest(PaymentRequestPlus& request, SendCoins
return false;
if (request.IsInitialized()) {
- const payments::PaymentDetails& details = request.getDetails();
-
// Payment request network matches client network?
- if (details.network() != Params().NetworkIDString())
- {
+ if (!verifyNetwork(request.getDetails())) {
emit message(tr("Payment request rejected"), tr("Payment request network doesn't match client network."),
CClientUIInterface::MSG_ERROR);
return false;
}
- // Expired payment request?
- if (details.has_expires() && (int64_t)details.expires() < GetTime())
- {
- emit message(tr("Payment request rejected"), tr("Payment request has expired."),
+ // Make sure any payment requests involved are still valid.
+ // This is re-checked just before sending coins in WalletModel::sendCoins().
+ if (verifyExpired(request.getDetails())) {
+ emit message(tr("Payment request rejected"), tr("Payment request expired."),
CClientUIInterface::MSG_ERROR);
return false;
}
- }
- else {
+ } else {
emit message(tr("Payment request error"), tr("Payment request is not initialized."),
CClientUIInterface::MSG_ERROR);
@@ -586,10 +585,10 @@ bool PaymentServer::processPaymentRequest(PaymentRequestPlus& request, SendCoins
recipient.address = addresses.join("<br />");
if (!recipient.authenticatedMerchant.isEmpty()) {
- qDebug() << "PaymentServer::processPaymentRequest : Secure payment request from " << recipient.authenticatedMerchant;
+ qDebug() << "PaymentServer::processPaymentRequest: Secure payment request from " << recipient.authenticatedMerchant;
}
else {
- qDebug() << "PaymentServer::processPaymentRequest : Insecure payment request to " << addresses.join(", ");
+ qDebug() << "PaymentServer::processPaymentRequest: Insecure payment request to " << addresses.join(", ");
}
return true;
@@ -644,7 +643,7 @@ void PaymentServer::fetchPaymentACK(CWallet* wallet, SendCoinsRecipient recipien
else {
// This should never happen, because sending coins should have
// just unlocked the wallet and refilled the keypool.
- qWarning() << "PaymentServer::fetchPaymentACK : Error getting refund key, refund_to not set";
+ qWarning() << "PaymentServer::fetchPaymentACK: Error getting refund key, refund_to not set";
}
}
@@ -656,7 +655,7 @@ void PaymentServer::fetchPaymentACK(CWallet* wallet, SendCoinsRecipient recipien
}
else {
// This should never happen, either.
- qWarning() << "PaymentServer::fetchPaymentACK : Error serializing payment message";
+ qWarning() << "PaymentServer::fetchPaymentACK: Error serializing payment message";
}
}
@@ -695,7 +694,7 @@ void PaymentServer::netRequestFinished(QNetworkReply* reply)
SendCoinsRecipient recipient;
if (!request.parse(data))
{
- qWarning() << "PaymentServer::netRequestFinished : Error parsing payment request";
+ qWarning() << "PaymentServer::netRequestFinished: Error parsing payment request";
emit message(tr("Payment request error"),
tr("Payment request cannot be parsed!"),
CClientUIInterface::MSG_ERROR);
@@ -713,7 +712,7 @@ void PaymentServer::netRequestFinished(QNetworkReply* reply)
QString msg = tr("Bad response from server %1")
.arg(reply->request().url().toString());
- qWarning() << "PaymentServer::netRequestFinished : " << msg;
+ qWarning() << "PaymentServer::netRequestFinished: " << msg;
emit message(tr("Payment request error"), msg, CClientUIInterface::MSG_ERROR);
}
else
@@ -729,7 +728,7 @@ void PaymentServer::reportSslErrors(QNetworkReply* reply, const QList<QSslError>
QString errString;
foreach (const QSslError& err, errs) {
- qWarning() << "PaymentServer::reportSslErrors : " << err;
+ qWarning() << "PaymentServer::reportSslErrors: " << err;
errString += err.errorString() + "\n";
}
emit message(tr("Network request error"), errString, CClientUIInterface::MSG_ERROR);
@@ -745,3 +744,27 @@ void PaymentServer::handlePaymentACK(const QString& paymentACKMsg)
// currently we don't futher process or store the paymentACK message
emit message(tr("Payment acknowledged"), paymentACKMsg, CClientUIInterface::ICON_INFORMATION | CClientUIInterface::MODAL);
}
+
+bool PaymentServer::verifyNetwork(const payments::PaymentDetails& requestDetails)
+{
+ bool fVerified = requestDetails.network() == Params().NetworkIDString();
+ if (!fVerified) {
+ qWarning() << QString("PaymentServer::%1: Payment request network \"%2\" doesn't match client network \"%3\".")
+ .arg(__func__)
+ .arg(QString::fromStdString(requestDetails.network()))
+ .arg(QString::fromStdString(Params().NetworkIDString()));
+ }
+ return fVerified;
+}
+
+bool PaymentServer::verifyExpired(const payments::PaymentDetails& requestDetails)
+{
+ bool fVerified = (requestDetails.has_expires() && (int64_t)requestDetails.expires() < GetTime());
+ if (fVerified) {
+ const QString requestExpires = QString::fromStdString(DateTimeStrFormat("%Y-%m-%d %H:%M:%S", (int64_t)requestDetails.expires()));
+ qWarning() << QString("PaymentServer::%1: Payment request expired \"%2\".")
+ .arg(__func__)
+ .arg(requestExpires);
+ }
+ return fVerified;
+}
diff --git a/src/qt/paymentserver.h b/src/qt/paymentserver.h
index 2fc24395f6..db5f44ff1d 100644
--- a/src/qt/paymentserver.h
+++ b/src/qt/paymentserver.h
@@ -91,6 +91,11 @@ public:
// This is now public, because we use it in paymentservertests.cpp
static bool readPaymentRequestFromFile(const QString& filename, PaymentRequestPlus& request);
+ // Verify that the payment request network matches the client network
+ static bool verifyNetwork(const payments::PaymentDetails& requestDetails);
+ // Verify if the payment request is expired
+ static bool verifyExpired(const payments::PaymentDetails& requestDetails);
+
signals:
// Fired when a valid payment request is received
void receivedPaymentRequest(SendCoinsRecipient);
diff --git a/src/qt/res/icons/about.png b/src/qt/res/icons/about.png
index eeef943355..83eb3c07ee 100644
--- a/src/qt/res/icons/about.png
+++ b/src/qt/res/icons/about.png
Binary files differ
diff --git a/src/qt/res/icons/about_qt.png b/src/qt/res/icons/about_qt.png
index d3665e9892..dd27a99d0a 100644
--- a/src/qt/res/icons/about_qt.png
+++ b/src/qt/res/icons/about_qt.png
Binary files differ
diff --git a/src/qt/res/icons/add.png b/src/qt/res/icons/add.png
index ef995cc0b5..1442b4e85e 100644
--- a/src/qt/res/icons/add.png
+++ b/src/qt/res/icons/add.png
Binary files differ
diff --git a/src/qt/res/icons/address-book.png b/src/qt/res/icons/address-book.png
index 0c9238c18e..b11c7d5356 100644
--- a/src/qt/res/icons/address-book.png
+++ b/src/qt/res/icons/address-book.png
Binary files differ
diff --git a/src/qt/res/icons/bitcoin.png b/src/qt/res/icons/bitcoin.png
index 705a20260a..435621af23 100644
--- a/src/qt/res/icons/bitcoin.png
+++ b/src/qt/res/icons/bitcoin.png
Binary files differ
diff --git a/src/qt/res/icons/clock1.png b/src/qt/res/icons/clock1.png
index 65adba5e21..ceae5ed0d9 100644
--- a/src/qt/res/icons/clock1.png
+++ b/src/qt/res/icons/clock1.png
Binary files differ
diff --git a/src/qt/res/icons/clock2.png b/src/qt/res/icons/clock2.png
index 196a79ce4a..159f69a8fc 100644
--- a/src/qt/res/icons/clock2.png
+++ b/src/qt/res/icons/clock2.png
Binary files differ
diff --git a/src/qt/res/icons/clock3.png b/src/qt/res/icons/clock3.png
index 3d04655ed9..d668e35ffc 100644
--- a/src/qt/res/icons/clock3.png
+++ b/src/qt/res/icons/clock3.png
Binary files differ
diff --git a/src/qt/res/icons/clock4.png b/src/qt/res/icons/clock4.png
index c3210c5af1..5ebf8ed7ac 100644
--- a/src/qt/res/icons/clock4.png
+++ b/src/qt/res/icons/clock4.png
Binary files differ
diff --git a/src/qt/res/icons/clock5.png b/src/qt/res/icons/clock5.png
index 84a9fa2842..96f15ef7d9 100644
--- a/src/qt/res/icons/clock5.png
+++ b/src/qt/res/icons/clock5.png
Binary files differ
diff --git a/src/qt/res/icons/configure.png b/src/qt/res/icons/configure.png
index fe9c6ec5ec..5333c83d5e 100644
--- a/src/qt/res/icons/configure.png
+++ b/src/qt/res/icons/configure.png
Binary files differ
diff --git a/src/qt/res/icons/connect0.png b/src/qt/res/icons/connect0.png
index 99bb2575d6..58e2c3e965 100644
--- a/src/qt/res/icons/connect0.png
+++ b/src/qt/res/icons/connect0.png
Binary files differ
diff --git a/src/qt/res/icons/connect1.png b/src/qt/res/icons/connect1.png
index dffc692c76..949e7a922d 100644
--- a/src/qt/res/icons/connect1.png
+++ b/src/qt/res/icons/connect1.png
Binary files differ
diff --git a/src/qt/res/icons/connect2.png b/src/qt/res/icons/connect2.png
index 3594fb117c..143b2054fb 100644
--- a/src/qt/res/icons/connect2.png
+++ b/src/qt/res/icons/connect2.png
Binary files differ
diff --git a/src/qt/res/icons/connect3.png b/src/qt/res/icons/connect3.png
index 3594fb117c..143b2054fb 100644
--- a/src/qt/res/icons/connect3.png
+++ b/src/qt/res/icons/connect3.png
Binary files differ
diff --git a/src/qt/res/icons/connect4.png b/src/qt/res/icons/connect4.png
index 0c667c7e06..f96e3455ce 100644
--- a/src/qt/res/icons/connect4.png
+++ b/src/qt/res/icons/connect4.png
Binary files differ
diff --git a/src/qt/res/icons/debugwindow.png b/src/qt/res/icons/debugwindow.png
index 576e57ab03..290fe60864 100644
--- a/src/qt/res/icons/debugwindow.png
+++ b/src/qt/res/icons/debugwindow.png
Binary files differ
diff --git a/src/qt/res/icons/edit.png b/src/qt/res/icons/edit.png
index 4df2229e98..46582716ef 100644
--- a/src/qt/res/icons/edit.png
+++ b/src/qt/res/icons/edit.png
Binary files differ
diff --git a/src/qt/res/icons/editcopy.png b/src/qt/res/icons/editcopy.png
index db0c51772c..74ac8b2774 100644
--- a/src/qt/res/icons/editcopy.png
+++ b/src/qt/res/icons/editcopy.png
Binary files differ
diff --git a/src/qt/res/icons/editpaste.png b/src/qt/res/icons/editpaste.png
index be8634674d..7b47f4d52b 100644
--- a/src/qt/res/icons/editpaste.png
+++ b/src/qt/res/icons/editpaste.png
Binary files differ
diff --git a/src/qt/res/icons/export.png b/src/qt/res/icons/export.png
index 18d0596194..ac76cc1eff 100644
--- a/src/qt/res/icons/export.png
+++ b/src/qt/res/icons/export.png
Binary files differ
diff --git a/src/qt/res/icons/eye.png b/src/qt/res/icons/eye.png
index 7036708de5..f2f139dbb2 100644
--- a/src/qt/res/icons/eye.png
+++ b/src/qt/res/icons/eye.png
Binary files differ
diff --git a/src/qt/res/icons/eye_minus.png b/src/qt/res/icons/eye_minus.png
index bdbe073627..795bf6436a 100644
--- a/src/qt/res/icons/eye_minus.png
+++ b/src/qt/res/icons/eye_minus.png
Binary files differ
diff --git a/src/qt/res/icons/eye_plus.png b/src/qt/res/icons/eye_plus.png
index 2ba5e68c76..eaab69297a 100644
--- a/src/qt/res/icons/eye_plus.png
+++ b/src/qt/res/icons/eye_plus.png
Binary files differ
diff --git a/src/qt/res/icons/filesave.png b/src/qt/res/icons/filesave.png
index a53390f594..779cca1d52 100644
--- a/src/qt/res/icons/filesave.png
+++ b/src/qt/res/icons/filesave.png
Binary files differ
diff --git a/src/qt/res/icons/history.png b/src/qt/res/icons/history.png
index cb723abc5f..68d841fa85 100644
--- a/src/qt/res/icons/history.png
+++ b/src/qt/res/icons/history.png
Binary files differ
diff --git a/src/qt/res/icons/info.png b/src/qt/res/icons/info.png
index 085fa8ea73..692b50c2a9 100644
--- a/src/qt/res/icons/info.png
+++ b/src/qt/res/icons/info.png
Binary files differ
diff --git a/src/qt/res/icons/key.png b/src/qt/res/icons/key.png
index d21f81364d..f301c4f38c 100644
--- a/src/qt/res/icons/key.png
+++ b/src/qt/res/icons/key.png
Binary files differ
diff --git a/src/qt/res/icons/lock_closed.png b/src/qt/res/icons/lock_closed.png
index 77914ab2ce..1bd98b21a6 100644
--- a/src/qt/res/icons/lock_closed.png
+++ b/src/qt/res/icons/lock_closed.png
Binary files differ
diff --git a/src/qt/res/icons/lock_open.png b/src/qt/res/icons/lock_open.png
index 50615b7336..a7045133b1 100644
--- a/src/qt/res/icons/lock_open.png
+++ b/src/qt/res/icons/lock_open.png
Binary files differ
diff --git a/src/qt/res/icons/open.png b/src/qt/res/icons/open.png
index 390d3dab64..4d958f0e18 100644
--- a/src/qt/res/icons/open.png
+++ b/src/qt/res/icons/open.png
Binary files differ
diff --git a/src/qt/res/icons/overview.png b/src/qt/res/icons/overview.png
index 36e1003c3c..411595413d 100644
--- a/src/qt/res/icons/overview.png
+++ b/src/qt/res/icons/overview.png
Binary files differ
diff --git a/src/qt/res/icons/quit.png b/src/qt/res/icons/quit.png
index 6e44a2d329..55e34de4b8 100644
--- a/src/qt/res/icons/quit.png
+++ b/src/qt/res/icons/quit.png
Binary files differ
diff --git a/src/qt/res/icons/receive.png b/src/qt/res/icons/receive.png
index a53390f594..f4e6f58d05 100644
--- a/src/qt/res/icons/receive.png
+++ b/src/qt/res/icons/receive.png
Binary files differ
diff --git a/src/qt/res/icons/remove.png b/src/qt/res/icons/remove.png
index 3849cdd6d8..8e738d6301 100644
--- a/src/qt/res/icons/remove.png
+++ b/src/qt/res/icons/remove.png
Binary files differ
diff --git a/src/qt/res/icons/send.png b/src/qt/res/icons/send.png
index 18d0596194..ac76cc1eff 100644
--- a/src/qt/res/icons/send.png
+++ b/src/qt/res/icons/send.png
Binary files differ
diff --git a/src/qt/res/icons/synced.png b/src/qt/res/icons/synced.png
index d33914f0b4..5ac28d36a3 100644
--- a/src/qt/res/icons/synced.png
+++ b/src/qt/res/icons/synced.png
Binary files differ
diff --git a/src/qt/res/icons/transaction0.png b/src/qt/res/icons/transaction0.png
index fd41da0680..1091b86e68 100644
--- a/src/qt/res/icons/transaction0.png
+++ b/src/qt/res/icons/transaction0.png
Binary files differ
diff --git a/src/qt/res/icons/transaction2.png b/src/qt/res/icons/transaction2.png
index d33914f0b4..5ac28d36a3 100644
--- a/src/qt/res/icons/transaction2.png
+++ b/src/qt/res/icons/transaction2.png
Binary files differ
diff --git a/src/qt/res/icons/transaction_conflicted.png b/src/qt/res/icons/transaction_conflicted.png
index 6e44a2d329..55e34de4b8 100644
--- a/src/qt/res/icons/transaction_conflicted.png
+++ b/src/qt/res/icons/transaction_conflicted.png
Binary files differ
diff --git a/src/qt/res/icons/tx_inout.png b/src/qt/res/icons/tx_inout.png
index cecd332ad1..0a6e72a898 100644
--- a/src/qt/res/icons/tx_inout.png
+++ b/src/qt/res/icons/tx_inout.png
Binary files differ
diff --git a/src/qt/res/icons/tx_input.png b/src/qt/res/icons/tx_input.png
index 1b4cfd967c..9e9ee92932 100644
--- a/src/qt/res/icons/tx_input.png
+++ b/src/qt/res/icons/tx_input.png
Binary files differ
diff --git a/src/qt/res/icons/tx_mined.png b/src/qt/res/icons/tx_mined.png
index 421a9cf639..5a6ef521c0 100644
--- a/src/qt/res/icons/tx_mined.png
+++ b/src/qt/res/icons/tx_mined.png
Binary files differ
diff --git a/src/qt/res/icons/tx_output.png b/src/qt/res/icons/tx_output.png
index 06d9d0adf2..6f66ab6547 100644
--- a/src/qt/res/icons/tx_output.png
+++ b/src/qt/res/icons/tx_output.png
Binary files differ
diff --git a/src/qt/res/icons/verify.png b/src/qt/res/icons/verify.png
index 9ff35c2793..8e2cb2cc14 100644
--- a/src/qt/res/icons/verify.png
+++ b/src/qt/res/icons/verify.png
Binary files differ
diff --git a/src/qt/res/images/about.png b/src/qt/res/images/about.png
deleted file mode 100644
index fdede66172..0000000000
--- a/src/qt/res/images/about.png
+++ /dev/null
Binary files differ
diff --git a/src/qt/res/movies/spinner-000.png b/src/qt/res/movies/spinner-000.png
index b296a58481..1e92d859da 100644
--- a/src/qt/res/movies/spinner-000.png
+++ b/src/qt/res/movies/spinner-000.png
Binary files differ
diff --git a/src/qt/res/movies/spinner-001.png b/src/qt/res/movies/spinner-001.png
index 4f6f9a487b..d167f20541 100644
--- a/src/qt/res/movies/spinner-001.png
+++ b/src/qt/res/movies/spinner-001.png
Binary files differ
diff --git a/src/qt/res/movies/spinner-002.png b/src/qt/res/movies/spinner-002.png
index 4f14e3ca93..4a1f1f8e56 100644
--- a/src/qt/res/movies/spinner-002.png
+++ b/src/qt/res/movies/spinner-002.png
Binary files differ
diff --git a/src/qt/res/movies/spinner-003.png b/src/qt/res/movies/spinner-003.png
index d7756e73bf..fb1c2cd4ad 100644
--- a/src/qt/res/movies/spinner-003.png
+++ b/src/qt/res/movies/spinner-003.png
Binary files differ
diff --git a/src/qt/res/movies/spinner-004.png b/src/qt/res/movies/spinner-004.png
index 4b381b81b2..4df2132344 100644
--- a/src/qt/res/movies/spinner-004.png
+++ b/src/qt/res/movies/spinner-004.png
Binary files differ
diff --git a/src/qt/res/movies/spinner-005.png b/src/qt/res/movies/spinner-005.png
index cbdb5b5797..5d6f41e0dc 100644
--- a/src/qt/res/movies/spinner-005.png
+++ b/src/qt/res/movies/spinner-005.png
Binary files differ
diff --git a/src/qt/res/movies/spinner-006.png b/src/qt/res/movies/spinner-006.png
index 55d4540c92..c1f7d18899 100644
--- a/src/qt/res/movies/spinner-006.png
+++ b/src/qt/res/movies/spinner-006.png
Binary files differ
diff --git a/src/qt/res/movies/spinner-007.png b/src/qt/res/movies/spinner-007.png
index b25f59a445..1e794b2626 100644
--- a/src/qt/res/movies/spinner-007.png
+++ b/src/qt/res/movies/spinner-007.png
Binary files differ
diff --git a/src/qt/res/movies/spinner-008.png b/src/qt/res/movies/spinner-008.png
index 6493184a7a..df12ea8719 100644
--- a/src/qt/res/movies/spinner-008.png
+++ b/src/qt/res/movies/spinner-008.png
Binary files differ
diff --git a/src/qt/res/movies/spinner-009.png b/src/qt/res/movies/spinner-009.png
index 938c49f9d3..18fc3a7d16 100644
--- a/src/qt/res/movies/spinner-009.png
+++ b/src/qt/res/movies/spinner-009.png
Binary files differ
diff --git a/src/qt/res/movies/spinner-010.png b/src/qt/res/movies/spinner-010.png
index 7eb645eda5..a79c845fe8 100644
--- a/src/qt/res/movies/spinner-010.png
+++ b/src/qt/res/movies/spinner-010.png
Binary files differ
diff --git a/src/qt/res/movies/spinner-011.png b/src/qt/res/movies/spinner-011.png
index fd4b63ca5a..57baf66895 100644
--- a/src/qt/res/movies/spinner-011.png
+++ b/src/qt/res/movies/spinner-011.png
Binary files differ
diff --git a/src/qt/res/movies/spinner-012.png b/src/qt/res/movies/spinner-012.png
index 10d26a3a53..9deae7853a 100644
--- a/src/qt/res/movies/spinner-012.png
+++ b/src/qt/res/movies/spinner-012.png
Binary files differ
diff --git a/src/qt/res/movies/spinner-013.png b/src/qt/res/movies/spinner-013.png
index 863a9d2908..0659d48dec 100644
--- a/src/qt/res/movies/spinner-013.png
+++ b/src/qt/res/movies/spinner-013.png
Binary files differ
diff --git a/src/qt/res/movies/spinner-014.png b/src/qt/res/movies/spinner-014.png
index d01086cb98..bc1ef51bde 100644
--- a/src/qt/res/movies/spinner-014.png
+++ b/src/qt/res/movies/spinner-014.png
Binary files differ
diff --git a/src/qt/res/movies/spinner-015.png b/src/qt/res/movies/spinner-015.png
index 402dbea693..24b57b62c2 100644
--- a/src/qt/res/movies/spinner-015.png
+++ b/src/qt/res/movies/spinner-015.png
Binary files differ
diff --git a/src/qt/res/movies/spinner-016.png b/src/qt/res/movies/spinner-016.png
index 1db20e6078..d622872651 100644
--- a/src/qt/res/movies/spinner-016.png
+++ b/src/qt/res/movies/spinner-016.png
Binary files differ
diff --git a/src/qt/res/movies/spinner-017.png b/src/qt/res/movies/spinner-017.png
index e2c2e2ef78..f48f688db2 100644
--- a/src/qt/res/movies/spinner-017.png
+++ b/src/qt/res/movies/spinner-017.png
Binary files differ
diff --git a/src/qt/res/movies/spinner-018.png b/src/qt/res/movies/spinner-018.png
index 6f1fe73756..a2c8f38b1d 100644
--- a/src/qt/res/movies/spinner-018.png
+++ b/src/qt/res/movies/spinner-018.png
Binary files differ
diff --git a/src/qt/res/movies/spinner-019.png b/src/qt/res/movies/spinner-019.png
index 5f18f65608..9d7cc35d82 100644
--- a/src/qt/res/movies/spinner-019.png
+++ b/src/qt/res/movies/spinner-019.png
Binary files differ
diff --git a/src/qt/res/movies/spinner-020.png b/src/qt/res/movies/spinner-020.png
index c12ae20016..1a07acc454 100644
--- a/src/qt/res/movies/spinner-020.png
+++ b/src/qt/res/movies/spinner-020.png
Binary files differ
diff --git a/src/qt/res/movies/spinner-021.png b/src/qt/res/movies/spinner-021.png
index d81ceade23..9cea8f2543 100644
--- a/src/qt/res/movies/spinner-021.png
+++ b/src/qt/res/movies/spinner-021.png
Binary files differ
diff --git a/src/qt/res/movies/spinner-022.png b/src/qt/res/movies/spinner-022.png
index 69c6657942..60250f6dea 100644
--- a/src/qt/res/movies/spinner-022.png
+++ b/src/qt/res/movies/spinner-022.png
Binary files differ
diff --git a/src/qt/res/movies/spinner-023.png b/src/qt/res/movies/spinner-023.png
index 7bed5bae85..fc290a0cf2 100644
--- a/src/qt/res/movies/spinner-023.png
+++ b/src/qt/res/movies/spinner-023.png
Binary files differ
diff --git a/src/qt/res/movies/spinner-024.png b/src/qt/res/movies/spinner-024.png
index b3be8d3e8e..c5dcf1eae9 100644
--- a/src/qt/res/movies/spinner-024.png
+++ b/src/qt/res/movies/spinner-024.png
Binary files differ
diff --git a/src/qt/res/movies/spinner-025.png b/src/qt/res/movies/spinner-025.png
index 3a7fa9ab0d..7f3577a4de 100644
--- a/src/qt/res/movies/spinner-025.png
+++ b/src/qt/res/movies/spinner-025.png
Binary files differ
diff --git a/src/qt/res/movies/spinner-026.png b/src/qt/res/movies/spinner-026.png
index dd92fc4fc1..1663ddf44c 100644
--- a/src/qt/res/movies/spinner-026.png
+++ b/src/qt/res/movies/spinner-026.png
Binary files differ
diff --git a/src/qt/res/movies/spinner-027.png b/src/qt/res/movies/spinner-027.png
index 9adefee268..d0e6da4503 100644
--- a/src/qt/res/movies/spinner-027.png
+++ b/src/qt/res/movies/spinner-027.png
Binary files differ
diff --git a/src/qt/res/movies/spinner-028.png b/src/qt/res/movies/spinner-028.png
index 83e7cdd583..2a7aba50e2 100644
--- a/src/qt/res/movies/spinner-028.png
+++ b/src/qt/res/movies/spinner-028.png
Binary files differ
diff --git a/src/qt/res/movies/spinner-029.png b/src/qt/res/movies/spinner-029.png
index 6cbdbb0fe1..c8ca15c1e1 100644
--- a/src/qt/res/movies/spinner-029.png
+++ b/src/qt/res/movies/spinner-029.png
Binary files differ
diff --git a/src/qt/res/movies/spinner-030.png b/src/qt/res/movies/spinner-030.png
index e4a09a44bc..c847c99a93 100644
--- a/src/qt/res/movies/spinner-030.png
+++ b/src/qt/res/movies/spinner-030.png
Binary files differ
diff --git a/src/qt/res/movies/spinner-031.png b/src/qt/res/movies/spinner-031.png
index 3c3d505741..403443144e 100644
--- a/src/qt/res/movies/spinner-031.png
+++ b/src/qt/res/movies/spinner-031.png
Binary files differ
diff --git a/src/qt/res/movies/spinner-032.png b/src/qt/res/movies/spinner-032.png
index 7460f80da3..f9db080567 100644
--- a/src/qt/res/movies/spinner-032.png
+++ b/src/qt/res/movies/spinner-032.png
Binary files differ
diff --git a/src/qt/res/movies/spinner-033.png b/src/qt/res/movies/spinner-033.png
index d327e8fb08..43f57719e7 100644
--- a/src/qt/res/movies/spinner-033.png
+++ b/src/qt/res/movies/spinner-033.png
Binary files differ
diff --git a/src/qt/res/movies/spinner-034.png b/src/qt/res/movies/spinner-034.png
index d8432751da..c26656ff17 100644
--- a/src/qt/res/movies/spinner-034.png
+++ b/src/qt/res/movies/spinner-034.png
Binary files differ
diff --git a/src/qt/res/movies/spinner-035.png b/src/qt/res/movies/spinner-035.png
index c89c959c94..e471f950a3 100644
--- a/src/qt/res/movies/spinner-035.png
+++ b/src/qt/res/movies/spinner-035.png
Binary files differ
diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp
index ffee56131d..5aef2d7539 100644
--- a/src/qt/sendcoinsdialog.cpp
+++ b/src/qt/sendcoinsdialog.cpp
@@ -526,8 +526,12 @@ void SendCoinsDialog::processSendCoinsReturn(const WalletModel::SendCoinsReturn
msgParams.first = tr("The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here.");
msgParams.second = CClientUIInterface::MSG_ERROR;
break;
- case WalletModel::InsaneFee:
- msgParams.first = tr("A fee higher than %1 is considered an insanely high fee.").arg(BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), 10000000));
+ case WalletModel::AbsurdFee:
+ msgParams.first = tr("A fee higher than %1 is considered an absurdly high fee.").arg(BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), 10000000));
+ break;
+ case WalletModel::PaymentRequestExpired:
+ msgParams.first = tr("Payment request expired!");
+ msgParams.second = CClientUIInterface::MSG_ERROR;
break;
// included to prevent a compiler warning.
case WalletModel::OK:
@@ -657,19 +661,19 @@ void SendCoinsDialog::coinControlClipboardAmount()
// Coin Control: copy label "Fee" to clipboard
void SendCoinsDialog::coinControlClipboardFee()
{
- GUIUtil::setClipboard(ui->labelCoinControlFee->text().left(ui->labelCoinControlFee->text().indexOf(" ")).replace("~", ""));
+ GUIUtil::setClipboard(ui->labelCoinControlFee->text().left(ui->labelCoinControlFee->text().indexOf(" ")).replace(ASYMP_UTF8, ""));
}
// Coin Control: copy label "After fee" to clipboard
void SendCoinsDialog::coinControlClipboardAfterFee()
{
- GUIUtil::setClipboard(ui->labelCoinControlAfterFee->text().left(ui->labelCoinControlAfterFee->text().indexOf(" ")).replace("~", ""));
+ GUIUtil::setClipboard(ui->labelCoinControlAfterFee->text().left(ui->labelCoinControlAfterFee->text().indexOf(" ")).replace(ASYMP_UTF8, ""));
}
// Coin Control: copy label "Bytes" to clipboard
void SendCoinsDialog::coinControlClipboardBytes()
{
- GUIUtil::setClipboard(ui->labelCoinControlBytes->text().replace("~", ""));
+ GUIUtil::setClipboard(ui->labelCoinControlBytes->text().replace(ASYMP_UTF8, ""));
}
// Coin Control: copy label "Priority" to clipboard
@@ -687,7 +691,7 @@ void SendCoinsDialog::coinControlClipboardLowOutput()
// Coin Control: copy label "Change" to clipboard
void SendCoinsDialog::coinControlClipboardChange()
{
- GUIUtil::setClipboard(ui->labelCoinControlChange->text().left(ui->labelCoinControlChange->text().indexOf(" ")).replace("~", ""));
+ GUIUtil::setClipboard(ui->labelCoinControlChange->text().left(ui->labelCoinControlChange->text().indexOf(" ")).replace(ASYMP_UTF8, ""));
}
// Coin Control: settings menu - coin control enabled/disabled by user
diff --git a/src/qt/splashscreen.cpp b/src/qt/splashscreen.cpp
index 366ed3df3d..e6a7fcaec5 100644
--- a/src/qt/splashscreen.cpp
+++ b/src/qt/splashscreen.cpp
@@ -42,7 +42,7 @@ SplashScreen::SplashScreen(Qt::WindowFlags f, const NetworkStyle *networkStyle)
QString copyrightText = QChar(0xA9)+QString(" 2009-%1 ").arg(COPYRIGHT_YEAR) + QString(tr("The Bitcoin Core developers"));
QString titleAddText = networkStyle->getTitleAddText();
- QString font = "Arial";
+ QString font = QApplication::font().toString();
// create a bitmap according to device pixelratio
QSize splashSize(480*devicePixelRatio,320*devicePixelRatio);
diff --git a/src/qt/test/paymentrequestdata.h b/src/qt/test/paymentrequestdata.h
index 37544cdebb..50636d7c67 100644
--- a/src/qt/test/paymentrequestdata.h
+++ b/src/qt/test/paymentrequestdata.h
@@ -6,16 +6,16 @@
// Data for paymentservertests.cpp
//
-// Base64/DER-encoded fake certificate authority certificate.
+// Base64/DER-encoded fake certificate authority certificates.
// Convert pem to base64/der with:
-// cat file.pem | openssl x509 -inform PEM -outform DER | openssl enc -base64
-//
+// openssl x509 -in cert.pem -inform PEM -outform DER | openssl enc -base64
+
// Serial Number: 10302349811211485352 (0x8ef94c91b112c0a8)
// Issuer: CN=PaymentRequest Test CA
// Subject: CN=PaymentRequest Test CA
// Not Valid After : Dec 8 16:37:24 2022 GMT
//
-const char* caCert_BASE64 =
+const char* caCert1_BASE64 =
"\
MIIB0DCCATmgAwIBAgIJAI75TJGxEsCoMA0GCSqGSIb3DQEBCwUAMCExHzAdBgNV\
BAMTFlBheW1lbnRSZXF1ZXN0IFRlc3QgQ0EwHhcNMTIxMjEwMTYzNzI0WhcNMjIx\
@@ -29,11 +29,36 @@ RtQcf0AJ9olzUMY4syehxbzUJP6aeXhZEYiMvdvcv9D55clq6+WLLlNT3jBgAaVn\
p3waRjPD4bUX3nv+ojz5s4puw7Qq5QUZlhGsMzPvwDGCmZkL\
";
+// Serial Number: f0:da:97:e4:38:d7:64:16
+// Issuer: CN=PaymentRequest Test CA
+// Subject: CN=PaymentRequest Test CA
+// Not Valid After : Jan 8 18:21:06 2025 GMT
+//
+const char* caCert2_BASE64 =
+"\
+MIIC1TCCAb2gAwIBAgIJAPDal+Q412QWMA0GCSqGSIb3DQEBCwUAMCExHzAdBgNV\
+BAMMFlBheW1lbnRSZXF1ZXN0IFRlc3QgQ0EwHhcNMTUwMTExMTgyMTA2WhcNMjUw\
+MTA4MTgyMTA2WjAhMR8wHQYDVQQDDBZQYXltZW50UmVxdWVzdCBUZXN0IENBMIIB\
+IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1S9wVLfTplJuT/1OaaBgl/Mb\
+I392v8S9kHbzYz7B4OTMslaO7piz0v3SO3TKMh0dswjiRdHrIgpO7XdIUQiU/ugg\
+xDw0kuNehfz1ycaGedlFFtFHTNXqLyIUF3dlwHhQwaomM6RXoJmxLny5BhYHEcmk\
+yWwr3Cdjd9gAZpblugVJB9C1e40uyL8ao4PHdLzOqO27iSe6riP8SwwisJZEbMaz\
+AZpgNEEMbIXPJEFvm5HTRXSMtQCOTSZYMFF0M2yrtmlECnz7hWP19b9bcoDzZQB4\
+ylIsFG/7q2jV7MC/e2STZv+niJiHL08RUdoFpAgzaxMgqj63C7B55HgNDNHJYQID\
+AQABoxAwDjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBGejPxLxj9\
++crv6gUeEBMZPiUx7pUgcI22Wm5yymP96B4fwI3Y0DBehq20d76vbWGPN17Z6pH3\
+ge7PVY1SYqXtS6hXTo4olCm/BZADli+2Bs2xCiaa+Ltve4ufVej+bKJXN/YnrhvO\
+Kq+klQkuuHywU+GJV/NQeBqToIrSOBgi477NgLFCCCmmx2QWsxHoCFGfuRCBVseT\
+z2k/tMuALCDXGeZBRPTsGHu1y4cj84swAeoDK5QSQcI+Ub7GKc+zkoj02sdDLiMo\
+3wokYPcIy47oclhmb4xubHc+y7nF610yZBoC/zgbhbawnZ65hDDWkdQ/SVAnWZD7\
+9PFfmNnYPTQH\
+";
+
//
// This payment request validates directly against the
-// above certificate authority.
+// caCert1 certificate authority.
//
-const char* paymentrequest1_BASE64 =
+const char* paymentrequest1_cert1_BASE64 =
"\
Egt4NTA5K3NoYTI1NhrxAwruAzCCAeowggFToAMCAQICAQEwDQYJKoZIhvcNAQEL\
BQAwITEfMB0GA1UEAxMWUGF5bWVudFJlcXVlc3QgVGVzdCBDQTAeFw0xMjEyMTAx\
@@ -55,7 +80,7 @@ SiWVbw0tX/68iSQEGGfh9n6ee/8Myb3ICdw=\
//
// Signed, but expired, merchant cert in the request
//
-const char* paymentrequest2_BASE64 =
+const char* paymentrequest2_cert1_BASE64 =
"\
Egt4NTA5K3NoYTI1NhrsAwrpAzCCAeUwggFOoAMCAQICAQMwDQYJKoZIhvcNAQEL\
BQAwITEfMB0GA1UEAxMWUGF5bWVudFJlcXVlc3QgVGVzdCBDQTAeFw0xMzAyMjMy\
@@ -75,9 +100,9 @@ tejrSPOBNSJ3Mi/q5u2Yl4gJZY2b\
";
//
-// 10-long chain, all intermediates valid
+// 10-long certificate chain, all intermediates valid
//
-const char* paymentrequest3_BASE64 =
+const char* paymentrequest3_cert1_BASE64 =
"\
Egt4NTA5K3NoYTI1Nhq8JAr/AzCCAfswggFkoAMCAQICAQEwDQYJKoZIhvcNAQEL\
BQAwPzEUMBIGA1UEAwwLdGVzdGNhOC5vcmcxJzAlBgNVBAoMHlBheW1lbnQgUmVx\
@@ -184,9 +209,9 @@ chhR/aHOuEMTxmc12K4rNlgYtHCsxLP9zd+6u0cva3TucZ6EzS8PKEib/+r12/52\
";
//
-// Long chain, with an invalid (expired) cert in the middle
+// Long certificate chain, with an expired certificate in the middle
//
-const char* paymentrequest4_BASE64 =
+const char* paymentrequest4_cert1_BASE64 =
"\
Egt4NTA5K3NoYTI1NhqeJAr/AzCCAfswggFkoAMCAQICAQEwDQYJKoZIhvcNAQEL\
BQAwPzEUMBIGA1UEAwwLdGVzdGNhOC5vcmcxJzAlBgNVBAoMHlBheW1lbnQgUmVx\
@@ -291,7 +316,10 @@ HXQjsfdR58qZQS9CS5DAtRUf0R8+43/wijO/hb49VNaNXmY+/cPHMkahP2aV3tZi\
FAyZblLik9A7ZvF+UsjeFQiHB5wzWQvbqk5wQ4yabHIXoYv/E0q+eQ==\
";
-const char* paymentrequest5_BASE64 =
+//
+// Validly signed, but by a CA not in our root CA list
+//
+const char* paymentrequest5_cert1_BASE64 =
"\
Egt4NTA5K3NoYTI1NhrxAwruAzCCAeowggFToAMCAQICAQEwDQYJKoZIhvcNAQEL\
BQAwITEfMB0GA1UEAxMWUGF5bWVudFJlcXVlc3QgVGVzdCBDQTAeFw0xMzA0MTkx\
@@ -309,3 +337,99 @@ ssymvca1S/1KeM3n8Ydi2fi1JUzAAr59xPvNJRUeqCLP9upHn5z7br3P12Oz9A20\
5/4wL4ClPRPVnOHgij0bEg+y0tGESqmF1rfOfXDszlo2U92wCxS07kq79YAZJ1Zo\
XYh860/Q4wvc7lfiTe+dXBzPKAKhMy91yETY\
";
+
+//
+// Contains a testnet paytoaddress, so payment request network doesn't match client network
+//
+const char* paymentrequest1_cert2_BASE64 =
+"\
+Egt4NTA5K3NoYTI1NhrQBArNBDCCAkkwggExoAMCAQICAQEwDQYJKoZIhvcNAQEL\
+BQAwITEfMB0GA1UEAwwWUGF5bWVudFJlcXVlc3QgVGVzdCBDQTAeFw0xNTAxMTEx\
+ODIxMDhaFw0yNTAxMDgxODIxMDhaMCExHzAdBgNVBAMMFlBheW1lbnRSZXF1ZXN0\
+IFRlc3QgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMsZqzkzeBGo+i2N\
+mUak3Ciodr1V7S062VOy7N0OQYNDQHYkgDFAUET7cEb5VJaHPv5m3ppTBpU9xBcf\
+wbHHUt4VjA+mhRmYrl1khjvZM+X8kEqvWn20BtcM9R6r0yIYec8UERDDHBleL/P8\
+RkxEnVLjYTV9zigCXfMsgYb3EQShAgMBAAGjEDAOMAwGA1UdEwQFMAMBAf8wDQYJ\
+KoZIhvcNAQELBQADggEBABUJpl3QCqsoDSxAsQdV6zKT4VGV76AzoGj7etQsQY+r\
++S26VfWh/fMobEzuxFChr0USgLJ6FoK78hAtoZvt1lrye9yqFv/ig3WLWsJKWHHb\
+3RT6oR03CIwZXFSUasi08QDVLxafwsU5OMcPLucF3a1lRL1ccYrNgVCCx1+X7Bos\
+tIgDGRQQ4AyoHTcfVd2hEGeUv7k14mOxFsAp6851yosHq9Q2kwmdH+rHEJbjof87\
+yyKLagc4owyXBZYkQmkeHWCNqnuRmO5vUsfVb0UUrkD64o7Th/NjwooA7SCiUXl6\
+dfygT1b7ggpx7GC+sP2DsIM47IAZ55drjqX5u2f+Ba0iPQoEdGVzdBIhCIDWwowE\
+Ehl2qRQErGqUUwSsaMpDvWIaGnJGNQqi8oisGNeMy6UFKgxKdXN0IFRlc3Rpbmcq\
+gAFwThsozZxkZxzCn4R8WxNiLFV6m0ye9fEtSbolfaW+EjBMpO03lr/dwNnrclhg\
+ew+A05xfZztrAt16XKEY7qKJ/eY2nLd0fVAIu/nIt+7/VYVXT83zLrWc150aRS7W\
+AdJbL3JOJLs6Eyp5zrPbfI8faRttFAdONKDrJgIpuW1E3g==\
+";
+
+//
+// Expired payment request (expires is set to 1 = 1970-01-01 00:00:01)
+//
+const char* paymentrequest2_cert2_BASE64 =
+"\
+Egt4NTA5K3NoYTI1NhrQBArNBDCCAkkwggExoAMCAQICAQEwDQYJKoZIhvcNAQEL\
+BQAwITEfMB0GA1UEAwwWUGF5bWVudFJlcXVlc3QgVGVzdCBDQTAeFw0xNTAxMTEx\
+ODIxMDhaFw0yNTAxMDgxODIxMDhaMCExHzAdBgNVBAMMFlBheW1lbnRSZXF1ZXN0\
+IFRlc3QgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMsZqzkzeBGo+i2N\
+mUak3Ciodr1V7S062VOy7N0OQYNDQHYkgDFAUET7cEb5VJaHPv5m3ppTBpU9xBcf\
+wbHHUt4VjA+mhRmYrl1khjvZM+X8kEqvWn20BtcM9R6r0yIYec8UERDDHBleL/P8\
+RkxEnVLjYTV9zigCXfMsgYb3EQShAgMBAAGjEDAOMAwGA1UdEwQFMAMBAf8wDQYJ\
+KoZIhvcNAQELBQADggEBABUJpl3QCqsoDSxAsQdV6zKT4VGV76AzoGj7etQsQY+r\
++S26VfWh/fMobEzuxFChr0USgLJ6FoK78hAtoZvt1lrye9yqFv/ig3WLWsJKWHHb\
+3RT6oR03CIwZXFSUasi08QDVLxafwsU5OMcPLucF3a1lRL1ccYrNgVCCx1+X7Bos\
+tIgDGRQQ4AyoHTcfVd2hEGeUv7k14mOxFsAp6851yosHq9Q2kwmdH+rHEJbjof87\
+yyKLagc4owyXBZYkQmkeHWCNqnuRmO5vUsfVb0UUrkD64o7Th/NjwooA7SCiUXl6\
+dfygT1b7ggpx7GC+sP2DsIM47IAZ55drjqX5u2f+Ba0iQgoEdGVzdBIgCICt4gQS\
+GXapFASsapRTBKxoykO9YhoackY1CqLyiKwYiNLUpQUgASoQVGVzdGluZyB0ZXN0\
+bmV0ISqAATXq9A5nmJgtmee/bQTeHeif4w1YYFPBlKghwx6qbVgXTWnwBJtOQhhV\
+sZdzbTl95ENR7/Y7VJupW9kDWobCK7zUUhLAzUlwmLlcx6itHw8LTUF5HK+AwsZm\
+Zs85lISGvOS0NZW/ENa6l+oQRnL87oqVZr/EDGiuqjz6T0ThQi0l\
+";
+
+//
+// Unexpired payment request (expires is set to 0x7FFFFFFFFFFFFFFF = max. int64_t)
+//
+const char* paymentrequest3_cert2_BASE64 =
+"\
+Egt4NTA5K3NoYTI1NhrQBArNBDCCAkkwggExoAMCAQICAQEwDQYJKoZIhvcNAQEL\
+BQAwITEfMB0GA1UEAwwWUGF5bWVudFJlcXVlc3QgVGVzdCBDQTAeFw0xNTAxMTEx\
+ODIxMDhaFw0yNTAxMDgxODIxMDhaMCExHzAdBgNVBAMMFlBheW1lbnRSZXF1ZXN0\
+IFRlc3QgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMsZqzkzeBGo+i2N\
+mUak3Ciodr1V7S062VOy7N0OQYNDQHYkgDFAUET7cEb5VJaHPv5m3ppTBpU9xBcf\
+wbHHUt4VjA+mhRmYrl1khjvZM+X8kEqvWn20BtcM9R6r0yIYec8UERDDHBleL/P8\
+RkxEnVLjYTV9zigCXfMsgYb3EQShAgMBAAGjEDAOMAwGA1UdEwQFMAMBAf8wDQYJ\
+KoZIhvcNAQELBQADggEBABUJpl3QCqsoDSxAsQdV6zKT4VGV76AzoGj7etQsQY+r\
++S26VfWh/fMobEzuxFChr0USgLJ6FoK78hAtoZvt1lrye9yqFv/ig3WLWsJKWHHb\
+3RT6oR03CIwZXFSUasi08QDVLxafwsU5OMcPLucF3a1lRL1ccYrNgVCCx1+X7Bos\
+tIgDGRQQ4AyoHTcfVd2hEGeUv7k14mOxFsAp6851yosHq9Q2kwmdH+rHEJbjof87\
+yyKLagc4owyXBZYkQmkeHWCNqnuRmO5vUsfVb0UUrkD64o7Th/NjwooA7SCiUXl6\
+dfygT1b7ggpx7GC+sP2DsIM47IAZ55drjqX5u2f+Ba0iSgoEdGVzdBIgCICt4gQS\
+GXapFASsapRTBKxoykO9YhoackY1CqLyiKwYyNfZpQUg//////////9/KhBUZXN0\
+aW5nIHRlc3RuZXQhKoABNwi8WnMW4aMvbmvorTiiWJLFhofLFnsoWCJnj3rWLnLh\
+n3w6q/fZ26p50ERL/noxdTUfeFsKnlECkUu/fOcOrqyYDiwvxI0SZ034DleVyFU1\
+Z3T+X0zcL8oe7bX01Yf+s2V+5JXQXarKnKBrZCGgv2ARjFNSZe7E7vGg5K4Q6Q8=\
+";
+
+//
+// Unexpired payment request (expires is set to 0x8000000000000000 > max. int64_t, allowed uint64)
+//
+const char* paymentrequest4_cert2_BASE64 =
+"\
+Egt4NTA5K3NoYTI1NhrQBArNBDCCAkkwggExoAMCAQICAQEwDQYJKoZIhvcNAQEL\
+BQAwITEfMB0GA1UEAwwWUGF5bWVudFJlcXVlc3QgVGVzdCBDQTAeFw0xNTAxMTEx\
+ODIxMDhaFw0yNTAxMDgxODIxMDhaMCExHzAdBgNVBAMMFlBheW1lbnRSZXF1ZXN0\
+IFRlc3QgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMsZqzkzeBGo+i2N\
+mUak3Ciodr1V7S062VOy7N0OQYNDQHYkgDFAUET7cEb5VJaHPv5m3ppTBpU9xBcf\
+wbHHUt4VjA+mhRmYrl1khjvZM+X8kEqvWn20BtcM9R6r0yIYec8UERDDHBleL/P8\
+RkxEnVLjYTV9zigCXfMsgYb3EQShAgMBAAGjEDAOMAwGA1UdEwQFMAMBAf8wDQYJ\
+KoZIhvcNAQELBQADggEBABUJpl3QCqsoDSxAsQdV6zKT4VGV76AzoGj7etQsQY+r\
++S26VfWh/fMobEzuxFChr0USgLJ6FoK78hAtoZvt1lrye9yqFv/ig3WLWsJKWHHb\
+3RT6oR03CIwZXFSUasi08QDVLxafwsU5OMcPLucF3a1lRL1ccYrNgVCCx1+X7Bos\
+tIgDGRQQ4AyoHTcfVd2hEGeUv7k14mOxFsAp6851yosHq9Q2kwmdH+rHEJbjof87\
+yyKLagc4owyXBZYkQmkeHWCNqnuRmO5vUsfVb0UUrkD64o7Th/NjwooA7SCiUXl6\
+dfygT1b7ggpx7GC+sP2DsIM47IAZ55drjqX5u2f+Ba0iSwoEdGVzdBIgCICt4gQS\
+GXapFASsapRTBKxoykO9YhoackY1CqLyiKwYt+HZpQUggICAgICAgICAASoQVGVz\
+dGluZyB0ZXN0bmV0ISqAAXSQG8+GFA18VaKarlYrOz293rNMIub0swKGcQm8jAGX\
+HSLaRgHfUDeEPr4hydy4dtfu59KNwe2xsHOHu/SpO4L8SrA4Dm9A7SlNBVWdcLbw\
+d2hj739GDLz0b5KuJ2SG6VknMRQM976w/m2qlq0ccVGaaZ2zMIGfpzL3p6adwx/5\
+";
diff --git a/src/qt/test/paymentservertests.cpp b/src/qt/test/paymentservertests.cpp
index 70254cd75d..04935192c8 100644
--- a/src/qt/test/paymentservertests.cpp
+++ b/src/qt/test/paymentservertests.cpp
@@ -65,38 +65,44 @@ void PaymentServerTests::paymentServerTests()
OptionsModel optionsModel;
PaymentServer* server = new PaymentServer(NULL, false);
X509_STORE* caStore = X509_STORE_new();
- X509_STORE_add_cert(caStore, parse_b64der_cert(caCert_BASE64));
+ X509_STORE_add_cert(caStore, parse_b64der_cert(caCert1_BASE64));
PaymentServer::LoadRootCAs(caStore);
server->setOptionsModel(&optionsModel);
server->uiReady();
- // Now feed PaymentRequests to server, and observe signals it produces:
- std::vector<unsigned char> data = DecodeBase64(paymentrequest1_BASE64);
- SendCoinsRecipient r = handleRequest(server, data);
+ std::vector<unsigned char> data;
+ SendCoinsRecipient r;
QString merchant;
+
+ // Now feed PaymentRequests to server, and observe signals it produces
+
+ // This payment request validates directly against the
+ // caCert1 certificate authority:
+ data = DecodeBase64(paymentrequest1_cert1_BASE64);
+ r = handleRequest(server, data);
r.paymentRequest.getMerchant(caStore, merchant);
QCOMPARE(merchant, QString("testmerchant.org"));
- // Version of the above, with an expired certificate:
- data = DecodeBase64(paymentrequest2_BASE64);
+ // Signed, but expired, merchant cert in the request:
+ data = DecodeBase64(paymentrequest2_cert1_BASE64);
r = handleRequest(server, data);
r.paymentRequest.getMerchant(caStore, merchant);
QCOMPARE(merchant, QString(""));
- // Long certificate chain:
- data = DecodeBase64(paymentrequest3_BASE64);
+ // 10-long certificate chain, all intermediates valid:
+ data = DecodeBase64(paymentrequest3_cert1_BASE64);
r = handleRequest(server, data);
r.paymentRequest.getMerchant(caStore, merchant);
QCOMPARE(merchant, QString("testmerchant8.org"));
// Long certificate chain, with an expired certificate in the middle:
- data = DecodeBase64(paymentrequest4_BASE64);
+ data = DecodeBase64(paymentrequest4_cert1_BASE64);
r = handleRequest(server, data);
r.paymentRequest.getMerchant(caStore, merchant);
QCOMPARE(merchant, QString(""));
// Validly signed, but by a CA not in our root CA list:
- data = DecodeBase64(paymentrequest5_BASE64);
+ data = DecodeBase64(paymentrequest5_cert1_BASE64);
r = handleRequest(server, data);
r.paymentRequest.getMerchant(caStore, merchant);
QCOMPARE(merchant, QString(""));
@@ -104,12 +110,71 @@ void PaymentServerTests::paymentServerTests()
// Try again with no root CA's, verifiedMerchant should be empty:
caStore = X509_STORE_new();
PaymentServer::LoadRootCAs(caStore);
- data = DecodeBase64(paymentrequest1_BASE64);
+ data = DecodeBase64(paymentrequest1_cert1_BASE64);
r = handleRequest(server, data);
r.paymentRequest.getMerchant(caStore, merchant);
QCOMPARE(merchant, QString(""));
- // Just get some random data big enough to trigger BIP70 DoS protection
+ // Load second root certificate
+ caStore = X509_STORE_new();
+ X509_STORE_add_cert(caStore, parse_b64der_cert(caCert2_BASE64));
+ PaymentServer::LoadRootCAs(caStore);
+
+ QByteArray byteArray;
+
+ // For the tests below we just need the payment request data from
+ // paymentrequestdata.h parsed + stored in r.paymentRequest.
+ //
+ // These tests require us to bypass the following normal client execution flow
+ // shown below to be able to explicitly just trigger a certain condition!
+ //
+ // handleRequest()
+ // -> PaymentServer::eventFilter()
+ // -> PaymentServer::handleURIOrFile()
+ // -> PaymentServer::readPaymentRequestFromFile()
+ // -> PaymentServer::processPaymentRequest()
+
+ // Contains a testnet paytoaddress, so payment request network doesn't match client network:
+ data = DecodeBase64(paymentrequest1_cert2_BASE64);
+ byteArray = QByteArray((const char*)&data[0], data.size());
+ r.paymentRequest.parse(byteArray);
+ // Ensure the request is initialized, because network "main" is default, even for
+ // uninizialized payment requests and that will fail our test here.
+ QVERIFY(r.paymentRequest.IsInitialized());
+ QCOMPARE(PaymentServer::verifyNetwork(r.paymentRequest.getDetails()), false);
+
+ // Expired payment request (expires is set to 1 = 1970-01-01 00:00:01):
+ data = DecodeBase64(paymentrequest2_cert2_BASE64);
+ byteArray = QByteArray((const char*)&data[0], data.size());
+ r.paymentRequest.parse(byteArray);
+ // Ensure the request is initialized
+ QVERIFY(r.paymentRequest.IsInitialized());
+ // compares 1 < GetTime() == false (treated as expired payment request)
+ QCOMPARE(PaymentServer::verifyExpired(r.paymentRequest.getDetails()), true);
+
+ // Unexpired payment request (expires is set to 0x7FFFFFFFFFFFFFFF = max. int64_t):
+ // 9223372036854775807 (uint64), 9223372036854775807 (int64_t) and -1 (int32_t)
+ // -1 is 1969-12-31 23:59:59 (for a 32 bit time values)
+ data = DecodeBase64(paymentrequest3_cert2_BASE64);
+ byteArray = QByteArray((const char*)&data[0], data.size());
+ r.paymentRequest.parse(byteArray);
+ // Ensure the request is initialized
+ QVERIFY(r.paymentRequest.IsInitialized());
+ // compares 9223372036854775807 < GetTime() == false (treated as unexpired payment request)
+ QCOMPARE(PaymentServer::verifyExpired(r.paymentRequest.getDetails()), false);
+
+ // Unexpired payment request (expires is set to 0x8000000000000000 > max. int64_t, allowed uint64):
+ // 9223372036854775808 (uint64), -9223372036854775808 (int64_t) and 0 (int32_t)
+ // 0 is 1970-01-01 00:00:00 (for a 32 bit time values)
+ data = DecodeBase64(paymentrequest4_cert2_BASE64);
+ byteArray = QByteArray((const char*)&data[0], data.size());
+ r.paymentRequest.parse(byteArray);
+ // Ensure the request is initialized
+ QVERIFY(r.paymentRequest.IsInitialized());
+ // compares -9223372036854775808 < GetTime() == true (treated as expired payment request)
+ QCOMPARE(PaymentServer::verifyExpired(r.paymentRequest.getDetails()), true);
+
+ // Test BIP70 DoS protection:
unsigned char randData[BIP70_MAX_PAYMENTREQUEST_SIZE + 1];
GetRandBytes(randData, sizeof(randData));
// Write data to a temp file:
@@ -117,7 +182,6 @@ void PaymentServerTests::paymentServerTests()
tempFile.open();
tempFile.write((const char*)randData, sizeof(randData));
tempFile.close();
- // Trigger BIP70 DoS protection
QCOMPARE(PaymentServer::readPaymentRequestFromFile(tempFile.fileName(), r.paymentRequest), false);
delete server;
diff --git a/src/qt/transactiontablemodel.cpp b/src/qt/transactiontablemodel.cpp
index 6771e77180..df1afbfaaa 100644
--- a/src/qt/transactiontablemodel.cpp
+++ b/src/qt/transactiontablemodel.cpp
@@ -94,7 +94,7 @@ public:
*/
void updateWallet(const uint256 &hash, int status, bool showTransaction)
{
- qDebug() << "TransactionTablePriv::updateWallet : " + QString::fromStdString(hash.ToString()) + " " + QString::number(status);
+ qDebug() << "TransactionTablePriv::updateWallet: " + QString::fromStdString(hash.ToString()) + " " + QString::number(status);
// Find bounds of this transaction in model
QList<TransactionRecord>::iterator lower = qLowerBound(
@@ -122,7 +122,7 @@ public:
case CT_NEW:
if(inModel)
{
- qWarning() << "TransactionTablePriv::updateWallet : Warning: Got CT_NEW, but transaction is already in model";
+ qWarning() << "TransactionTablePriv::updateWallet: Warning: Got CT_NEW, but transaction is already in model";
break;
}
if(showTransaction)
@@ -132,7 +132,7 @@ public:
std::map<uint256, CWalletTx>::iterator mi = wallet->mapWallet.find(hash);
if(mi == wallet->mapWallet.end())
{
- qWarning() << "TransactionTablePriv::updateWallet : Warning: Got CT_NEW, but transaction is not in wallet";
+ qWarning() << "TransactionTablePriv::updateWallet: Warning: Got CT_NEW, but transaction is not in wallet";
break;
}
// Added -- insert at the right position
@@ -154,7 +154,7 @@ public:
case CT_DELETED:
if(!inModel)
{
- qWarning() << "TransactionTablePriv::updateWallet : Warning: Got CT_DELETED, but transaction is not in model";
+ qWarning() << "TransactionTablePriv::updateWallet: Warning: Got CT_DELETED, but transaction is not in model";
break;
}
// Removed -- remove entire transaction from table
@@ -664,7 +664,7 @@ public:
void invoke(QObject *ttm)
{
QString strHash = QString::fromStdString(hash.GetHex());
- qDebug() << "NotifyTransactionChanged : " + strHash + " status= " + QString::number(status);
+ qDebug() << "NotifyTransactionChanged: " + strHash + " status= " + QString::number(status);
QMetaObject::invokeMethod(ttm, "updateTransaction", Qt::QueuedConnection,
Q_ARG(QString, strHash),
Q_ARG(int, status),
diff --git a/src/qt/transactionview.h b/src/qt/transactionview.h
index 2858982f09..092d919042 100644
--- a/src/qt/transactionview.h
+++ b/src/qt/transactionview.h
@@ -49,10 +49,10 @@ public:
};
enum ColumnWidths {
- STATUS_COLUMN_WIDTH = 23,
+ STATUS_COLUMN_WIDTH = 30,
WATCHONLY_COLUMN_WIDTH = 23,
DATE_COLUMN_WIDTH = 120,
- TYPE_COLUMN_WIDTH = 120,
+ TYPE_COLUMN_WIDTH = 113,
AMOUNT_MINIMUM_COLUMN_WIDTH = 120,
MINIMUM_COLUMN_WIDTH = 23
};
diff --git a/src/qt/utilitydialog.cpp b/src/qt/utilitydialog.cpp
index 9ee408179d..63dd6efb52 100644
--- a/src/qt/utilitydialog.cpp
+++ b/src/qt/utilitydialog.cpp
@@ -12,6 +12,7 @@
#include "clientversion.h"
#include "init.h"
+#include "util.h"
#include <stdio.h>
@@ -73,8 +74,8 @@ HelpMessageDialog::HelpMessageDialog(QWidget *parent, bool about) :
tf.setBorderStyle(QTextFrameFormat::BorderStyle_None);
tf.setCellPadding(2);
QVector<QTextLength> widths;
- widths << QTextLength(QTextLength::PercentageLength, 20);
- widths << QTextLength(QTextLength::PercentageLength, 80);
+ widths << QTextLength(QTextLength::PercentageLength, 35);
+ widths << QTextLength(QTextLength::PercentageLength, 65);
tf.setColumnWidthConstraints(widths);
QTextTable *table = cursor.insertTable(2, 2, tf);
@@ -108,6 +109,12 @@ HelpMessageDialog::HelpMessageDialog(QWidget *parent, bool about) :
cursor.movePosition(QTextCursor::NextRow);
cursor.insertText(tr("UI options") + ":", bold);
cursor.movePosition(QTextCursor::NextRow);
+ if (GetBoolArg("-help-debug", false)) {
+ cursor.insertText("-allowselfsignedrootcertificates");
+ cursor.movePosition(QTextCursor::NextCell);
+ cursor.insertText(tr("Allow self signed root certificates (default: 0)"));
+ cursor.movePosition(QTextCursor::NextCell);
+ }
cursor.insertText("-choosedatadir");
cursor.movePosition(QTextCursor::NextCell);
cursor.insertText(tr("Choose data directory on startup (default: 0)"));
@@ -130,6 +137,7 @@ HelpMessageDialog::HelpMessageDialog(QWidget *parent, bool about) :
ui->helpMessage->moveCursor(QTextCursor::Start);
ui->scrollArea->setVisible(false);
+ ui->aboutLogo->setVisible(false);
}
}
diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp
index 6006a7bd7b..79f5191fc0 100644
--- a/src/qt/walletmodel.cpp
+++ b/src/qt/walletmodel.cpp
@@ -6,6 +6,7 @@
#include "addresstablemodel.h"
#include "guiconstants.h"
+#include "paymentserver.h"
#include "recentrequeststablemodel.h"
#include "transactiontablemodel.h"
@@ -278,9 +279,9 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact
return TransactionCreationFailed;
}
- // reject insane fee > 0.1 bitcoin
+ // reject absurdly high fee > 0.1 bitcoin
if (nFeeRequired > 10000000)
- return InsaneFee;
+ return AbsurdFee;
}
return SendCoinsReturn(OK);
@@ -294,11 +295,16 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(WalletModelTransaction &tran
LOCK2(cs_main, wallet->cs_wallet);
CWalletTx *newTx = transaction.getTransaction();
- // Store PaymentRequests in wtx.vOrderForm in wallet.
foreach(const SendCoinsRecipient &rcp, transaction.getRecipients())
{
if (rcp.paymentRequest.IsInitialized())
{
+ // Make sure any payment requests involved are still valid.
+ if (PaymentServer::verifyExpired(rcp.paymentRequest.getDetails())) {
+ return PaymentRequestExpired;
+ }
+
+ // Store PaymentRequests in wtx.vOrderForm in wallet.
std::string key("PaymentRequest");
std::string value;
rcp.paymentRequest.SerializeToString(&value);
@@ -446,7 +452,7 @@ static void NotifyAddressBookChanged(WalletModel *walletmodel, CWallet *wallet,
QString strLabel = QString::fromStdString(label);
QString strPurpose = QString::fromStdString(purpose);
- qDebug() << "NotifyAddressBookChanged : " + strAddress + " " + strLabel + " isMine=" + QString::number(isMine) + " purpose=" + strPurpose + " status=" + QString::number(status);
+ qDebug() << "NotifyAddressBookChanged: " + strAddress + " " + strLabel + " isMine=" + QString::number(isMine) + " purpose=" + strPurpose + " status=" + QString::number(status);
QMetaObject::invokeMethod(walletmodel, "updateAddressBook", Qt::QueuedConnection,
Q_ARG(QString, strAddress),
Q_ARG(QString, strLabel),
diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h
index d8df25f660..4a9a12beaa 100644
--- a/src/qt/walletmodel.h
+++ b/src/qt/walletmodel.h
@@ -40,7 +40,7 @@ public:
explicit SendCoinsRecipient(const QString &addr, const QString &label, const CAmount& amount, const QString &message):
address(addr), label(label), amount(amount), message(message), nVersion(SendCoinsRecipient::CURRENT_VERSION) {}
- // If from an insecure payment request, this is used for storing
+ // If from an unauthenticated payment request, this is used for storing
// the addresses, e.g. address-A<br />address-B<br />address-C.
// Info: As we don't need to process addresses in here when using
// payment requests, we can abuse it for displaying an address list.
@@ -111,7 +111,8 @@ public:
DuplicateAddress,
TransactionCreationFailed, // Error returned when wallet is still locked
TransactionCommitFailed,
- InsaneFee
+ AbsurdFee,
+ PaymentRequestExpired
};
enum EncryptionStatus
diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp
index cfc559d198..293d6d5619 100644
--- a/src/rpcblockchain.cpp
+++ b/src/rpcblockchain.cpp
@@ -105,6 +105,7 @@ Value getblockcount(const Array& params, bool fHelp)
+ HelpExampleRpc("getblockcount", "")
);
+ LOCK(cs_main);
return chainActive.Height();
}
@@ -121,6 +122,7 @@ Value getbestblockhash(const Array& params, bool fHelp)
+ HelpExampleRpc("getbestblockhash", "")
);
+ LOCK(cs_main);
return chainActive.Tip()->GetBlockHash().GetHex();
}
@@ -137,6 +139,7 @@ Value getdifficulty(const Array& params, bool fHelp)
+ HelpExampleRpc("getdifficulty", "")
);
+ LOCK(cs_main);
return GetDifficulty();
}
@@ -173,6 +176,8 @@ Value getrawmempool(const Array& params, bool fHelp)
+ HelpExampleRpc("getrawmempool", "true")
);
+ LOCK(cs_main);
+
bool fVerbose = false;
if (params.size() > 0)
fVerbose = params[0].get_bool();
@@ -233,6 +238,8 @@ Value getblockhash(const Array& params, bool fHelp)
+ HelpExampleRpc("getblockhash", "1000")
);
+ LOCK(cs_main);
+
int nHeight = params[0].get_int();
if (nHeight < 0 || nHeight > chainActive.Height())
throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range");
@@ -277,6 +284,8 @@ Value getblock(const Array& params, bool fHelp)
+ HelpExampleRpc("getblock", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"")
);
+ LOCK(cs_main);
+
std::string strHash = params[0].get_str();
uint256 hash(uint256S(strHash));
@@ -326,6 +335,8 @@ Value gettxoutsetinfo(const Array& params, bool fHelp)
+ HelpExampleRpc("gettxoutsetinfo", "")
);
+ LOCK(cs_main);
+
Object ret;
CCoinsStats stats;
@@ -380,6 +391,8 @@ Value gettxout(const Array& params, bool fHelp)
+ HelpExampleRpc("gettxout", "\"txid\", 1")
);
+ LOCK(cs_main);
+
Object ret;
std::string strHash = params[0].get_str();
@@ -436,6 +449,8 @@ Value verifychain(const Array& params, bool fHelp)
+ HelpExampleRpc("verifychain", "")
);
+ LOCK(cs_main);
+
int nCheckLevel = GetArg("-checklevel", 3);
int nCheckDepth = GetArg("-checkblocks", 288);
if (params.size() > 0)
@@ -467,6 +482,8 @@ Value getblockchaininfo(const Array& params, bool fHelp)
+ HelpExampleRpc("getblockchaininfo", "")
);
+ LOCK(cs_main);
+
Object obj;
obj.push_back(Pair("chain", Params().NetworkIDString()));
obj.push_back(Pair("blocks", (int)chainActive.Height()));
@@ -526,6 +543,8 @@ Value getchaintips(const Array& params, bool fHelp)
+ HelpExampleRpc("getchaintips", "")
);
+ LOCK(cs_main);
+
/* Build up a list of chain tips. We start with the list of all
known blocks, and successively remove blocks that appear as pprev
of another block. */
diff --git a/src/rpcdump.cpp b/src/rpcdump.cpp
index 8666779cc1..b9c92a06c5 100644
--- a/src/rpcdump.cpp
+++ b/src/rpcdump.cpp
@@ -91,6 +91,8 @@ Value importprivkey(const Array& params, bool fHelp)
+ HelpExampleRpc("importprivkey", "\"mykey\", \"testing\", false")
);
+ LOCK2(cs_main, pwalletMain->cs_wallet);
+
EnsureWalletIsUnlocked();
string strSecret = params[0].get_str();
@@ -158,6 +160,8 @@ Value importaddress(const Array& params, bool fHelp)
+ HelpExampleRpc("importaddress", "\"myaddress\", \"testing\", false")
);
+ LOCK2(cs_main, pwalletMain->cs_wallet);
+
CScript script;
CBitcoinAddress address(params[0].get_str());
@@ -223,6 +227,8 @@ Value importwallet(const Array& params, bool fHelp)
+ HelpExampleRpc("importwallet", "\"test\"")
);
+ LOCK2(cs_main, pwalletMain->cs_wallet);
+
EnsureWalletIsUnlocked();
ifstream file;
@@ -322,6 +328,8 @@ Value dumpprivkey(const Array& params, bool fHelp)
+ HelpExampleRpc("dumpprivkey", "\"myaddress\"")
);
+ LOCK2(cs_main, pwalletMain->cs_wallet);
+
EnsureWalletIsUnlocked();
string strAddress = params[0].get_str();
@@ -351,6 +359,8 @@ Value dumpwallet(const Array& params, bool fHelp)
+ HelpExampleRpc("dumpwallet", "\"test\"")
);
+ LOCK2(cs_main, pwalletMain->cs_wallet);
+
EnsureWalletIsUnlocked();
ofstream file;
diff --git a/src/rpcmining.cpp b/src/rpcmining.cpp
index 603e2935dd..e3ae5cff42 100644
--- a/src/rpcmining.cpp
+++ b/src/rpcmining.cpp
@@ -44,7 +44,7 @@ Value GetNetworkHashPS(int lookup, int height) {
// If lookup is -1, then use blocks since last difficulty change.
if (lookup <= 0)
- lookup = pb->nHeight % 2016 + 1;
+ lookup = pb->nHeight % Params().Interval() + 1;
// If lookup is larger than chain, then set it to chain length.
if (lookup > pb->nHeight)
@@ -88,6 +88,7 @@ Value getnetworkhashps(const Array& params, bool fHelp)
+ HelpExampleRpc("getnetworkhashps", "")
);
+ LOCK(cs_main);
return GetNetworkHashPS(params.size() > 0 ? params[0].get_int() : 120, params.size() > 1 ? params[1].get_int() : -1);
}
@@ -107,6 +108,7 @@ Value getgenerate(const Array& params, bool fHelp)
+ HelpExampleRpc("getgenerate", "")
);
+ LOCK(cs_main);
return GetBoolArg("-gen", false);
}
@@ -200,25 +202,6 @@ Value setgenerate(const Array& params, bool fHelp)
return Value::null;
}
-
-Value gethashespersec(const Array& params, bool fHelp)
-{
- if (fHelp || params.size() != 0)
- throw runtime_error(
- "gethashespersec\n"
- "\nReturns a recent hashes per second performance measurement while generating.\n"
- "See the getgenerate and setgenerate calls to turn generation on and off.\n"
- "\nResult:\n"
- "n (numeric) The recent hashes per second when generation is on (will return 0 if generation is off)\n"
- "\nExamples:\n"
- + HelpExampleCli("gethashespersec", "")
- + HelpExampleRpc("gethashespersec", "")
- );
-
- if (GetTimeMillis() - nHPSTimerStart > 8000)
- return (int64_t)0;
- return (int64_t)dHashesPerSec;
-}
#endif
@@ -237,7 +220,6 @@ Value getmininginfo(const Array& params, bool fHelp)
" \"errors\": \"...\" (string) Current errors\n"
" \"generate\": true|false (boolean) If the generation is on or off (see getgenerate or setgenerate calls)\n"
" \"genproclimit\": n (numeric) The processor limit for generation. -1 if no generation. (see getgenerate or setgenerate calls)\n"
- " \"hashespersec\": n (numeric) The hashes per second of the generation, or 0 if no generation.\n"
" \"pooledtx\": n (numeric) The size of the mem pool\n"
" \"testnet\": true|false (boolean) If using testnet or not\n"
" \"chain\": \"xxxx\", (string) current network name as defined in BIP70 (main, test, regtest)\n"
@@ -247,6 +229,9 @@ Value getmininginfo(const Array& params, bool fHelp)
+ HelpExampleRpc("getmininginfo", "")
);
+
+ LOCK(cs_main);
+
Object obj;
obj.push_back(Pair("blocks", (int)chainActive.Height()));
obj.push_back(Pair("currentblocksize", (uint64_t)nLastBlockSize));
@@ -260,7 +245,6 @@ Value getmininginfo(const Array& params, bool fHelp)
obj.push_back(Pair("chain", Params().NetworkIDString()));
#ifdef ENABLE_WALLET
obj.push_back(Pair("generate", getgenerate(params, false)));
- obj.push_back(Pair("hashespersec", gethashespersec(params, false)));
#endif
return obj;
}
@@ -288,8 +272,9 @@ Value prioritisetransaction(const Array& params, bool fHelp)
+ HelpExampleRpc("prioritisetransaction", "\"txid\", 0.0, 10000")
);
- uint256 hash = ParseHashStr(params[0].get_str(), "txid");
+ LOCK(cs_main);
+ uint256 hash = ParseHashStr(params[0].get_str(), "txid");
CAmount nAmount = params[2].get_int64();
mempool.PrioritiseTransaction(hash, params[0].get_str(), params[1].get_real(), nAmount);
@@ -378,6 +363,8 @@ Value getblocktemplate(const Array& params, bool fHelp)
+ HelpExampleRpc("getblocktemplate", "")
);
+ LOCK(cs_main);
+
std::string strMode = "template";
Value lpval = Value::null;
if (params.size() > 0)
@@ -459,10 +446,6 @@ Value getblocktemplate(const Array& params, bool fHelp)
}
// Release the wallet and main lock while waiting
-#ifdef ENABLE_WALLET
- if(pwalletMain)
- LEAVE_CRITICAL_SECTION(pwalletMain->cs_wallet);
-#endif
LEAVE_CRITICAL_SECTION(cs_main);
{
checktxtime = boost::get_system_time() + boost::posix_time::minutes(1);
@@ -480,10 +463,6 @@ Value getblocktemplate(const Array& params, bool fHelp)
}
}
ENTER_CRITICAL_SECTION(cs_main);
-#ifdef ENABLE_WALLET
- if(pwalletMain)
- ENTER_CRITICAL_SECTION(pwalletMain->cs_wallet);
-#endif
if (!IsRPCRunning())
throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Shutting down");
diff --git a/src/rpcmisc.cpp b/src/rpcmisc.cpp
index 184aacf5a8..8d260b1cc9 100644
--- a/src/rpcmisc.cpp
+++ b/src/rpcmisc.cpp
@@ -69,6 +69,12 @@ Value getinfo(const Array& params, bool fHelp)
+ HelpExampleRpc("getinfo", "")
);
+#ifdef ENABLE_WALLET
+ LOCK2(cs_main, pwalletMain ? &pwalletMain->cs_wallet : NULL);
+#else
+ LOCK(cs_main);
+#endif
+
proxyType proxy;
GetProxy(NET_IPV4, proxy);
@@ -165,13 +171,19 @@ Value validateaddress(const Array& params, bool fHelp)
" \"isscript\" : true|false, (boolean) If the key is a script\n"
" \"pubkey\" : \"publickeyhex\", (string) The hex value of the raw public key\n"
" \"iscompressed\" : true|false, (boolean) If the address is compressed\n"
- " \"account\" : \"account\" (string) The account associated with the address, \"\" is the default account\n"
+ " \"account\" : \"account\" (string) DEPRECATED. The account associated with the address, \"\" is the default account\n"
"}\n"
"\nExamples:\n"
+ HelpExampleCli("validateaddress", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"")
+ HelpExampleRpc("validateaddress", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"")
);
+#ifdef ENABLE_WALLET
+ LOCK2(cs_main, pwalletMain ? &pwalletMain->cs_wallet : NULL);
+#else
+ LOCK(cs_main);
+#endif
+
CBitcoinAddress address(params[0].get_str());
bool isValid = address.IsValid();
@@ -329,6 +341,8 @@ Value verifymessage(const Array& params, bool fHelp)
+ HelpExampleRpc("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\", \"signature\", \"my message\"")
);
+ LOCK(cs_main);
+
string strAddress = params[0].get_str();
string strSign = params[1].get_str();
string strMessage = params[2].get_str();
@@ -372,6 +386,8 @@ Value setmocktime(const Array& params, bool fHelp)
if (!Params().MineBlocksOnDemand())
throw runtime_error("setmocktime for regression testing (-regtest mode) only");
+ LOCK(cs_main);
+
RPCTypeCheck(params, boost::assign::list_of(int_type));
SetMockTime(params[0].get_int64());
diff --git a/src/rpcnet.cpp b/src/rpcnet.cpp
index f0fadb5987..6306fd4406 100644
--- a/src/rpcnet.cpp
+++ b/src/rpcnet.cpp
@@ -34,7 +34,8 @@ Value getconnectioncount(const Array& params, bool fHelp)
+ HelpExampleRpc("getconnectioncount", "")
);
- LOCK(cs_vNodes);
+ LOCK2(cs_main, cs_vNodes);
+
return (int)vNodes.size();
}
@@ -52,7 +53,8 @@ Value ping(const Array& params, bool fHelp)
);
// Request that each node send a ping during next message processing pass
- LOCK(cs_vNodes);
+ LOCK2(cs_main, cs_vNodes);
+
BOOST_FOREACH(CNode* pNode, vNodes) {
pNode->fPingQueued = true;
}
@@ -113,6 +115,8 @@ Value getpeerinfo(const Array& params, bool fHelp)
+ HelpExampleRpc("getpeerinfo", "")
);
+ LOCK(cs_main);
+
vector<CNodeStats> vstats;
CopyNodeStats(vstats);
@@ -411,6 +415,8 @@ Value getnetworkinfo(const Array& params, bool fHelp)
+ HelpExampleRpc("getnetworkinfo", "")
);
+ LOCK(cs_main);
+
Object obj;
obj.push_back(Pair("version", CLIENT_VERSION));
obj.push_back(Pair("subversion",
diff --git a/src/rpcrawtransaction.cpp b/src/rpcrawtransaction.cpp
index 9bd8233992..4a079f5c81 100644
--- a/src/rpcrawtransaction.cpp
+++ b/src/rpcrawtransaction.cpp
@@ -169,6 +169,8 @@ Value getrawtransaction(const Array& params, bool fHelp)
+ HelpExampleRpc("getrawtransaction", "\"mytxid\", 1")
);
+ LOCK(cs_main);
+
uint256 hash = ParseHashV(params[0], "parameter 1");
bool fVerbose = false;
@@ -216,7 +218,7 @@ Value listunspent(const Array& params, bool fHelp)
" \"txid\" : \"txid\", (string) the transaction id \n"
" \"vout\" : n, (numeric) the vout value\n"
" \"address\" : \"address\", (string) the bitcoin address\n"
- " \"account\" : \"account\", (string) The associated account, or \"\" for the default account\n"
+ " \"account\" : \"account\", (string) DEPRECATED. The associated account, or \"\" for the default account\n"
" \"scriptPubKey\" : \"key\", (string) the script key\n"
" \"amount\" : x.xxx, (numeric) the transaction amount in btc\n"
" \"confirmations\" : n (numeric) The number of confirmations\n"
@@ -256,6 +258,7 @@ Value listunspent(const Array& params, bool fHelp)
Array results;
vector<COutput> vecOutputs;
assert(pwalletMain != NULL);
+ LOCK2(cs_main, pwalletMain->cs_wallet);
pwalletMain->AvailableCoins(vecOutputs, false);
BOOST_FOREACH(const COutput& out, vecOutputs) {
if (out.nDepth < nMinDepth || out.nDepth > nMaxDepth)
@@ -334,6 +337,7 @@ Value createrawtransaction(const Array& params, bool fHelp)
+ HelpExampleRpc("createrawtransaction", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\", \"{\\\"address\\\":0.01}\"")
);
+ LOCK(cs_main);
RPCTypeCheck(params, boost::assign::list_of(array_type)(obj_type));
Array inputs = params[0].get_array();
@@ -428,6 +432,7 @@ Value decoderawtransaction(const Array& params, bool fHelp)
+ HelpExampleRpc("decoderawtransaction", "\"hexstring\"")
);
+ LOCK(cs_main);
RPCTypeCheck(params, boost::assign::list_of(str_type));
CTransaction tx;
@@ -466,6 +471,7 @@ Value decodescript(const Array& params, bool fHelp)
+ HelpExampleRpc("decodescript", "\"hexstring\"")
);
+ LOCK(cs_main);
RPCTypeCheck(params, boost::assign::list_of(str_type));
Object r;
@@ -532,6 +538,11 @@ Value signrawtransaction(const Array& params, bool fHelp)
+ HelpExampleRpc("signrawtransaction", "\"myhex\"")
);
+#ifdef ENABLE_WALLET
+ LOCK2(cs_main, pwalletMain ? &pwalletMain->cs_wallet : NULL);
+#else
+ LOCK(cs_main);
+#endif
RPCTypeCheck(params, boost::assign::list_of(str_type)(array_type)(array_type)(str_type), true);
vector<unsigned char> txData(ParseHexV(params[0], "argument 1"));
@@ -591,7 +602,7 @@ Value signrawtransaction(const Array& params, bool fHelp)
}
}
#ifdef ENABLE_WALLET
- else
+ else if (pwalletMain)
EnsureWalletIsUnlocked();
#endif
@@ -688,7 +699,7 @@ Value signrawtransaction(const Array& params, bool fHelp)
BOOST_FOREACH(const CMutableTransaction& txv, txVariants) {
txin.scriptSig = CombineSignatures(prevPubKey, mergedTx, i, txin.scriptSig, txv.vin[i].scriptSig);
}
- if (!VerifyScript(txin.scriptSig, prevPubKey, STANDARD_SCRIPT_VERIFY_FLAGS, SignatureChecker(mergedTx, i)))
+ if (!VerifyScript(txin.scriptSig, prevPubKey, STANDARD_SCRIPT_VERIFY_FLAGS, MutableTransactionSignatureChecker(&mergedTx, i)))
fComplete = false;
}
@@ -722,6 +733,7 @@ Value sendrawtransaction(const Array& params, bool fHelp)
+ HelpExampleRpc("sendrawtransaction", "\"signedhex\"")
);
+ LOCK(cs_main);
RPCTypeCheck(params, boost::assign::list_of(str_type)(bool_type));
// parse hex string from parameter
diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp
index a070ab5bbe..20e9252d7e 100644
--- a/src/rpcserver.cpp
+++ b/src/rpcserver.cpp
@@ -7,9 +7,11 @@
#include "base58.h"
#include "init.h"
-#include "main.h"
+#include "random.h"
+#include "sync.h"
#include "ui_interface.h"
#include "util.h"
+#include "utilstrencodings.h"
#ifdef ENABLE_WALLET
#include "wallet.h"
#endif
@@ -23,11 +25,13 @@
#include <boost/iostreams/concepts.hpp>
#include <boost/iostreams/stream.hpp>
#include <boost/shared_ptr.hpp>
+#include <boost/signals2/signal.hpp>
#include <boost/thread.hpp>
#include "json/json_spirit_writer_template.h"
using namespace boost::asio;
using namespace json_spirit;
+using namespace RPCServer;
using namespace std;
static std::string strRPCUserColonPass;
@@ -46,6 +50,34 @@ static boost::asio::io_service::work *rpc_dummy_work = NULL;
static std::vector<CSubNet> rpc_allow_subnets; //!< List of subnets to allow RPC connections from
static std::vector< boost::shared_ptr<ip::tcp::acceptor> > rpc_acceptors;
+static struct CRPCSignals
+{
+ boost::signals2::signal<void ()> Started;
+ boost::signals2::signal<void ()> Stopped;
+ boost::signals2::signal<void (const CRPCCommand&)> PreCommand;
+ boost::signals2::signal<void (const CRPCCommand&)> PostCommand;
+} g_rpcSignals;
+
+void RPCServer::OnStarted(boost::function<void ()> slot)
+{
+ g_rpcSignals.Started.connect(slot);
+}
+
+void RPCServer::OnStopped(boost::function<void ()> slot)
+{
+ g_rpcSignals.Stopped.connect(slot);
+}
+
+void RPCServer::OnPreCommand(boost::function<void (const CRPCCommand&)> slot)
+{
+ g_rpcSignals.PreCommand.connect(boost::bind(slot, _1));
+}
+
+void RPCServer::OnPostCommand(boost::function<void (const CRPCCommand&)> slot)
+{
+ g_rpcSignals.PostCommand.connect(boost::bind(slot, _1));
+}
+
void RPCTypeCheck(const Array& params,
const list<Value_type>& typesExpected,
bool fAllowNull)
@@ -239,113 +271,110 @@ Value stop(const Array& params, bool fHelp)
* Call Table
*/
static const CRPCCommand vRPCCommands[] =
-{ // category name actor (function) okSafeMode threadSafe reqWallet
- // --------------------- ------------------------ ----------------------- ---------- ---------- ---------
+{ // category name actor (function) okSafeMode reqWallet
+ // --------------------- ------------------------ ----------------------- ---------- ---------
/* Overall control/query calls */
- { "control", "getinfo", &getinfo, true, false, false }, /* uses wallet if enabled */
- { "control", "help", &help, true, true, false },
- { "control", "stop", &stop, true, true, false },
+ { "control", "getinfo", &getinfo, true, false }, /* uses wallet if enabled */
+ { "control", "help", &help, true, false },
+ { "control", "stop", &stop, true, false },
/* P2P networking */
- { "network", "getnetworkinfo", &getnetworkinfo, true, false, false },
- { "network", "addnode", &addnode, true, true, false },
- { "network", "getaddednodeinfo", &getaddednodeinfo, true, true, false },
- { "network", "getconnectioncount", &getconnectioncount, true, false, false },
- { "network", "getnettotals", &getnettotals, true, true, false },
- { "network", "getpeerinfo", &getpeerinfo, true, false, false },
- { "network", "ping", &ping, true, false, false },
+ { "network", "getnetworkinfo", &getnetworkinfo, true, false },
+ { "network", "addnode", &addnode, true, false },
+ { "network", "getaddednodeinfo", &getaddednodeinfo, true, false },
+ { "network", "getconnectioncount", &getconnectioncount, true, false },
+ { "network", "getnettotals", &getnettotals, true, false },
+ { "network", "getpeerinfo", &getpeerinfo, true, false },
+ { "network", "ping", &ping, true, false },
/* Block chain and UTXO */
- { "blockchain", "getblockchaininfo", &getblockchaininfo, true, false, false },
- { "blockchain", "getbestblockhash", &getbestblockhash, true, false, false },
- { "blockchain", "getblockcount", &getblockcount, true, false, false },
- { "blockchain", "getblock", &getblock, true, false, false },
- { "blockchain", "getblockhash", &getblockhash, true, false, false },
- { "blockchain", "getchaintips", &getchaintips, true, false, false },
- { "blockchain", "getdifficulty", &getdifficulty, true, false, false },
- { "blockchain", "getmempoolinfo", &getmempoolinfo, true, true, false },
- { "blockchain", "getrawmempool", &getrawmempool, true, false, false },
- { "blockchain", "gettxout", &gettxout, true, false, false },
- { "blockchain", "gettxoutsetinfo", &gettxoutsetinfo, true, false, false },
- { "blockchain", "verifychain", &verifychain, true, false, false },
- { "blockchain", "invalidateblock", &invalidateblock, true, true, false },
- { "blockchain", "reconsiderblock", &reconsiderblock, true, true, false },
+ { "blockchain", "getblockchaininfo", &getblockchaininfo, true, false },
+ { "blockchain", "getbestblockhash", &getbestblockhash, true, false },
+ { "blockchain", "getblockcount", &getblockcount, true, false },
+ { "blockchain", "getblock", &getblock, true, false },
+ { "blockchain", "getblockhash", &getblockhash, true, false },
+ { "blockchain", "getchaintips", &getchaintips, true, false },
+ { "blockchain", "getdifficulty", &getdifficulty, true, false },
+ { "blockchain", "getmempoolinfo", &getmempoolinfo, true, false },
+ { "blockchain", "getrawmempool", &getrawmempool, true, false },
+ { "blockchain", "gettxout", &gettxout, true, false },
+ { "blockchain", "gettxoutsetinfo", &gettxoutsetinfo, true, false },
+ { "blockchain", "verifychain", &verifychain, true, false },
/* Mining */
- { "mining", "getblocktemplate", &getblocktemplate, true, false, false },
- { "mining", "getmininginfo", &getmininginfo, true, false, false },
- { "mining", "getnetworkhashps", &getnetworkhashps, true, false, false },
- { "mining", "prioritisetransaction", &prioritisetransaction, true, false, false },
- { "mining", "submitblock", &submitblock, true, true, false },
+ { "mining", "getblocktemplate", &getblocktemplate, true, false },
+ { "mining", "getmininginfo", &getmininginfo, true, false },
+ { "mining", "getnetworkhashps", &getnetworkhashps, true, false },
+ { "mining", "prioritisetransaction", &prioritisetransaction, true, false },
+ { "mining", "submitblock", &submitblock, true, false },
#ifdef ENABLE_WALLET
/* Coin generation */
- { "generating", "getgenerate", &getgenerate, true, false, false },
- { "generating", "gethashespersec", &gethashespersec, true, false, false },
- { "generating", "setgenerate", &setgenerate, true, true, false },
+ { "generating", "getgenerate", &getgenerate, true, false },
+ { "generating", "setgenerate", &setgenerate, true, false },
#endif
/* Raw transactions */
- { "rawtransactions", "createrawtransaction", &createrawtransaction, true, false, false },
- { "rawtransactions", "decoderawtransaction", &decoderawtransaction, true, false, false },
- { "rawtransactions", "decodescript", &decodescript, true, false, false },
- { "rawtransactions", "getrawtransaction", &getrawtransaction, true, false, false },
- { "rawtransactions", "sendrawtransaction", &sendrawtransaction, false, false, false },
- { "rawtransactions", "signrawtransaction", &signrawtransaction, false, false, false }, /* uses wallet if enabled */
+ { "rawtransactions", "createrawtransaction", &createrawtransaction, true, false },
+ { "rawtransactions", "decoderawtransaction", &decoderawtransaction, true, false },
+ { "rawtransactions", "decodescript", &decodescript, true, false },
+ { "rawtransactions", "getrawtransaction", &getrawtransaction, true, false },
+ { "rawtransactions", "sendrawtransaction", &sendrawtransaction, false, false },
+ { "rawtransactions", "signrawtransaction", &signrawtransaction, false, false }, /* uses wallet if enabled */
/* Utility functions */
- { "util", "createmultisig", &createmultisig, true, true , false },
- { "util", "validateaddress", &validateaddress, true, false, false }, /* uses wallet if enabled */
- { "util", "verifymessage", &verifymessage, true, false, false },
- { "util", "estimatefee", &estimatefee, true, true, false },
- { "util", "estimatepriority", &estimatepriority, true, true, false },
+ { "util", "createmultisig", &createmultisig, true, false },
+ { "util", "validateaddress", &validateaddress, true, false }, /* uses wallet if enabled */
+ { "util", "verifymessage", &verifymessage, true, false },
+ { "util", "estimatefee", &estimatefee, true, false },
+ { "util", "estimatepriority", &estimatepriority, true, false },
/* Not shown in help */
- { "hidden", "invalidateblock", &invalidateblock, true, true, false },
- { "hidden", "reconsiderblock", &reconsiderblock, true, true, false },
- { "hidden", "setmocktime", &setmocktime, true, false, false },
+ { "hidden", "invalidateblock", &invalidateblock, true, false },
+ { "hidden", "reconsiderblock", &reconsiderblock, true, false },
+ { "hidden", "setmocktime", &setmocktime, true, false },
#ifdef ENABLE_WALLET
/* Wallet */
- { "wallet", "addmultisigaddress", &addmultisigaddress, true, false, true },
- { "wallet", "backupwallet", &backupwallet, true, false, true },
- { "wallet", "dumpprivkey", &dumpprivkey, true, false, true },
- { "wallet", "dumpwallet", &dumpwallet, true, false, true },
- { "wallet", "encryptwallet", &encryptwallet, true, false, true },
- { "wallet", "getaccountaddress", &getaccountaddress, true, false, true },
- { "wallet", "getaccount", &getaccount, true, false, true },
- { "wallet", "getaddressesbyaccount", &getaddressesbyaccount, true, false, true },
- { "wallet", "getbalance", &getbalance, false, false, true },
- { "wallet", "getnewaddress", &getnewaddress, true, false, true },
- { "wallet", "getrawchangeaddress", &getrawchangeaddress, true, false, true },
- { "wallet", "getreceivedbyaccount", &getreceivedbyaccount, false, false, true },
- { "wallet", "getreceivedbyaddress", &getreceivedbyaddress, false, false, true },
- { "wallet", "gettransaction", &gettransaction, false, false, true },
- { "wallet", "getunconfirmedbalance", &getunconfirmedbalance, false, false, true },
- { "wallet", "getwalletinfo", &getwalletinfo, false, false, true },
- { "wallet", "importprivkey", &importprivkey, true, false, true },
- { "wallet", "importwallet", &importwallet, true, false, true },
- { "wallet", "importaddress", &importaddress, true, false, true },
- { "wallet", "keypoolrefill", &keypoolrefill, true, false, true },
- { "wallet", "listaccounts", &listaccounts, false, false, true },
- { "wallet", "listaddressgroupings", &listaddressgroupings, false, false, true },
- { "wallet", "listlockunspent", &listlockunspent, false, false, true },
- { "wallet", "listreceivedbyaccount", &listreceivedbyaccount, false, false, true },
- { "wallet", "listreceivedbyaddress", &listreceivedbyaddress, false, false, true },
- { "wallet", "listsinceblock", &listsinceblock, false, false, true },
- { "wallet", "listtransactions", &listtransactions, false, false, true },
- { "wallet", "listunspent", &listunspent, false, false, true },
- { "wallet", "lockunspent", &lockunspent, true, false, true },
- { "wallet", "move", &movecmd, false, false, true },
- { "wallet", "sendfrom", &sendfrom, false, false, true },
- { "wallet", "sendmany", &sendmany, false, false, true },
- { "wallet", "sendtoaddress", &sendtoaddress, false, false, true },
- { "wallet", "setaccount", &setaccount, true, false, true },
- { "wallet", "settxfee", &settxfee, true, false, true },
- { "wallet", "signmessage", &signmessage, true, false, true },
- { "wallet", "walletlock", &walletlock, true, false, true },
- { "wallet", "walletpassphrasechange", &walletpassphrasechange, true, false, true },
- { "wallet", "walletpassphrase", &walletpassphrase, true, false, true },
+ { "wallet", "addmultisigaddress", &addmultisigaddress, true, true },
+ { "wallet", "backupwallet", &backupwallet, true, true },
+ { "wallet", "dumpprivkey", &dumpprivkey, true, true },
+ { "wallet", "dumpwallet", &dumpwallet, true, true },
+ { "wallet", "encryptwallet", &encryptwallet, true, true },
+ { "wallet", "getaccountaddress", &getaccountaddress, true, true },
+ { "wallet", "getaccount", &getaccount, true, true },
+ { "wallet", "getaddressesbyaccount", &getaddressesbyaccount, true, true },
+ { "wallet", "getbalance", &getbalance, false, true },
+ { "wallet", "getnewaddress", &getnewaddress, true, true },
+ { "wallet", "getrawchangeaddress", &getrawchangeaddress, true, true },
+ { "wallet", "getreceivedbyaccount", &getreceivedbyaccount, false, true },
+ { "wallet", "getreceivedbyaddress", &getreceivedbyaddress, false, true },
+ { "wallet", "gettransaction", &gettransaction, false, true },
+ { "wallet", "getunconfirmedbalance", &getunconfirmedbalance, false, true },
+ { "wallet", "getwalletinfo", &getwalletinfo, false, true },
+ { "wallet", "importprivkey", &importprivkey, true, true },
+ { "wallet", "importwallet", &importwallet, true, true },
+ { "wallet", "importaddress", &importaddress, true, true },
+ { "wallet", "keypoolrefill", &keypoolrefill, true, true },
+ { "wallet", "listaccounts", &listaccounts, false, true },
+ { "wallet", "listaddressgroupings", &listaddressgroupings, false, true },
+ { "wallet", "listlockunspent", &listlockunspent, false, true },
+ { "wallet", "listreceivedbyaccount", &listreceivedbyaccount, false, true },
+ { "wallet", "listreceivedbyaddress", &listreceivedbyaddress, false, true },
+ { "wallet", "listsinceblock", &listsinceblock, false, true },
+ { "wallet", "listtransactions", &listtransactions, false, true },
+ { "wallet", "listunspent", &listunspent, false, true },
+ { "wallet", "lockunspent", &lockunspent, true, true },
+ { "wallet", "move", &movecmd, false, true },
+ { "wallet", "sendfrom", &sendfrom, false, true },
+ { "wallet", "sendmany", &sendmany, false, true },
+ { "wallet", "sendtoaddress", &sendtoaddress, false, true },
+ { "wallet", "setaccount", &setaccount, true, true },
+ { "wallet", "settxfee", &settxfee, true, true },
+ { "wallet", "signmessage", &signmessage, true, true },
+ { "wallet", "walletlock", &walletlock, true, true },
+ { "wallet", "walletpassphrasechange", &walletpassphrasechange, true, true },
+ { "wallet", "walletpassphrase", &walletpassphrase, true, true },
#endif // ENABLE_WALLET
};
@@ -694,6 +723,7 @@ void StartRPCThreads()
for (int i = 0; i < GetArg("-rpcthreads", 4); i++)
rpc_worker_group->create_thread(boost::bind(&boost::asio::io_service::run, rpc_io_service));
fRPCRunning = true;
+ g_rpcSignals.Started();
}
void StartDummyRPCThread()
@@ -736,7 +766,7 @@ void StopRPCThreads()
deadlineTimers.clear();
rpc_io_service->stop();
- cvBlockChange.notify_all();
+ g_rpcSignals.Stopped();
if (rpc_worker_group != NULL)
rpc_worker_group->join_all();
delete rpc_dummy_work; rpc_dummy_work = NULL;
@@ -819,7 +849,7 @@ void JSONRequest::parse(const Value& valRequest)
throw JSONRPCError(RPC_INVALID_REQUEST, "Method must be a string");
strMethod = valMethod.get_str();
if (strMethod != "getblocktemplate")
- LogPrint("rpc", "ThreadRPCServer method=%s\n", strMethod);
+ LogPrint("rpc", "ThreadRPCServer method=%s\n", SanitizeString(strMethod));
// Parse params
Value valParams = find_value(request, "params");
@@ -953,7 +983,7 @@ void ServiceConnection(AcceptedConnection *conn)
ReadHTTPMessage(conn->stream(), mapHeaders, strRequest, nProto, MAX_SIZE);
// HTTP Keep-Alive is false; close connection immediately
- if (mapHeaders["connection"] == "close")
+ if ((mapHeaders["connection"] == "close") || (!GetBoolArg("-rpckeepalive", true)))
fRun = false;
// Process via JSON-RPC API
@@ -979,45 +1009,20 @@ json_spirit::Value CRPCTable::execute(const std::string &strMethod, const json_s
const CRPCCommand *pcmd = tableRPC[strMethod];
if (!pcmd)
throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Method not found");
-#ifdef ENABLE_WALLET
- if (pcmd->reqWallet && !pwalletMain)
- throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Method not found (disabled)");
-#endif
- // Observe safe mode
- string strWarning = GetWarnings("rpc");
- if (strWarning != "" && !GetBoolArg("-disablesafemode", false) &&
- !pcmd->okSafeMode)
- throw JSONRPCError(RPC_FORBIDDEN_BY_SAFE_MODE, string("Safe mode: ") + strWarning);
+ g_rpcSignals.PreCommand(*pcmd);
try
{
// Execute
- Value result;
- {
- if (pcmd->threadSafe)
- result = pcmd->actor(params, false);
-#ifdef ENABLE_WALLET
- else if (!pwalletMain) {
- LOCK(cs_main);
- result = pcmd->actor(params, false);
- } else {
- LOCK2(cs_main, pwalletMain->cs_wallet);
- result = pcmd->actor(params, false);
- }
-#else // ENABLE_WALLET
- else {
- LOCK(cs_main);
- result = pcmd->actor(params, false);
- }
-#endif // !ENABLE_WALLET
- }
- return result;
+ return pcmd->actor(params, false);
}
catch (const std::exception& e)
{
throw JSONRPCError(RPC_MISC_ERROR, e.what());
}
+
+ g_rpcSignals.PostCommand(*pcmd);
}
std::string HelpExampleCli(string methodname, string args){
diff --git a/src/rpcserver.h b/src/rpcserver.h
index fb561ab939..f63438ecb8 100644
--- a/src/rpcserver.h
+++ b/src/rpcserver.h
@@ -19,6 +19,16 @@
#include "json/json_spirit_utils.h"
#include "json/json_spirit_writer_template.h"
+class CRPCCommand;
+
+namespace RPCServer
+{
+ void OnStarted(boost::function<void ()> slot);
+ void OnStopped(boost::function<void ()> slot);
+ void OnPreCommand(boost::function<void (const CRPCCommand&)> slot);
+ void OnPostCommand(boost::function<void (const CRPCCommand&)> slot);
+}
+
class CBlockIndex;
class CNetAddr;
@@ -88,7 +98,6 @@ public:
std::string name;
rpcfn_type actor;
bool okSafeMode;
- bool threadSafe;
bool reqWallet;
};
@@ -154,7 +163,6 @@ extern json_spirit::Value importwallet(const json_spirit::Array& params, bool fH
extern json_spirit::Value getgenerate(const json_spirit::Array& params, bool fHelp); // in rpcmining.cpp
extern json_spirit::Value setgenerate(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value getnetworkhashps(const json_spirit::Array& params, bool fHelp);
-extern json_spirit::Value gethashespersec(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value getmininginfo(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value prioritisetransaction(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value getblocktemplate(const json_spirit::Array& params, bool fHelp);
diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp
index 7a4d685717..1afc3c910e 100644
--- a/src/rpcwallet.cpp
+++ b/src/rpcwallet.cpp
@@ -79,19 +79,19 @@ Value getnewaddress(const Array& params, bool fHelp)
throw runtime_error(
"getnewaddress ( \"account\" )\n"
"\nReturns a new Bitcoin address for receiving payments.\n"
- "If 'account' is specified (recommended), it is added to the address book \n"
+ "If 'account' is specified (DEPRECATED), it is added to the address book \n"
"so payments received with the address will be credited to 'account'.\n"
"\nArguments:\n"
- "1. \"account\" (string, optional) The account name for the address to be linked to. if not provided, the default account \"\" is used. It can also be set to the empty string \"\" to represent the default account. The account does not need to exist, it will be created if there is no account by the given name.\n"
+ "1. \"account\" (string, optional) DEPRECATED. The account name for the address to be linked to. If not provided, the default account \"\" is used. It can also be set to the empty string \"\" to represent the default account. The account does not need to exist, it will be created if there is no account by the given name.\n"
"\nResult:\n"
"\"bitcoinaddress\" (string) The new bitcoin address\n"
"\nExamples:\n"
+ HelpExampleCli("getnewaddress", "")
- + HelpExampleCli("getnewaddress", "\"\"")
- + HelpExampleCli("getnewaddress", "\"myaccount\"")
- + HelpExampleRpc("getnewaddress", "\"myaccount\"")
+ + HelpExampleRpc("getnewaddress", "")
);
+ LOCK2(cs_main, pwalletMain->cs_wallet);
+
// Parse the account first so we don't generate a key if there's an error
string strAccount;
if (params.size() > 0)
@@ -154,7 +154,7 @@ Value getaccountaddress(const Array& params, bool fHelp)
if (fHelp || params.size() != 1)
throw runtime_error(
"getaccountaddress \"account\"\n"
- "\nReturns the current Bitcoin address for receiving payments to this account.\n"
+ "\nDEPRECATED. Returns the current Bitcoin address for receiving payments to this account.\n"
"\nArguments:\n"
"1. \"account\" (string, required) The account name for the address. It can also be set to the empty string \"\" to represent the default account. The account does not need to exist, it will be created and a new address created if there is no account by the given name.\n"
"\nResult:\n"
@@ -166,13 +166,14 @@ Value getaccountaddress(const Array& params, bool fHelp)
+ HelpExampleRpc("getaccountaddress", "\"myaccount\"")
);
+ LOCK2(cs_main, pwalletMain->cs_wallet);
+
// Parse the account first so we don't generate a key if there's an error
string strAccount = AccountFromValue(params[0]);
Value ret;
ret = GetAccountAddress(strAccount).ToString();
-
return ret;
}
@@ -191,6 +192,8 @@ Value getrawchangeaddress(const Array& params, bool fHelp)
+ HelpExampleRpc("getrawchangeaddress", "")
);
+ LOCK2(cs_main, pwalletMain->cs_wallet);
+
if (!pwalletMain->IsLocked())
pwalletMain->TopUpKeyPool();
@@ -212,7 +215,7 @@ Value setaccount(const Array& params, bool fHelp)
if (fHelp || params.size() < 1 || params.size() > 2)
throw runtime_error(
"setaccount \"bitcoinaddress\" \"account\"\n"
- "\nSets the account associated with the given address.\n"
+ "\nDEPRECATED. Sets the account associated with the given address.\n"
"\nArguments:\n"
"1. \"bitcoinaddress\" (string, required) The bitcoin address to be associated with an account.\n"
"2. \"account\" (string, required) The account to assign the address to.\n"
@@ -221,11 +224,12 @@ Value setaccount(const Array& params, bool fHelp)
+ HelpExampleRpc("setaccount", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\", \"tabby\"")
);
+ LOCK2(cs_main, pwalletMain->cs_wallet);
+
CBitcoinAddress address(params[0].get_str());
if (!address.IsValid())
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
-
string strAccount;
if (params.size() > 1)
strAccount = AccountFromValue(params[1]);
@@ -254,7 +258,7 @@ Value getaccount(const Array& params, bool fHelp)
if (fHelp || params.size() != 1)
throw runtime_error(
"getaccount \"bitcoinaddress\"\n"
- "\nReturns the account associated with the given address.\n"
+ "\nDEPRECATED. Returns the account associated with the given address.\n"
"\nArguments:\n"
"1. \"bitcoinaddress\" (string, required) The bitcoin address for account lookup.\n"
"\nResult:\n"
@@ -264,6 +268,8 @@ Value getaccount(const Array& params, bool fHelp)
+ HelpExampleRpc("getaccount", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\"")
);
+ LOCK2(cs_main, pwalletMain->cs_wallet);
+
CBitcoinAddress address(params[0].get_str());
if (!address.IsValid())
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
@@ -281,7 +287,7 @@ Value getaddressesbyaccount(const Array& params, bool fHelp)
if (fHelp || params.size() != 1)
throw runtime_error(
"getaddressesbyaccount \"account\"\n"
- "\nReturns the list of addresses for the given account.\n"
+ "\nDEPRECATED. Returns the list of addresses for the given account.\n"
"\nArguments:\n"
"1. \"account\" (string, required) The account name.\n"
"\nResult:\n"
@@ -294,6 +300,8 @@ Value getaddressesbyaccount(const Array& params, bool fHelp)
+ HelpExampleRpc("getaddressesbyaccount", "\"tabby\"")
);
+ LOCK2(cs_main, pwalletMain->cs_wallet);
+
string strAccount = AccountFromValue(params[0]);
// Find all addresses that have the given account
@@ -321,7 +329,7 @@ void SendMoney(const CTxDestination &address, CAmount nValue, CWalletTx& wtxNew)
if (pwalletMain->IsLocked())
{
strError = "Error: Wallet locked, unable to create transaction!";
- LogPrintf("SendMoney() : %s", strError);
+ LogPrintf("SendMoney(): %s", strError);
throw JSONRPCError(RPC_WALLET_ERROR, strError);
}
@@ -335,7 +343,7 @@ void SendMoney(const CTxDestination &address, CAmount nValue, CWalletTx& wtxNew)
{
if (nValue + nFeeRequired > pwalletMain->GetBalance())
strError = strprintf("Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds!", FormatMoney(nFeeRequired));
- LogPrintf("SendMoney() : %s\n", strError);
+ LogPrintf("SendMoney(): %s\n", strError);
throw JSONRPCError(RPC_WALLET_ERROR, strError);
}
if (!pwalletMain->CommitTransaction(wtxNew, reservekey))
@@ -365,6 +373,8 @@ Value sendtoaddress(const Array& params, bool fHelp)
+ HelpExampleRpc("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\", 0.1, \"donation\", \"seans outpost\"")
);
+ LOCK2(cs_main, pwalletMain->cs_wallet);
+
CBitcoinAddress address(params[0].get_str());
if (!address.IsValid())
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
@@ -400,7 +410,7 @@ Value listaddressgroupings(const Array& params, bool fHelp)
" [\n"
" \"bitcoinaddress\", (string) The bitcoin address\n"
" amount, (numeric) The amount in btc\n"
- " \"account\" (string, optional) The account\n"
+ " \"account\" (string, optional) The account (DEPRECATED)\n"
" ]\n"
" ,...\n"
" ]\n"
@@ -411,6 +421,8 @@ Value listaddressgroupings(const Array& params, bool fHelp)
+ HelpExampleRpc("listaddressgroupings", "")
);
+ LOCK2(cs_main, pwalletMain->cs_wallet);
+
Array jsonGroupings;
map<CTxDestination, CAmount> balances = pwalletMain->GetAddressBalances();
BOOST_FOREACH(set<CTxDestination> grouping, pwalletMain->GetAddressGroupings())
@@ -456,6 +468,8 @@ Value signmessage(const Array& params, bool fHelp)
+ HelpExampleRpc("signmessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\", \"my message\"")
);
+ LOCK2(cs_main, pwalletMain->cs_wallet);
+
EnsureWalletIsUnlocked();
string strAddress = params[0].get_str();
@@ -506,6 +520,8 @@ Value getreceivedbyaddress(const Array& params, bool fHelp)
+ HelpExampleRpc("getreceivedbyaddress", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\", 6")
);
+ LOCK2(cs_main, pwalletMain->cs_wallet);
+
// Bitcoin address
CBitcoinAddress address = CBitcoinAddress(params[0].get_str());
if (!address.IsValid())
@@ -542,7 +558,7 @@ Value getreceivedbyaccount(const Array& params, bool fHelp)
if (fHelp || params.size() < 1 || params.size() > 2)
throw runtime_error(
"getreceivedbyaccount \"account\" ( minconf )\n"
- "\nReturns the total amount received by addresses with <account> in transactions with at least [minconf] confirmations.\n"
+ "\nDEPRECATED. Returns the total amount received by addresses with <account> in transactions with at least [minconf] confirmations.\n"
"\nArguments:\n"
"1. \"account\" (string, required) The selected account, may be the default account using \"\".\n"
"2. minconf (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n"
@@ -559,6 +575,8 @@ Value getreceivedbyaccount(const Array& params, bool fHelp)
+ HelpExampleRpc("getreceivedbyaccount", "\"tabby\", 6")
);
+ LOCK2(cs_main, pwalletMain->cs_wallet);
+
// Minimum confirmations
int nMinDepth = 1;
if (params.size() > 1)
@@ -627,28 +645,26 @@ Value getbalance(const Array& params, bool fHelp)
throw runtime_error(
"getbalance ( \"account\" minconf includeWatchonly )\n"
"\nIf account is not specified, returns the server's total available balance.\n"
- "If account is specified, returns the balance in the account.\n"
+ "If account is specified (DEPRECATED), returns the balance in the account.\n"
"Note that the account \"\" is not the same as leaving the parameter out.\n"
"The server total may be different to the balance in the default \"\" account.\n"
"\nArguments:\n"
- "1. \"account\" (string, optional) The selected account, or \"*\" for entire wallet. It may be the default account using \"\".\n"
+ "1. \"account\" (string, optional) DEPRECATED. The selected account, or \"*\" for entire wallet. It may be the default account using \"\".\n"
"2. minconf (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n"
"3. includeWatchonly (bool, optional, default=false) Also include balance in watchonly addresses (see 'importaddress')\n"
"\nResult:\n"
"amount (numeric) The total amount in btc received for this account.\n"
"\nExamples:\n"
- "\nThe total amount in the server across all accounts\n"
+ "\nThe total amount in the wallet\n"
+ HelpExampleCli("getbalance", "") +
- "\nThe total amount in the server across all accounts, with at least 5 confirmations\n"
+ "\nThe total amount in the wallet at least 5 blocks confirmed\n"
+ HelpExampleCli("getbalance", "\"*\" 6") +
- "\nThe total amount in the default account with at least 1 confirmation\n"
- + HelpExampleCli("getbalance", "\"\"") +
- "\nThe total amount in the account named tabby with at least 6 confirmations\n"
- + HelpExampleCli("getbalance", "\"tabby\" 6") +
"\nAs a json rpc call\n"
- + HelpExampleRpc("getbalance", "\"tabby\", 6")
+ + HelpExampleRpc("getbalance", "\"*\", 6")
);
+ LOCK2(cs_main, pwalletMain->cs_wallet);
+
if (params.size() == 0)
return ValueFromAmount(pwalletMain->GetBalance());
@@ -701,6 +717,9 @@ Value getunconfirmedbalance(const Array &params, bool fHelp)
throw runtime_error(
"getunconfirmedbalance\n"
"Returns the server's total unconfirmed balance\n");
+
+ LOCK2(cs_main, pwalletMain->cs_wallet);
+
return ValueFromAmount(pwalletMain->GetUnconfirmedBalance());
}
@@ -710,7 +729,7 @@ Value movecmd(const Array& params, bool fHelp)
if (fHelp || params.size() < 3 || params.size() > 5)
throw runtime_error(
"move \"fromaccount\" \"toaccount\" amount ( minconf \"comment\" )\n"
- "\nMove a specified amount from one account in your wallet to another.\n"
+ "\nDEPRECATED. Move a specified amount from one account in your wallet to another.\n"
"\nArguments:\n"
"1. \"fromaccount\" (string, required) The name of the account to move funds from. May be the default account using \"\".\n"
"2. \"toaccount\" (string, required) The name of the account to move funds to. May be the default account using \"\".\n"
@@ -727,6 +746,8 @@ Value movecmd(const Array& params, bool fHelp)
+ HelpExampleRpc("move", "\"timotei\", \"akiko\", 0.01, 6, \"happy birthday!\"")
);
+ LOCK2(cs_main, pwalletMain->cs_wallet);
+
string strFrom = AccountFromValue(params[0]);
string strTo = AccountFromValue(params[1]);
CAmount nAmount = AmountFromValue(params[2]);
@@ -775,7 +796,7 @@ Value sendfrom(const Array& params, bool fHelp)
if (fHelp || params.size() < 3 || params.size() > 6)
throw runtime_error(
"sendfrom \"fromaccount\" \"tobitcoinaddress\" amount ( minconf \"comment\" \"comment-to\" )\n"
- "\nSent an amount from an account to a bitcoin address.\n"
+ "\nDEPRECATED (use sendtoaddress). Sent an amount from an account to a bitcoin address.\n"
"The amount is a real and is rounded to the nearest 0.00000001."
+ HelpRequiringPassphrase() + "\n"
"\nArguments:\n"
@@ -799,6 +820,8 @@ Value sendfrom(const Array& params, bool fHelp)
+ HelpExampleRpc("sendfrom", "\"tabby\", \"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\", 0.01, 6, \"donation\", \"seans outpost\"")
);
+ LOCK2(cs_main, pwalletMain->cs_wallet);
+
string strAccount = AccountFromValue(params[0]);
CBitcoinAddress address(params[1].get_str());
if (!address.IsValid())
@@ -836,7 +859,7 @@ Value sendmany(const Array& params, bool fHelp)
"\nSend multiple times. Amounts are double-precision floating point numbers."
+ HelpRequiringPassphrase() + "\n"
"\nArguments:\n"
- "1. \"fromaccount\" (string, required) The account to send the funds from, can be \"\" for the default account\n"
+ "1. \"fromaccount\" (string, required) DEPRECATED. The account to send the funds from. Should be \"\" for the default account\n"
"2. \"amounts\" (string, required) A json object with addresses and amounts\n"
" {\n"
" \"address\":amount (numeric) The bitcoin address is the key, the numeric amount in btc is the value\n"
@@ -849,13 +872,15 @@ Value sendmany(const Array& params, bool fHelp)
" the number of addresses.\n"
"\nExamples:\n"
"\nSend two amounts to two different addresses:\n"
- + HelpExampleCli("sendmany", "\"tabby\" \"{\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\\\":0.01,\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\"") +
+ + HelpExampleCli("sendmany", "\"\" \"{\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\\\":0.01,\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\"") +
"\nSend two amounts to two different addresses setting the confirmation and comment:\n"
- + HelpExampleCli("sendmany", "\"tabby\" \"{\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\\\":0.01,\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\" 6 \"testing\"") +
+ + HelpExampleCli("sendmany", "\"\" \"{\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\\\":0.01,\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\" 6 \"testing\"") +
"\nAs a json rpc call\n"
- + HelpExampleRpc("sendmany", "\"tabby\", \"{\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\\\":0.01,\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\", 6, \"testing\"")
+ + HelpExampleRpc("sendmany", "\"\", \"{\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\\\":0.01,\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\", 6, \"testing\"")
);
+ LOCK2(cs_main, pwalletMain->cs_wallet);
+
string strAccount = AccountFromValue(params[0]);
Object sendTo = params[1].get_obj();
int nMinDepth = 1;
@@ -918,7 +943,7 @@ Value addmultisigaddress(const Array& params, bool fHelp)
string msg = "addmultisigaddress nrequired [\"key\",...] ( \"account\" )\n"
"\nAdd a nrequired-to-sign multisignature address to the wallet.\n"
"Each key is a Bitcoin address or hex-encoded public key.\n"
- "If 'account' is specified, assign address to that account.\n"
+ "If 'account' is specified (DEPRECATED), assign address to that account.\n"
"\nArguments:\n"
"1. nrequired (numeric, required) The number of required signatures out of the n keys or addresses.\n"
@@ -927,7 +952,7 @@ Value addmultisigaddress(const Array& params, bool fHelp)
" \"address\" (string) bitcoin address or hex-encoded public key\n"
" ...,\n"
" ]\n"
- "3. \"account\" (string, optional) An account to assign the addresses to.\n"
+ "3. \"account\" (string, optional) DEPRECATED. An account to assign the addresses to.\n"
"\nResult:\n"
"\"bitcoinaddress\" (string) A bitcoin address associated with the keys.\n"
@@ -941,6 +966,8 @@ Value addmultisigaddress(const Array& params, bool fHelp)
throw runtime_error(msg);
}
+ LOCK2(cs_main, pwalletMain->cs_wallet);
+
string strAccount;
if (params.size() > 2)
strAccount = AccountFromValue(params[2]);
@@ -1103,7 +1130,7 @@ Value listreceivedbyaddress(const Array& params, bool fHelp)
" {\n"
" \"involvesWatchonly\" : true, (bool) Only returned if imported addresses were involved in transaction\n"
" \"address\" : \"receivingaddress\", (string) The receiving address\n"
- " \"account\" : \"accountname\", (string) The account of the receiving address. The default account is \"\".\n"
+ " \"account\" : \"accountname\", (string) DEPRECATED. The account of the receiving address. The default account is \"\".\n"
" \"amount\" : x.xxx, (numeric) The total amount in btc received by the address\n"
" \"confirmations\" : n (numeric) The number of confirmations of the most recent transaction included\n"
" }\n"
@@ -1116,6 +1143,8 @@ Value listreceivedbyaddress(const Array& params, bool fHelp)
+ HelpExampleRpc("listreceivedbyaddress", "6, true, true")
);
+ LOCK2(cs_main, pwalletMain->cs_wallet);
+
return ListReceived(params, false);
}
@@ -1124,7 +1153,7 @@ Value listreceivedbyaccount(const Array& params, bool fHelp)
if (fHelp || params.size() > 3)
throw runtime_error(
"listreceivedbyaccount ( minconf includeempty includeWatchonly)\n"
- "\nList balances by account.\n"
+ "\nDEPRECATED. List balances by account.\n"
"\nArguments:\n"
"1. minconf (numeric, optional, default=1) The minimum number of confirmations before payments are included.\n"
"2. includeempty (boolean, optional, default=false) Whether to include accounts that haven't received any payments.\n"
@@ -1147,6 +1176,8 @@ Value listreceivedbyaccount(const Array& params, bool fHelp)
+ HelpExampleRpc("listreceivedbyaccount", "6, true, true")
);
+ LOCK2(cs_main, pwalletMain->cs_wallet);
+
return ListReceived(params, true);
}
@@ -1251,15 +1282,14 @@ Value listtransactions(const Array& params, bool fHelp)
"listtransactions ( \"account\" count from includeWatchonly)\n"
"\nReturns up to 'count' most recent transactions skipping the first 'from' transactions for account 'account'.\n"
"\nArguments:\n"
- "1. \"account\" (string, optional) The account name. If not included, it will list all transactions for all accounts.\n"
- " If \"\" is set, it will list transactions for the default account.\n"
+ "1. \"account\" (string, optional) DEPRECATED. The account name. Should be \"*\".\n"
"2. count (numeric, optional, default=10) The number of transactions to return\n"
"3. from (numeric, optional, default=0) The number of transactions to skip\n"
"4. includeWatchonly (bool, optional, default=false) Include transactions to watchonly addresses (see 'importaddress')\n"
"\nResult:\n"
"[\n"
" {\n"
- " \"account\":\"accountname\", (string) The account name associated with the transaction. \n"
+ " \"account\":\"accountname\", (string) DEPRECATED. The account name associated with the transaction. \n"
" It will be \"\" for the default account.\n"
" \"address\":\"bitcoinaddress\", (string) The bitcoin address of the transaction. Not present for \n"
" move transactions (category = move).\n"
@@ -1293,14 +1323,14 @@ Value listtransactions(const Array& params, bool fHelp)
"\nExamples:\n"
"\nList the most recent 10 transactions in the systems\n"
+ HelpExampleCli("listtransactions", "") +
- "\nList the most recent 10 transactions for the tabby account\n"
- + HelpExampleCli("listtransactions", "\"tabby\"") +
- "\nList transactions 100 to 120 from the tabby account\n"
- + HelpExampleCli("listtransactions", "\"tabby\" 20 100") +
+ "\nList transactions 100 to 120\n"
+ + HelpExampleCli("listtransactions", "\"*\" 20 100") +
"\nAs a json rpc call\n"
- + HelpExampleRpc("listtransactions", "\"tabby\", 20, 100")
+ + HelpExampleRpc("listtransactions", "\"*\", 20, 100")
);
+ LOCK2(cs_main, pwalletMain->cs_wallet);
+
string strAccount = "*";
if (params.size() > 0)
strAccount = params[0].get_str();
@@ -1361,7 +1391,7 @@ Value listaccounts(const Array& params, bool fHelp)
if (fHelp || params.size() > 2)
throw runtime_error(
"listaccounts ( minconf includeWatchonly)\n"
- "\nReturns Object that has account names as keys, account balances as values.\n"
+ "\nDEPRECATED. Returns Object that has account names as keys, account balances as values.\n"
"\nArguments:\n"
"1. minconf (numeric, optional, default=1) Only include transactions with at least this many confirmations\n"
"2. includeWatchonly (bool, optional, default=false) Include balances in watchonly addresses (see 'importaddress')\n"
@@ -1381,6 +1411,8 @@ Value listaccounts(const Array& params, bool fHelp)
+ HelpExampleRpc("listaccounts", "6")
);
+ LOCK2(cs_main, pwalletMain->cs_wallet);
+
int nMinDepth = 1;
if (params.size() > 0)
nMinDepth = params[0].get_int();
@@ -1444,7 +1476,7 @@ Value listsinceblock(const Array& params, bool fHelp)
"\nResult:\n"
"{\n"
" \"transactions\": [\n"
- " \"account\":\"accountname\", (string) The account name associated with the transaction. Will be \"\" for the default account.\n"
+ " \"account\":\"accountname\", (string) DEPRECATED. The account name associated with the transaction. Will be \"\" for the default account.\n"
" \"address\":\"bitcoinaddress\", (string) The bitcoin address of the transaction. Not present for move transactions (category = move).\n"
" \"category\":\"send|receive\", (string) The transaction category. 'send' has negative amounts, 'receive' has positive amounts.\n"
" \"amount\": x.xxx, (numeric) The amount in btc. This is negative for the 'send' category, and for the 'move' category for moves \n"
@@ -1469,6 +1501,8 @@ Value listsinceblock(const Array& params, bool fHelp)
+ HelpExampleRpc("listsinceblock", "\"000000000000000bacf66f7497b7dc45ef753ee9a7d38571037cdb1a57f663ad\", 6")
);
+ LOCK2(cs_main, pwalletMain->cs_wallet);
+
CBlockIndex *pindex = NULL;
int target_confirms = 1;
isminefilter filter = ISMINE_SPENDABLE;
@@ -1538,7 +1572,7 @@ Value gettransaction(const Array& params, bool fHelp)
" \"timereceived\" : ttt, (numeric) The time received in seconds since epoch (1 Jan 1970 GMT)\n"
" \"details\" : [\n"
" {\n"
- " \"account\" : \"accountname\", (string) The account name involved in the transaction, can be \"\" for the default account.\n"
+ " \"account\" : \"accountname\", (string) DEPRECATED. The account name involved in the transaction, can be \"\" for the default account.\n"
" \"address\" : \"bitcoinaddress\", (string) The bitcoin address involved in the transaction\n"
" \"category\" : \"send|receive\", (string) The category, either 'send' or 'receive'\n"
" \"amount\" : x.xxx (numeric) The amount in btc\n"
@@ -1555,6 +1589,8 @@ Value gettransaction(const Array& params, bool fHelp)
+ HelpExampleRpc("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
);
+ LOCK2(cs_main, pwalletMain->cs_wallet);
+
uint256 hash;
hash.SetHex(params[0].get_str());
@@ -1603,6 +1639,8 @@ Value backupwallet(const Array& params, bool fHelp)
+ HelpExampleRpc("backupwallet", "\"backup.dat\"")
);
+ LOCK2(cs_main, pwalletMain->cs_wallet);
+
string strDest = params[0].get_str();
if (!BackupWallet(*pwalletMain, strDest))
throw JSONRPCError(RPC_WALLET_ERROR, "Error: Wallet backup failed!");
@@ -1625,6 +1663,8 @@ Value keypoolrefill(const Array& params, bool fHelp)
+ HelpExampleRpc("keypoolrefill", "")
);
+ LOCK2(cs_main, pwalletMain->cs_wallet);
+
// 0 is interpreted by TopUpKeyPool() as the default keypool size given by -keypool
unsigned int kpSize = 0;
if (params.size() > 0) {
@@ -1672,6 +1712,8 @@ Value walletpassphrase(const Array& params, bool fHelp)
+ HelpExampleRpc("walletpassphrase", "\"my pass phrase\", 60")
);
+ LOCK2(cs_main, pwalletMain->cs_wallet);
+
if (fHelp)
return true;
if (!pwalletMain->IsCrypted())
@@ -1719,6 +1761,8 @@ Value walletpassphrasechange(const Array& params, bool fHelp)
+ HelpExampleRpc("walletpassphrasechange", "\"old one\", \"new one\"")
);
+ LOCK2(cs_main, pwalletMain->cs_wallet);
+
if (fHelp)
return true;
if (!pwalletMain->IsCrypted())
@@ -1765,6 +1809,8 @@ Value walletlock(const Array& params, bool fHelp)
+ HelpExampleRpc("walletlock", "")
);
+ LOCK2(cs_main, pwalletMain->cs_wallet);
+
if (fHelp)
return true;
if (!pwalletMain->IsCrypted())
@@ -1806,6 +1852,8 @@ Value encryptwallet(const Array& params, bool fHelp)
+ HelpExampleRpc("encryptwallet", "\"my pass phrase\"")
);
+ LOCK2(cs_main, pwalletMain->cs_wallet);
+
if (fHelp)
return true;
if (pwalletMain->IsCrypted())
@@ -1870,6 +1918,8 @@ Value lockunspent(const Array& params, bool fHelp)
+ HelpExampleRpc("lockunspent", "false, \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"")
);
+ LOCK2(cs_main, pwalletMain->cs_wallet);
+
if (params.size() == 1)
RPCTypeCheck(params, boost::assign::list_of(bool_type));
else
@@ -1939,6 +1989,8 @@ Value listlockunspent(const Array& params, bool fHelp)
+ HelpExampleRpc("listlockunspent", "")
);
+ LOCK2(cs_main, pwalletMain->cs_wallet);
+
vector<COutPoint> vOutpts;
pwalletMain->ListLockedCoins(vOutpts);
@@ -1970,6 +2022,8 @@ Value settxfee(const Array& params, bool fHelp)
+ HelpExampleRpc("settxfee", "0.00001")
);
+ LOCK2(cs_main, pwalletMain->cs_wallet);
+
// Amount
CAmount nAmount = 0;
if (params[0].get_real() != 0.0)
@@ -2001,6 +2055,8 @@ Value getwalletinfo(const Array& params, bool fHelp)
+ HelpExampleRpc("getwalletinfo", "")
);
+ LOCK2(cs_main, pwalletMain->cs_wallet);
+
Object obj;
obj.push_back(Pair("walletversion", pwalletMain->GetVersion()));
obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance())));
diff --git a/src/script/bitcoinconsensus.cpp b/src/script/bitcoinconsensus.cpp
index c8dd54a747..b0d5faaf77 100644
--- a/src/script/bitcoinconsensus.cpp
+++ b/src/script/bitcoinconsensus.cpp
@@ -78,7 +78,7 @@ int bitcoinconsensus_verify_script(const unsigned char *scriptPubKey, unsigned i
// Regardless of the verification result, the tx did not error.
set_error(err, bitcoinconsensus_ERR_OK);
- return VerifyScript(tx.vin[nIn].scriptSig, CScript(scriptPubKey, scriptPubKey + scriptPubKeyLen), flags, SignatureChecker(tx, nIn), NULL);
+ return VerifyScript(tx.vin[nIn].scriptSig, CScript(scriptPubKey, scriptPubKey + scriptPubKeyLen), flags, TransactionSignatureChecker(&tx, nIn), NULL);
} catch (const std::exception&) {
return set_error(err, bitcoinconsensus_ERR_TX_DESERIALIZE); // Error deserializing
}
diff --git a/src/script/bitcoinconsensus.h b/src/script/bitcoinconsensus.h
index 9d9c266435..0320577797 100644
--- a/src/script/bitcoinconsensus.h
+++ b/src/script/bitcoinconsensus.h
@@ -46,6 +46,7 @@ enum
{
bitcoinconsensus_SCRIPT_FLAGS_VERIFY_NONE = 0,
bitcoinconsensus_SCRIPT_FLAGS_VERIFY_P2SH = (1U << 0), // evaluate P2SH (BIP16) subscripts
+ bitcoinconsensus_SCRIPT_FLAGS_VERIFY_DERSIG = (1U << 2), // enforce strict DER (BIP66) compliance
};
/// Returns 1 if the input nIn of the serialized transaction pointed to by
diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp
index d0f75ab672..84a7432fdb 100644
--- a/src/script/interpreter.cpp
+++ b/src/script/interpreter.cpp
@@ -60,7 +60,7 @@ bool CastToBool(const valtype& vch)
static inline void popstack(vector<valtype>& stack)
{
if (stack.empty())
- throw runtime_error("popstack() : stack empty");
+ throw runtime_error("popstack(): stack empty");
stack.pop_back();
}
@@ -93,76 +93,76 @@ bool static IsCompressedOrUncompressedPubKey(const valtype &vchPubKey) {
* in which case a single 0 byte is necessary and even required).
*
* See https://bitcointalk.org/index.php?topic=8392.msg127623#msg127623
+ *
+ * This function is consensus-critical since BIP66.
*/
-bool static IsDERSignature(const valtype &vchSig) {
+bool static IsValidSignatureEncoding(const std::vector<unsigned char> &sig) {
+ // Format: 0x30 [total-length] 0x02 [R-length] [R] 0x02 [S-length] [S] [sighash]
+ // * total-length: 1-byte length descriptor of everything that follows,
+ // excluding the sighash byte.
+ // * R-length: 1-byte length descriptor of the R value that follows.
+ // * R: arbitrary-length big-endian encoded R value. It must use the shortest
+ // possible encoding for a positive integers (which means no null bytes at
+ // the start, except a single one when the next byte has its highest bit set).
+ // * S-length: 1-byte length descriptor of the S value that follows.
+ // * S: arbitrary-length big-endian encoded S value. The same rules apply.
+ // * sighash: 1-byte value indicating what data is hashed (not part of the DER
+ // signature)
- if (vchSig.size() < 9) {
- // Non-canonical signature: too short
- return false;
- }
- if (vchSig.size() > 73) {
- // Non-canonical signature: too long
- return false;
- }
- if (vchSig[0] != 0x30) {
- // Non-canonical signature: wrong type
- return false;
- }
- if (vchSig[1] != vchSig.size()-3) {
- // Non-canonical signature: wrong length marker
- return false;
- }
- unsigned int nLenR = vchSig[3];
- if (5 + nLenR >= vchSig.size()) {
- // Non-canonical signature: S length misplaced
- return false;
- }
- unsigned int nLenS = vchSig[5+nLenR];
- if ((unsigned long)(nLenR+nLenS+7) != vchSig.size()) {
- // Non-canonical signature: R+S length mismatch
- return false;
- }
+ // Minimum and maximum size constraints.
+ if (sig.size() < 9) return false;
+ if (sig.size() > 73) return false;
- const unsigned char *R = &vchSig[4];
- if (R[-2] != 0x02) {
- // Non-canonical signature: R value type mismatch
- return false;
- }
- if (nLenR == 0) {
- // Non-canonical signature: R length is zero
- return false;
- }
- if (R[0] & 0x80) {
- // Non-canonical signature: R value negative
- return false;
- }
- if (nLenR > 1 && (R[0] == 0x00) && !(R[1] & 0x80)) {
- // Non-canonical signature: R value excessively padded
- return false;
- }
+ // A signature is of type 0x30 (compound).
+ if (sig[0] != 0x30) return false;
+
+ // Make sure the length covers the entire signature.
+ if (sig[1] != sig.size() - 3) return false;
+
+ // Extract the length of the R element.
+ unsigned int lenR = sig[3];
+
+ // Make sure the length of the S element is still inside the signature.
+ if (5 + lenR >= sig.size()) return false;
+
+ // Extract the length of the S element.
+ unsigned int lenS = sig[5 + lenR];
+
+ // Verify that the length of the signature matches the sum of the length
+ // of the elements.
+ if ((size_t)(lenR + lenS + 7) != sig.size()) return false;
+
+ // Check whether the R element is an integer.
+ if (sig[2] != 0x02) return false;
+
+ // Zero-length integers are not allowed for R.
+ if (lenR == 0) return false;
+
+ // Negative numbers are not allowed for R.
+ if (sig[4] & 0x80) return false;
+
+ // Null bytes at the start of R are not allowed, unless R would
+ // otherwise be interpreted as a negative number.
+ if (lenR > 1 && (sig[4] == 0x00) && !(sig[5] & 0x80)) return false;
+
+ // Check whether the S element is an integer.
+ if (sig[lenR + 4] != 0x02) return false;
+
+ // Zero-length integers are not allowed for S.
+ if (lenS == 0) return false;
+
+ // Negative numbers are not allowed for S.
+ if (sig[lenR + 6] & 0x80) return false;
+
+ // Null bytes at the start of S are not allowed, unless S would otherwise be
+ // interpreted as a negative number.
+ if (lenS > 1 && (sig[lenR + 6] == 0x00) && !(sig[lenR + 7] & 0x80)) return false;
- const unsigned char *S = &vchSig[6+nLenR];
- if (S[-2] != 0x02) {
- // Non-canonical signature: S value type mismatch
- return false;
- }
- if (nLenS == 0) {
- // Non-canonical signature: S length is zero
- return false;
- }
- if (S[0] & 0x80) {
- // Non-canonical signature: S value negative
- return false;
- }
- if (nLenS > 1 && (S[0] == 0x00) && !(S[1] & 0x80)) {
- // Non-canonical signature: S value excessively padded
- return false;
- }
return true;
}
bool static IsLowDERSignature(const valtype &vchSig, ScriptError* serror) {
- if (!IsDERSignature(vchSig)) {
+ if (!IsValidSignatureEncoding(vchSig)) {
return set_error(serror, SCRIPT_ERR_SIG_DER);
}
unsigned int nLenR = vchSig[3];
@@ -189,7 +189,12 @@ bool static IsDefinedHashtypeSignature(const valtype &vchSig) {
}
bool static CheckSignatureEncoding(const valtype &vchSig, unsigned int flags, ScriptError* serror) {
- if ((flags & (SCRIPT_VERIFY_DERSIG | SCRIPT_VERIFY_LOW_S | SCRIPT_VERIFY_STRICTENC)) != 0 && !IsDERSignature(vchSig)) {
+ // Empty signature. Not strictly DER encoded, but allowed to provide a
+ // compact way to provide an invalid signature for use with CHECK(MULTI)SIG
+ if (vchSig.size() == 0) {
+ return true;
+ }
+ if ((flags & (SCRIPT_VERIFY_DERSIG | SCRIPT_VERIFY_LOW_S | SCRIPT_VERIFY_STRICTENC)) != 0 && !IsValidSignatureEncoding(vchSig)) {
return set_error(serror, SCRIPT_ERR_SIG_DER);
} else if ((flags & SCRIPT_VERIFY_LOW_S) != 0 && !IsLowDERSignature(vchSig, serror)) {
// serror is set
@@ -1053,12 +1058,12 @@ uint256 SignatureHash(const CScript& scriptCode, const CTransaction& txTo, unsig
return ss.GetHash();
}
-bool SignatureChecker::VerifySignature(const std::vector<unsigned char>& vchSig, const CPubKey& pubkey, const uint256& sighash) const
+bool TransactionSignatureChecker::VerifySignature(const std::vector<unsigned char>& vchSig, const CPubKey& pubkey, const uint256& sighash) const
{
return pubkey.Verify(sighash, vchSig);
}
-bool SignatureChecker::CheckSig(const vector<unsigned char>& vchSigIn, const vector<unsigned char>& vchPubKey, const CScript& scriptCode) const
+bool TransactionSignatureChecker::CheckSig(const vector<unsigned char>& vchSigIn, const vector<unsigned char>& vchPubKey, const CScript& scriptCode) const
{
CPubKey pubkey(vchPubKey);
if (!pubkey.IsValid())
@@ -1071,7 +1076,7 @@ bool SignatureChecker::CheckSig(const vector<unsigned char>& vchSigIn, const vec
int nHashType = vchSig.back();
vchSig.pop_back();
- uint256 sighash = SignatureHash(scriptCode, txTo, nIn, nHashType);
+ uint256 sighash = SignatureHash(scriptCode, *txTo, nIn, nHashType);
if (!VerifySignature(vchSig, pubkey, sighash))
return false;
diff --git a/src/script/interpreter.h b/src/script/interpreter.h
index 8bf379ed89..fc64438f68 100644
--- a/src/script/interpreter.h
+++ b/src/script/interpreter.h
@@ -7,6 +7,7 @@
#define BITCOIN_SCRIPT_INTERPRETER_H
#include "script_error.h"
+#include "primitives/transaction.h"
#include <vector>
#include <stdint.h>
@@ -90,20 +91,29 @@ public:
virtual ~BaseSignatureChecker() {}
};
-class SignatureChecker : public BaseSignatureChecker
+class TransactionSignatureChecker : public BaseSignatureChecker
{
private:
- const CTransaction& txTo;
+ const CTransaction* txTo;
unsigned int nIn;
protected:
virtual bool VerifySignature(const std::vector<unsigned char>& vchSig, const CPubKey& vchPubKey, const uint256& sighash) const;
public:
- SignatureChecker(const CTransaction& txToIn, unsigned int nInIn) : txTo(txToIn), nIn(nInIn) {}
+ TransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn) : txTo(txToIn), nIn(nInIn) {}
bool CheckSig(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode) const;
};
+class MutableTransactionSignatureChecker : public TransactionSignatureChecker
+{
+private:
+ const CTransaction txTo;
+
+public:
+ MutableTransactionSignatureChecker(const CMutableTransaction* txToIn, unsigned int nInIn) : TransactionSignatureChecker(&txTo, nInIn), txTo(*txToIn) {}
+};
+
bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* error = NULL);
bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* error = NULL);
diff --git a/src/script/script.h b/src/script/script.h
index 78fd12cd29..8b36aa2f50 100644
--- a/src/script/script.h
+++ b/src/script/script.h
@@ -391,7 +391,7 @@ public:
CScript& operator<<(opcodetype opcode)
{
if (opcode < 0 || opcode > 0xff)
- throw std::runtime_error("CScript::operator<<() : invalid opcode");
+ throw std::runtime_error("CScript::operator<<(): invalid opcode");
insert(end(), (unsigned char)opcode);
return *this;
}
diff --git a/src/script/sigcache.cpp b/src/script/sigcache.cpp
index 75ecdb563d..099b4ad0e3 100644
--- a/src/script/sigcache.cpp
+++ b/src/script/sigcache.cpp
@@ -74,14 +74,14 @@ public:
}
-bool CachingSignatureChecker::VerifySignature(const std::vector<unsigned char>& vchSig, const CPubKey& pubkey, const uint256& sighash) const
+bool CachingTransactionSignatureChecker::VerifySignature(const std::vector<unsigned char>& vchSig, const CPubKey& pubkey, const uint256& sighash) const
{
static CSignatureCache signatureCache;
if (signatureCache.Get(sighash, vchSig, pubkey))
return true;
- if (!SignatureChecker::VerifySignature(vchSig, pubkey, sighash))
+ if (!TransactionSignatureChecker::VerifySignature(vchSig, pubkey, sighash))
return false;
if (store)
diff --git a/src/script/sigcache.h b/src/script/sigcache.h
index 3bd11caff5..b299038daa 100644
--- a/src/script/sigcache.h
+++ b/src/script/sigcache.h
@@ -12,13 +12,13 @@
class CPubKey;
-class CachingSignatureChecker : public SignatureChecker
+class CachingTransactionSignatureChecker : public TransactionSignatureChecker
{
private:
bool store;
public:
- CachingSignatureChecker(const CTransaction& txToIn, unsigned int nInIn, bool storeIn=true) : SignatureChecker(txToIn, nInIn), store(storeIn) {}
+ CachingTransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, bool storeIn=true) : TransactionSignatureChecker(txToIn, nInIn), store(storeIn) {}
bool VerifySignature(const std::vector<unsigned char>& vchSig, const CPubKey& vchPubKey, const uint256& sighash) const;
};
diff --git a/src/script/sign.cpp b/src/script/sign.cpp
index adddd4ec78..14119f7e2c 100644
--- a/src/script/sign.cpp
+++ b/src/script/sign.cpp
@@ -123,7 +123,7 @@ bool SignSignature(const CKeyStore &keystore, const CScript& fromPubKey, CMutabl
}
// Test solution
- return VerifyScript(txin.scriptSig, fromPubKey, STANDARD_SCRIPT_VERIFY_FLAGS, SignatureChecker(txTo, nIn));
+ return VerifyScript(txin.scriptSig, fromPubKey, STANDARD_SCRIPT_VERIFY_FLAGS, MutableTransactionSignatureChecker(&txTo, nIn));
}
bool SignSignature(const CKeyStore &keystore, const CTransaction& txFrom, CMutableTransaction& txTo, unsigned int nIn, int nHashType)
@@ -174,7 +174,7 @@ static CScript CombineMultisig(const CScript& scriptPubKey, const CTransaction&
if (sigs.count(pubkey))
continue; // Already got a sig for this pubkey
- if (SignatureChecker(txTo, nIn).CheckSig(sig, pubkey, scriptPubKey))
+ if (TransactionSignatureChecker(&txTo, nIn).CheckSig(sig, pubkey, scriptPubKey))
{
sigs[pubkey] = sig;
break;
diff --git a/src/script/standard.h b/src/script/standard.h
index ac80193773..a8b0acc981 100644
--- a/src/script/standard.h
+++ b/src/script/standard.h
@@ -25,7 +25,7 @@ public:
CScriptID(const uint160& in) : uint160(in) {}
};
-static const unsigned int MAX_OP_RETURN_RELAY = 40; //! bytes
+static const unsigned int MAX_OP_RETURN_RELAY = 80; //! bytes
extern unsigned nMaxDatacarrierBytes;
/**
@@ -45,6 +45,7 @@ static const unsigned int MANDATORY_SCRIPT_VERIFY_FLAGS = SCRIPT_VERIFY_P2SH;
* blocks and we must accept those blocks.
*/
static const unsigned int STANDARD_SCRIPT_VERIFY_FLAGS = MANDATORY_SCRIPT_VERIFY_FLAGS |
+ SCRIPT_VERIFY_DERSIG |
SCRIPT_VERIFY_STRICTENC |
SCRIPT_VERIFY_MINIMALDATA |
SCRIPT_VERIFY_NULLDUMMY |
diff --git a/src/secp256k1/.gitignore b/src/secp256k1/.gitignore
index f0a54077a5..b9f7d243ec 100644
--- a/src/secp256k1/.gitignore
+++ b/src/secp256k1/.gitignore
@@ -1,6 +1,7 @@
bench_inv
bench_sign
bench_verify
+bench_recover
tests
*.exe
*.so
diff --git a/src/secp256k1/.travis.yml b/src/secp256k1/.travis.yml
index 28cd61dbc9..40f8dae23f 100644
--- a/src/secp256k1/.travis.yml
+++ b/src/secp256k1/.travis.yml
@@ -4,24 +4,22 @@ compiler:
- gcc
install:
- sudo apt-get install -qq libssl-dev
- - if [ "$BIGNUM" = "gmp" -o "$BIGNUM" = "auto" -o "$FIELD" = "gmp" ]; then sudo apt-get install --no-install-recommends --no-upgrade -qq libgmp-dev; fi
+ - if [ "$BIGNUM" = "gmp" -o "$BIGNUM" = "auto" ]; then sudo apt-get install --no-install-recommends --no-upgrade -qq libgmp-dev; fi
- if [ -n "$EXTRAPACKAGES" ]; then sudo apt-get update && sudo apt-get install --no-install-recommends --no-upgrade $EXTRAPACKAGES; fi
env:
global:
- - FIELD=auto BIGNUM=auto SCALAR=auto ENDOMORPHISM=no BUILD=check EXTRAFLAGS= HOST= EXTRAPACKAGES=
+ - FIELD=auto BIGNUM=auto SCALAR=auto ENDOMORPHISM=no ASM=no BUILD=check EXTRAFLAGS= HOST= EXTRAPACKAGES=
matrix:
- SCALAR=32bit
- SCALAR=64bit
- - FIELD=gmp
- - FIELD=gmp ENDOMORPHISM=yes
- - FIELD=64bit_asm
- - FIELD=64bit_asm ENDOMORPHISM=yes
- FIELD=64bit
- FIELD=64bit ENDOMORPHISM=yes
+ - FIELD=64bit ASM=x86_64
+ - FIELD=64bit ENDOMORPHISM=yes ASM=x86_64
- FIELD=32bit
- FIELD=32bit ENDOMORPHISM=yes
- - BIGNUM=none
- - BIGNUM=none ENDOMORPHISM=yes
+ - BIGNUM=no
+ - BIGNUM=no ENDOMORPHISM=yes
- BUILD=distcheck
- EXTRAFLAGS=CFLAGS=-DDETERMINISTIC
- HOST=i686-linux-gnu EXTRAPACKAGES="gcc-multilib"
diff --git a/src/secp256k1/Makefile.am b/src/secp256k1/Makefile.am
index 390d2c9ffa..985c172eba 100644
--- a/src/secp256k1/Makefile.am
+++ b/src/secp256k1/Makefile.am
@@ -33,8 +33,8 @@ noinst_HEADERS += src/java/org_bitcoin_NativeSecp256k1.h
noinst_HEADERS += src/util.h
noinst_HEADERS += src/testrand.h
noinst_HEADERS += src/testrand_impl.h
-noinst_HEADERS += src/field_gmp.h
-noinst_HEADERS += src/field_gmp_impl.h
+noinst_HEADERS += src/hash.h
+noinst_HEADERS += src/hash_impl.h
noinst_HEADERS += src/field.h
noinst_HEADERS += src/field_impl.h
noinst_HEADERS += src/bench.h
diff --git a/src/secp256k1/build-aux/m4/bitcoin_secp.m4 b/src/secp256k1/build-aux/m4/bitcoin_secp.m4
index 1373478c9c..4a398d6c93 100644
--- a/src/secp256k1/build-aux/m4/bitcoin_secp.m4
+++ b/src/secp256k1/build-aux/m4/bitcoin_secp.m4
@@ -1,12 +1,6 @@
dnl libsecp25k1 helper checks
AC_DEFUN([SECP_INT128_CHECK],[
has_int128=$ac_cv_type___int128
-if test x"$has_int128" != x"yes" && test x"$set_field" = x"64bit"; then
- AC_MSG_ERROR([$set_field field support explicitly requested but is not compatible with this host])
-fi
-if test x"$has_int128" != x"yes" && test x"$set_scalar" = x"64bit"; then
- AC_MSG_ERROR([$set_scalar scalar support explicitly requested but is not compatible with this host])
-fi
])
dnl
@@ -18,11 +12,6 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
__asm__ __volatile__("movq $0x100000000,%1; mulq %%rsi" : "+a"(a) : "S"(tmp) : "cc", "%rdx");
]])],[has_64bit_asm=yes],[has_64bit_asm=no])
AC_MSG_RESULT([$has_64bit_asm])
-if test x"$set_field" == x"64bit_asm"; then
- if test x"$has_64bit_asm" == x"no"; then
- AC_MSG_ERROR([$set_field field support explicitly requested but no x86_64 assembly available])
- fi
-fi
])
dnl
@@ -43,7 +32,7 @@ else
)])
LIBS=
fi
-if test x"$has_libcrypto" == x"yes" && test x"$has_openssl_ec" = x; then
+if test x"$has_libcrypto" = x"yes" && test x"$has_openssl_ec" = x; then
AC_MSG_CHECKING(for EC functions in libcrypto)
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#include <openssl/ec.h>
@@ -69,11 +58,4 @@ if test x"$has_gmp" != x"yes"; then
CPPFLAGS="$CPPFLAGS_TEMP"
LIBS="$LIBS_TEMP"
fi
-if test x"$set_field" = x"gmp" && test x"$has_gmp" != x"yes"; then
- AC_MSG_ERROR([$set_field field support explicitly requested but libgmp was not found])
-fi
-if test x"$set_bignum" = x"gmp" && test x"$has_gmp" != x"yes"; then
- AC_MSG_ERROR([$set_bignum field support explicitly requested but libgmp was not found])
-fi
])
-
diff --git a/src/secp256k1/configure.ac b/src/secp256k1/configure.ac
index 40e121e806..f691156ff7 100644
--- a/src/secp256k1/configure.ac
+++ b/src/secp256k1/configure.ac
@@ -6,7 +6,7 @@ AC_CANONICAL_HOST
AH_TOP([#ifndef LIBSECP256K1_CONFIG_H])
AH_TOP([#define LIBSECP256K1_CONFIG_H])
AH_BOTTOM([#endif //LIBSECP256K1_CONFIG_H])
-AM_INIT_AUTOMAKE([foreign])
+AM_INIT_AUTOMAKE([foreign subdir-objects])
LT_INIT
dnl make the compilation flags quiet unless V=1 is used
@@ -23,7 +23,7 @@ if test "x$CFLAGS" = "x"; then
fi
AC_PROG_CC_C99
-if test x"$ac_cv_prog_cc_c99" == x"no"; then
+if test x"$ac_cv_prog_cc_c99" = x"no"; then
AC_MSG_ERROR([c99 compiler support required])
fi
@@ -82,9 +82,9 @@ AC_COMPILE_IFELSE([AC_LANG_SOURCE([[char foo;]])],
AC_ARG_ENABLE(benchmark,
- AS_HELP_STRING([--enable-benchmark],[compile benchmark (default is yes)]),
+ AS_HELP_STRING([--enable-benchmark],[compile benchmark (default is no)]),
[use_benchmark=$enableval],
- [use_benchmark=yes])
+ [use_benchmark=no])
AC_ARG_ENABLE(tests,
AS_HELP_STRING([--enable-tests],[compile tests (default is yes)]),
@@ -96,15 +96,18 @@ AC_ARG_ENABLE(endomorphism,
[use_endomorphism=$enableval],
[use_endomorphism=no])
-AC_ARG_WITH([field], [AS_HELP_STRING([--with-field=gmp|64bit|64bit_asm|32bit|auto],
+AC_ARG_WITH([field], [AS_HELP_STRING([--with-field=64bit|32bit|auto],
[Specify Field Implementation. Default is auto])],[req_field=$withval], [req_field=auto])
-AC_ARG_WITH([bignum], [AS_HELP_STRING([--with-bignum=gmp|none|auto],
+AC_ARG_WITH([bignum], [AS_HELP_STRING([--with-bignum=gmp|no|auto],
[Specify Bignum Implementation. Default is auto])],[req_bignum=$withval], [req_bignum=auto])
AC_ARG_WITH([scalar], [AS_HELP_STRING([--with-scalar=64bit|32bit|auto],
[Specify scalar implementation. Default is auto])],[req_scalar=$withval], [req_scalar=auto])
+AC_ARG_WITH([asm], [AS_HELP_STRING([--with-asm=x86_64|no|auto]
+[Specify assembly optimizations to use. Default is auto])],[req_asm=$withval], [req_asm=auto])
+
AC_CHECK_TYPES([__int128])
AC_MSG_CHECKING([for __builtin_expect])
@@ -113,40 +116,54 @@ AC_COMPILE_IFELSE([AC_LANG_SOURCE([[void myfunc() {__builtin_expect(0,0);}]])],
[ AC_MSG_RESULT([no])
])
-if test x"$req_field" = x"auto"; then
+if test x"$req_asm" = x"auto"; then
SECP_64BIT_ASM_CHECK
if test x"$has_64bit_asm" = x"yes"; then
- set_field=64bit_asm
+ set_asm=x86_64
+ fi
+ if test x"$set_asm" = x; then
+ set_asm=no
fi
+else
+ set_asm=$req_asm
+ case $set_asm in
+ x86_64)
+ SECP_64BIT_ASM_CHECK
+ if test x"$has_64bit_asm" != x"yes"; then
+ AC_MSG_ERROR([x86_64 assembly optimization requested but not available])
+ fi
+ ;;
+ no)
+ ;;
+ *)
+ AC_MSG_ERROR([invalid assembly optimization selection])
+ ;;
+ esac
+fi
+if test x"$req_field" = x"auto"; then
+ if test x"set_asm" = x"x86_64"; then
+ set_field=64bit
+ fi
if test x"$set_field" = x; then
SECP_INT128_CHECK
if test x"$has_int128" = x"yes"; then
set_field=64bit
fi
fi
-
- if test x"$set_field" = x; then
- SECP_GMP_CHECK
- if test x"$has_gmp" = x"yes"; then
- set_field=gmp
- fi
- fi
-
if test x"$set_field" = x; then
set_field=32bit
fi
else
set_field=$req_field
case $set_field in
- 64bit_asm)
- SECP_64BIT_ASM_CHECK
- ;;
64bit)
- SECP_INT128_CHECK
- ;;
- gmp)
- SECP_GMP_CHECK
+ if test x"$set_asm" != x"x86_64"; then
+ SECP_INT128_CHECK
+ if test x"$has_int128" != x"yes"; then
+ AC_MSG_ERROR([64bit field explicitly requested but neither __int128 support or x86_64 assembly available])
+ fi
+ fi
;;
32bit)
;;
@@ -157,11 +174,9 @@ else
fi
if test x"$req_scalar" = x"auto"; then
- if test x"$set_scalar" = x; then
- SECP_INT128_CHECK
- if test x"$has_int128" = x"yes"; then
- set_scalar=64bit
- fi
+ SECP_INT128_CHECK
+ if test x"$has_int128" = x"yes"; then
+ set_scalar=64bit
fi
if test x"$set_scalar" = x; then
set_scalar=32bit
@@ -171,6 +186,9 @@ else
case $set_scalar in
64bit)
SECP_INT128_CHECK
+ if test x"$has_int128" != x"yes"; then
+ AC_MSG_ERROR([64bit scalar explicitly requested but __int128 support not available])
+ fi
;;
32bit)
;;
@@ -187,15 +205,18 @@ if test x"$req_bignum" = x"auto"; then
fi
if test x"$set_bignum" = x; then
- set_bignum=none
+ set_bignum=no
fi
else
set_bignum=$req_bignum
case $set_bignum in
gmp)
SECP_GMP_CHECK
+ if test x"$has_gmp" != x"yes"; then
+ AC_MSG_ERROR([gmp bignum explicitly requested but libgmp not available])
+ fi
;;
- none)
+ no)
;;
*)
AC_MSG_ERROR([invalid bignum implementation selection])
@@ -203,20 +224,23 @@ else
esac
fi
+# select assembly optimization
+case $set_asm in
+x86_64)
+ AC_DEFINE(USE_ASM_X86_64, 1, [Define this symbol to enable x86_64 assembly optimizations])
+ ;;
+no)
+ ;;
+*)
+ AC_MSG_ERROR([invalid assembly optimizations])
+ ;;
+esac
+
# select field implementation
case $set_field in
-64bit_asm)
- AC_DEFINE(USE_FIELD_5X52_ASM, 1, [Define this symbol to use the assembly version for the 5x52 field implementation])
- AC_DEFINE(USE_FIELD_5X52, 1, [Define this symbol to use the FIELD_5X52 implementation])
- ;;
64bit)
- AC_DEFINE(USE_FIELD_5X52_INT128, 1, [Define this symbol to use the __int128 version for the 5x52 field implementation])
AC_DEFINE(USE_FIELD_5X52, 1, [Define this symbol to use the FIELD_5X52 implementation])
;;
-gmp)
- AC_DEFINE(HAVE_LIBGMP,1,[Define this symbol if libgmp is installed])
- AC_DEFINE(USE_FIELD_GMP, 1, [Define this symbol to use the FIELD_GMP implementation])
- ;;
32bit)
AC_DEFINE(USE_FIELD_10X26, 1, [Define this symbol to use the FIELD_10X26 implementation])
;;
@@ -233,7 +257,7 @@ gmp)
AC_DEFINE(USE_FIELD_INV_NUM, 1, [Define this symbol to use the num-based field inverse implementation])
AC_DEFINE(USE_SCALAR_INV_NUM, 1, [Define this symbol to use the num-based scalar inverse implementation])
;;
-none)
+no)
AC_DEFINE(USE_NUM_NONE, 1, [Define this symbol to use no num implementation])
AC_DEFINE(USE_FIELD_INV_BUILTIN, 1, [Define this symbol to use the native field inverse implementation])
AC_DEFINE(USE_SCALAR_INV_BUILTIN, 1, [Define this symbol to use the native scalar inverse implementation])
@@ -258,7 +282,7 @@ esac
if test x"$use_tests" = x"yes"; then
SECP_OPENSSL_CHECK
- if test x"$has_openssl_ec" == x"yes"; then
+ if test x"$has_openssl_ec" = x"yes"; then
AC_DEFINE(ENABLE_OPENSSL_TESTS, 1, [Define this symbol if OpenSSL EC functions are available])
SECP_TEST_INCLUDES="$SSL_CFLAGS $CRYPTO_CFLAGS"
SECP_TEST_LIBS="$CRYPTO_LIBS"
@@ -272,7 +296,7 @@ if test x"$use_tests" = x"yes"; then
fi
fi
-if test x"$set_field" = x"gmp" || test x"$set_bignum" = x"gmp"; then
+if test x"$set_bignum" = x"gmp"; then
SECP_LIBS="$SECP_LIBS $GMP_LIBS"
SECP_INCLUDES="$SECP_INCLUDES $GMP_CPPFLAGS"
fi
@@ -281,9 +305,11 @@ if test x"$use_endomorphism" = x"yes"; then
AC_DEFINE(USE_ENDOMORPHISM, 1, [Define this symbol to use endomorphism optimization])
fi
+AC_MSG_NOTICE([Using assembly optimizations: $set_asm])
AC_MSG_NOTICE([Using field implementation: $set_field])
AC_MSG_NOTICE([Using bignum implementation: $set_bignum])
AC_MSG_NOTICE([Using scalar implementation: $set_scalar])
+AC_MSG_NOTICE([Using endomorphism optimizations: $use_endomorphism])
AC_CONFIG_HEADERS([src/libsecp256k1-config.h])
AC_CONFIG_FILES([Makefile libsecp256k1.pc])
@@ -291,9 +317,8 @@ AC_SUBST(SECP_INCLUDES)
AC_SUBST(SECP_LIBS)
AC_SUBST(SECP_TEST_LIBS)
AC_SUBST(SECP_TEST_INCLUDES)
-AM_CONDITIONAL([USE_ASM], [test x"$set_field" == x"64bit_asm"])
AM_CONDITIONAL([USE_TESTS], [test x"$use_tests" != x"no"])
-AM_CONDITIONAL([USE_BENCHMARK], [test x"$use_benchmark" != x"no"])
+AM_CONDITIONAL([USE_BENCHMARK], [test x"$use_benchmark" = x"yes"])
dnl make sure nothing new is exported so that we don't break the cache
PKGCONFIG_PATH_TEMP="$PKG_CONFIG_PATH"
diff --git a/src/secp256k1/include/secp256k1.h b/src/secp256k1/include/secp256k1.h
index dca7ca00e7..cfdae31eaf 100644
--- a/src/secp256k1/include/secp256k1.h
+++ b/src/secp256k1/include/secp256k1.h
@@ -77,42 +77,73 @@ SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_verify(
int pubkeylen
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(4);
+/** A pointer to a function to deterministically generate a nonce.
+ * Returns: 1 if a nonce was succesfully generated. 0 will cause signing to fail.
+ * In: msg32: the 32-byte message hash being verified (will not be NULL)
+ * key32: pointer to a 32-byte secret key (will not be NULL)
+ * attempt: how many iterations we have tried to find a nonce.
+ * This will almost always be 0, but different attempt values
+ * are required to result in a different nonce.
+ * data: Arbitrary data pointer that is passed through.
+ * Out: nonce32: pointer to a 32-byte array to be filled by the function.
+ * Except for test cases, this function should compute some cryptographic hash of
+ * the message, the key and the attempt.
+ */
+typedef int (*secp256k1_nonce_function_t)(
+ unsigned char *nonce32,
+ const unsigned char *msg32,
+ const unsigned char *key32,
+ unsigned int attempt,
+ const void *data
+);
+
+/** An implementation of RFC6979 (using HMAC-SHA256) as nonce generation function. */
+extern const secp256k1_nonce_function_t secp256k1_nonce_function_rfc6979;
+
+/** A default safe nonce generation function (currently equal to secp256k1_nonce_function_rfc6979). */
+extern const secp256k1_nonce_function_t secp256k1_nonce_function_default;
+
+
/** Create an ECDSA signature.
* Returns: 1: signature created
- * 0: nonce invalid, try another one
+ * 0: the nonce generation function failed
* In: msg32: the 32-byte message hash being signed (cannot be NULL)
* seckey: pointer to a 32-byte secret key (cannot be NULL, assumed to be valid)
- * nonce: pointer to a 32-byte nonce (cannot be NULL, generated with a cryptographic PRNG)
+ * noncefp:pointer to a nonce generation function. If NULL, secp256k1_nonce_function_default is used
+ * ndata: pointer to arbitrary data used by the nonce generation function (can be NULL)
* Out: sig: pointer to an array where the signature will be placed (cannot be NULL)
* In/Out: siglen: pointer to an int with the length of sig, which will be updated
* to contain the actual signature length (<=72).
* Requires starting using SECP256K1_START_SIGN.
*/
-SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_sign(
+int secp256k1_ecdsa_sign(
const unsigned char *msg32,
unsigned char *sig,
int *siglen,
const unsigned char *seckey,
- const unsigned char *nonce
-) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5);
+ secp256k1_nonce_function_t noncefp,
+ const void *ndata
+) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
/** Create a compact ECDSA signature (64 byte + recovery id).
* Returns: 1: signature created
- * 0: nonce invalid, try another one
+ * 0: the nonce generation function failed
* In: msg32: the 32-byte message hash being signed (cannot be NULL)
* seckey: pointer to a 32-byte secret key (cannot be NULL, assumed to be valid)
- * nonce: pointer to a 32-byte nonce (cannot be NULL, generated with a cryptographic PRNG)
+ * noncefp:pointer to a nonce generation function. If NULL, secp256k1_nonce_function_default is used
+ * ndata: pointer to arbitrary data used by the nonce generation function (can be NULL)
* Out: sig: pointer to a 64-byte array where the signature will be placed (cannot be NULL)
* recid: pointer to an int, which will be updated to contain the recovery id (can be NULL)
* Requires starting using SECP256K1_START_SIGN.
*/
-SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_sign_compact(
+int secp256k1_ecdsa_sign_compact(
const unsigned char *msg32,
unsigned char *sig64,
const unsigned char *seckey,
- const unsigned char *nonce,
+ secp256k1_nonce_function_t noncefp,
+ const void *ndata,
int *recid
-) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
+) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
/** Recover an ECDSA public key from a compact signature.
* Returns: 1: public key successfully recovered (which guarantees a correct signature).
diff --git a/src/secp256k1/src/bench_sign.c b/src/secp256k1/src/bench_sign.c
index 66e71e1ac4..2276f00b9a 100644
--- a/src/secp256k1/src/bench_sign.c
+++ b/src/secp256k1/src/bench_sign.c
@@ -10,7 +10,6 @@
typedef struct {
unsigned char msg[32];
- unsigned char nonce[32];
unsigned char key[32];
} bench_sign_t;
@@ -18,7 +17,6 @@ static void bench_sign_setup(void* arg) {
bench_sign_t *data = (bench_sign_t*)arg;
for (int i = 0; i < 32; i++) data->msg[i] = i + 1;
- for (int i = 0; i < 32; i++) data->nonce[i] = i + 33;
for (int i = 0; i < 32; i++) data->key[i] = i + 65;
}
@@ -28,9 +26,8 @@ static void bench_sign(void* arg) {
unsigned char sig[64];
for (int i=0; i<20000; i++) {
int recid = 0;
- CHECK(secp256k1_ecdsa_sign_compact(data->msg, sig, data->key, data->nonce, &recid));
+ CHECK(secp256k1_ecdsa_sign_compact(data->msg, sig, data->key, NULL, NULL, &recid));
for (int j = 0; j < 32; j++) {
- data->nonce[j] = data->key[j]; /* Move former key to nonce */
data->msg[j] = sig[j]; /* Move former R to message. */
data->key[j] = sig[j + 32]; /* Move former S to key. */
}
diff --git a/src/secp256k1/src/bench_verify.c b/src/secp256k1/src/bench_verify.c
index b123c4087d..a58ca84347 100644
--- a/src/secp256k1/src/bench_verify.c
+++ b/src/secp256k1/src/bench_verify.c
@@ -14,7 +14,6 @@
typedef struct {
unsigned char msg[32];
unsigned char key[32];
- unsigned char nonce[32];
unsigned char sig[72];
int siglen;
unsigned char pubkey[33];
@@ -42,9 +41,8 @@ int main(void) {
for (int i = 0; i < 32; i++) data.msg[i] = 1 + i;
for (int i = 0; i < 32; i++) data.key[i] = 33 + i;
- for (int i = 0; i < 32; i++) data.nonce[i] = 65 + i;
data.siglen = 72;
- CHECK(secp256k1_ecdsa_sign(data.msg, data.sig, &data.siglen, data.key, data.nonce));
+ secp256k1_ecdsa_sign(data.msg, data.sig, &data.siglen, data.key, NULL, NULL);
data.pubkeylen = 33;
CHECK(secp256k1_ec_pubkey_create(data.pubkey, &data.pubkeylen, data.key, 1));
diff --git a/src/secp256k1/src/ecdsa_impl.h b/src/secp256k1/src/ecdsa_impl.h
index 8825d05fed..674650c1e9 100644
--- a/src/secp256k1/src/ecdsa_impl.h
+++ b/src/secp256k1/src/ecdsa_impl.h
@@ -109,25 +109,53 @@ static int secp256k1_ecdsa_sig_serialize(unsigned char *sig, int *size, const se
return 1;
}
-static int secp256k1_ecdsa_sig_recompute(secp256k1_scalar_t *r2, const secp256k1_ecdsa_sig_t *sig, const secp256k1_ge_t *pubkey, const secp256k1_scalar_t *message) {
+static int secp256k1_ecdsa_sig_verify(const secp256k1_ecdsa_sig_t *sig, const secp256k1_ge_t *pubkey, const secp256k1_scalar_t *message) {
if (secp256k1_scalar_is_zero(&sig->r) || secp256k1_scalar_is_zero(&sig->s))
return 0;
- int ret = 0;
secp256k1_scalar_t sn, u1, u2;
secp256k1_scalar_inverse_var(&sn, &sig->s);
secp256k1_scalar_mul(&u1, &sn, message);
secp256k1_scalar_mul(&u2, &sn, &sig->r);
secp256k1_gej_t pubkeyj; secp256k1_gej_set_ge(&pubkeyj, pubkey);
secp256k1_gej_t pr; secp256k1_ecmult(&pr, &pubkeyj, &u2, &u1);
- if (!secp256k1_gej_is_infinity(&pr)) {
- secp256k1_fe_t xr; secp256k1_gej_get_x_var(&xr, &pr);
- secp256k1_fe_normalize_var(&xr);
- unsigned char xrb[32]; secp256k1_fe_get_b32(xrb, &xr);
- secp256k1_scalar_set_b32(r2, xrb, NULL);
- ret = 1;
+ if (secp256k1_gej_is_infinity(&pr)) {
+ return 0;
+ }
+ unsigned char c[32];
+ secp256k1_scalar_get_b32(c, &sig->r);
+ secp256k1_fe_t xr;
+ secp256k1_fe_set_b32(&xr, c);
+
+ // We now have the recomputed R point in pr, and its claimed x coordinate (modulo n)
+ // in xr. Naively, we would extract the x coordinate from pr (requiring a inversion modulo p),
+ // compute the remainder modulo n, and compare it to xr. However:
+ //
+ // xr == X(pr) mod n
+ // <=> exists h. (xr + h * n < p && xr + h * n == X(pr))
+ // [Since 2 * n > p, h can only be 0 or 1]
+ // <=> (xr == X(pr)) || (xr + n < p && xr + n == X(pr))
+ // [In Jacobian coordinates, X(pr) is pr.x / pr.z^2 mod p]
+ // <=> (xr == pr.x / pr.z^2 mod p) || (xr + n < p && xr + n == pr.x / pr.z^2 mod p)
+ // [Multiplying both sides of the equations by pr.z^2 mod p]
+ // <=> (xr * pr.z^2 mod p == pr.x) || (xr + n < p && (xr + n) * pr.z^2 mod p == pr.x)
+ //
+ // Thus, we can avoid the inversion, but we have to check both cases separately.
+ // secp256k1_gej_eq_x implements the (xr * pr.z^2 mod p == pr.x) test.
+ if (secp256k1_gej_eq_x_var(&xr, &pr)) {
+ // xr.x == xr * xr.z^2 mod p, so the signature is valid.
+ return 1;
+ }
+ if (secp256k1_fe_cmp_var(&xr, &secp256k1_ecdsa_consts->p_minus_order) >= 0) {
+ // xr + p >= n, so we can skip testing the second case.
+ return 0;
+ }
+ secp256k1_fe_add(&xr, &secp256k1_ecdsa_consts->order_as_fe);
+ if (secp256k1_gej_eq_x_var(&xr, &pr)) {
+ // (xr + n) * pr.z^2 mod p == pr.x, so the signature is valid.
+ return 1;
}
- return ret;
+ return 0;
}
static int secp256k1_ecdsa_sig_recover(const secp256k1_ecdsa_sig_t *sig, secp256k1_ge_t *pubkey, const secp256k1_scalar_t *message, int recid) {
@@ -159,13 +187,6 @@ static int secp256k1_ecdsa_sig_recover(const secp256k1_ecdsa_sig_t *sig, secp256
return !secp256k1_gej_is_infinity(&qj);
}
-static int secp256k1_ecdsa_sig_verify(const secp256k1_ecdsa_sig_t *sig, const secp256k1_ge_t *pubkey, const secp256k1_scalar_t *message) {
- secp256k1_scalar_t r2;
- int ret = 0;
- ret = secp256k1_ecdsa_sig_recompute(&r2, sig, pubkey, message) && secp256k1_scalar_eq(&sig->r, &r2);
- return ret;
-}
-
static int secp256k1_ecdsa_sig_sign(secp256k1_ecdsa_sig_t *sig, const secp256k1_scalar_t *seckey, const secp256k1_scalar_t *message, const secp256k1_scalar_t *nonce, int *recid) {
secp256k1_gej_t rp;
secp256k1_ecmult_gen(&rp, nonce);
@@ -177,6 +198,12 @@ static int secp256k1_ecdsa_sig_sign(secp256k1_ecdsa_sig_t *sig, const secp256k1_
secp256k1_fe_get_b32(b, &r.x);
int overflow = 0;
secp256k1_scalar_set_b32(&sig->r, b, &overflow);
+ if (secp256k1_scalar_is_zero(&sig->r)) {
+ /* P.x = order is on the curve, so technically sig->r could end up zero, which would be an invalid signature. */
+ secp256k1_gej_clear(&rp);
+ secp256k1_ge_clear(&r);
+ return 0;
+ }
if (recid)
*recid = (overflow ? 2 : 0) | (secp256k1_fe_is_odd(&r.y) ? 1 : 0);
secp256k1_scalar_t n;
diff --git a/src/secp256k1/src/ecmult_gen_impl.h b/src/secp256k1/src/ecmult_gen_impl.h
index 5a5b16ce14..48436316e1 100644
--- a/src/secp256k1/src/ecmult_gen_impl.h
+++ b/src/secp256k1/src/ecmult_gen_impl.h
@@ -73,7 +73,7 @@ static void secp256k1_ecmult_gen_start(void) {
secp256k1_gej_double_var(&numsbase, &numsbase);
if (j == 62) {
/* In the last iteration, numsbase is (1 - 2^j) * nums instead. */
- secp256k1_gej_neg_var(&numsbase, &numsbase);
+ secp256k1_gej_neg(&numsbase, &numsbase);
secp256k1_gej_add_var(&numsbase, &numsbase, &nums_gej);
}
}
diff --git a/src/secp256k1/src/ecmult_impl.h b/src/secp256k1/src/ecmult_impl.h
index 6536771046..345cfae733 100644
--- a/src/secp256k1/src/ecmult_impl.h
+++ b/src/secp256k1/src/ecmult_impl.h
@@ -70,8 +70,8 @@ static void secp256k1_ecmult_table_precomp_ge_var(secp256k1_ge_t *pre, const sec
(neg)((r), &(pre)[(-(n)-1)/2]); \
} while(0)
-#define ECMULT_TABLE_GET_GEJ(r,pre,n,w) ECMULT_TABLE_GET((r),(pre),(n),(w),secp256k1_gej_neg_var)
-#define ECMULT_TABLE_GET_GE(r,pre,n,w) ECMULT_TABLE_GET((r),(pre),(n),(w),secp256k1_ge_neg_var)
+#define ECMULT_TABLE_GET_GEJ(r,pre,n,w) ECMULT_TABLE_GET((r),(pre),(n),(w),secp256k1_gej_neg)
+#define ECMULT_TABLE_GET_GE(r,pre,n,w) ECMULT_TABLE_GET((r),(pre),(n),(w),secp256k1_ge_neg)
typedef struct {
/* For accelerating the computation of a*P + b*G: */
diff --git a/src/secp256k1/src/field.h b/src/secp256k1/src/field.h
index 53aa29e13f..14e2b813c1 100644
--- a/src/secp256k1/src/field.h
+++ b/src/secp256k1/src/field.h
@@ -22,9 +22,7 @@
#include "libsecp256k1-config.h"
#endif
-#if defined(USE_FIELD_GMP)
-#include "field_gmp.h"
-#elif defined(USE_FIELD_10X26)
+#if defined(USE_FIELD_10X26)
#include "field_10x26.h"
#elif defined(USE_FIELD_5X52)
#include "field_5x52.h"
@@ -50,9 +48,20 @@ static void secp256k1_fe_stop(void);
/** Normalize a field element. */
static void secp256k1_fe_normalize(secp256k1_fe_t *r);
+/** Weakly normalize a field element: reduce it magnitude to 1, but don't fully normalize. */
+static void secp256k1_fe_normalize_weak(secp256k1_fe_t *r);
+
/** Normalize a field element, without constant-time guarantee. */
static void secp256k1_fe_normalize_var(secp256k1_fe_t *r);
+/** Verify whether a field element represents zero i.e. would normalize to a zero value. The field
+ * implementation may optionally normalize the input, but this should not be relied upon. */
+static int secp256k1_fe_normalizes_to_zero(secp256k1_fe_t *r);
+
+/** Verify whether a field element represents zero i.e. would normalize to a zero value. The field
+ * implementation may optionally normalize the input, but this should not be relied upon. */
+static int secp256k1_fe_normalizes_to_zero_var(secp256k1_fe_t *r);
+
/** Set a field element equal to a small integer. Resulting field element is normalized. */
static void secp256k1_fe_set_int(secp256k1_fe_t *r, int a);
@@ -62,8 +71,8 @@ static int secp256k1_fe_is_zero(const secp256k1_fe_t *a);
/** Check the "oddness" of a field element. Requires the input to be normalized. */
static int secp256k1_fe_is_odd(const secp256k1_fe_t *a);
-/** Compare two field elements. Requires both inputs to be normalized */
-static int secp256k1_fe_equal(const secp256k1_fe_t *a, const secp256k1_fe_t *b);
+/** Compare two field elements. Requires magnitude-1 inputs. */
+static int secp256k1_fe_equal_var(const secp256k1_fe_t *a, const secp256k1_fe_t *b);
/** Compare two field elements. Requires both inputs to be normalized */
static int secp256k1_fe_cmp_var(const secp256k1_fe_t *a, const secp256k1_fe_t *b);
diff --git a/src/secp256k1/src/field_10x26_impl.h b/src/secp256k1/src/field_10x26_impl.h
index d20229cda6..9ef60a807a 100644
--- a/src/secp256k1/src/field_10x26_impl.h
+++ b/src/secp256k1/src/field_10x26_impl.h
@@ -31,6 +31,7 @@ static void secp256k1_fe_verify(const secp256k1_fe_t *a) {
r &= (d[8] <= 0x3FFFFFFUL * m);
r &= (d[9] <= 0x03FFFFFUL * m);
r &= (a->magnitude >= 0);
+ r &= (a->magnitude <= 32);
if (a->normalized) {
r &= (a->magnitude <= 1);
if (r && (d[9] == 0x03FFFFFUL)) {
@@ -103,6 +104,37 @@ static void secp256k1_fe_normalize(secp256k1_fe_t *r) {
#endif
}
+static void secp256k1_fe_normalize_weak(secp256k1_fe_t *r) {
+ uint32_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4],
+ t5 = r->n[5], t6 = r->n[6], t7 = r->n[7], t8 = r->n[8], t9 = r->n[9];
+
+ /* Reduce t9 at the start so there will be at most a single carry from the first pass */
+ uint32_t x = t9 >> 22; t9 &= 0x03FFFFFUL;
+
+ /* The first pass ensures the magnitude is 1, ... */
+ t0 += x * 0x3D1UL; t1 += (x << 6);
+ t1 += (t0 >> 26); t0 &= 0x3FFFFFFUL;
+ t2 += (t1 >> 26); t1 &= 0x3FFFFFFUL;
+ t3 += (t2 >> 26); t2 &= 0x3FFFFFFUL;
+ t4 += (t3 >> 26); t3 &= 0x3FFFFFFUL;
+ t5 += (t4 >> 26); t4 &= 0x3FFFFFFUL;
+ t6 += (t5 >> 26); t5 &= 0x3FFFFFFUL;
+ t7 += (t6 >> 26); t6 &= 0x3FFFFFFUL;
+ t8 += (t7 >> 26); t7 &= 0x3FFFFFFUL;
+ t9 += (t8 >> 26); t8 &= 0x3FFFFFFUL;
+
+ /* ... except for a possible carry at bit 22 of t9 (i.e. bit 256 of the field element) */
+ VERIFY_CHECK(t9 >> 23 == 0);
+
+ r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4;
+ r->n[5] = t5; r->n[6] = t6; r->n[7] = t7; r->n[8] = t8; r->n[9] = t9;
+
+#ifdef VERIFY
+ r->magnitude = 1;
+ secp256k1_fe_verify(r);
+#endif
+}
+
static void secp256k1_fe_normalize_var(secp256k1_fe_t *r) {
uint32_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4],
t5 = r->n[5], t6 = r->n[6], t7 = r->n[7], t8 = r->n[8], t9 = r->n[9];
@@ -159,6 +191,73 @@ static void secp256k1_fe_normalize_var(secp256k1_fe_t *r) {
#endif
}
+static int secp256k1_fe_normalizes_to_zero(secp256k1_fe_t *r) {
+ uint32_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4],
+ t5 = r->n[5], t6 = r->n[6], t7 = r->n[7], t8 = r->n[8], t9 = r->n[9];
+
+ /* Reduce t9 at the start so there will be at most a single carry from the first pass */
+ uint32_t x = t9 >> 22; t9 &= 0x03FFFFFUL;
+
+ /* z0 tracks a possible raw value of 0, z1 tracks a possible raw value of P */
+ uint32_t z0, z1;
+
+ /* The first pass ensures the magnitude is 1, ... */
+ t0 += x * 0x3D1UL; t1 += (x << 6);
+ t1 += (t0 >> 26); t0 &= 0x3FFFFFFUL; z0 = t0; z1 = t0 ^ 0x3D0UL;
+ t2 += (t1 >> 26); t1 &= 0x3FFFFFFUL; z0 |= t1; z1 &= t1 ^ 0x40UL;
+ t3 += (t2 >> 26); t2 &= 0x3FFFFFFUL; z0 |= t2; z1 &= t2;
+ t4 += (t3 >> 26); t3 &= 0x3FFFFFFUL; z0 |= t3; z1 &= t3;
+ t5 += (t4 >> 26); t4 &= 0x3FFFFFFUL; z0 |= t4; z1 &= t4;
+ t6 += (t5 >> 26); t5 &= 0x3FFFFFFUL; z0 |= t5; z1 &= t5;
+ t7 += (t6 >> 26); t6 &= 0x3FFFFFFUL; z0 |= t6; z1 &= t6;
+ t8 += (t7 >> 26); t7 &= 0x3FFFFFFUL; z0 |= t7; z1 &= t7;
+ t9 += (t8 >> 26); t8 &= 0x3FFFFFFUL; z0 |= t8; z1 &= t8;
+ z0 |= t9; z1 &= t9 ^ 0x3C00000UL;
+
+ /* ... except for a possible carry at bit 22 of t9 (i.e. bit 256 of the field element) */
+ VERIFY_CHECK(t9 >> 23 == 0);
+
+ return (z0 == 0) | (z1 == 0x3FFFFFFUL);
+}
+
+static int secp256k1_fe_normalizes_to_zero_var(secp256k1_fe_t *r) {
+ uint32_t t0 = r->n[0], t9 = r->n[9];
+
+ /* Reduce t9 at the start so there will be at most a single carry from the first pass */
+ uint32_t x = t9 >> 22;
+
+ /* The first pass ensures the magnitude is 1, ... */
+ t0 += x * 0x3D1UL;
+
+ /* z0 tracks a possible raw value of 0, z1 tracks a possible raw value of P */
+ uint32_t z0 = t0 & 0x3FFFFFFUL, z1 = z0 ^ 0x3D0UL;
+
+ /* Fast return path should catch the majority of cases */
+ if ((z0 != 0UL) & (z1 != 0x3FFFFFFUL))
+ return 0;
+
+ uint32_t t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4],
+ t5 = r->n[5], t6 = r->n[6], t7 = r->n[7], t8 = r->n[8];
+ t9 &= 0x03FFFFFUL;
+ t1 += (x << 6);
+
+ t1 += (t0 >> 26); t0 = z0;
+ t2 += (t1 >> 26); t1 &= 0x3FFFFFFUL; z0 |= t1; z1 &= t1 ^ 0x40UL;
+ t3 += (t2 >> 26); t2 &= 0x3FFFFFFUL; z0 |= t2; z1 &= t2;
+ t4 += (t3 >> 26); t3 &= 0x3FFFFFFUL; z0 |= t3; z1 &= t3;
+ t5 += (t4 >> 26); t4 &= 0x3FFFFFFUL; z0 |= t4; z1 &= t4;
+ t6 += (t5 >> 26); t5 &= 0x3FFFFFFUL; z0 |= t5; z1 &= t5;
+ t7 += (t6 >> 26); t6 &= 0x3FFFFFFUL; z0 |= t6; z1 &= t6;
+ t8 += (t7 >> 26); t7 &= 0x3FFFFFFUL; z0 |= t7; z1 &= t7;
+ t9 += (t8 >> 26); t8 &= 0x3FFFFFFUL; z0 |= t8; z1 &= t8;
+ z0 |= t9; z1 &= t9 ^ 0x3C00000UL;
+
+ /* ... except for a possible carry at bit 22 of t9 (i.e. bit 256 of the field element) */
+ VERIFY_CHECK(t9 >> 23 == 0);
+
+ return (z0 == 0) | (z1 == 0x3FFFFFFUL);
+}
+
SECP256K1_INLINE static void secp256k1_fe_set_int(secp256k1_fe_t *r, int a) {
r->n[0] = a;
r->n[1] = r->n[2] = r->n[3] = r->n[4] = r->n[5] = r->n[6] = r->n[7] = r->n[8] = r->n[9] = 0;
@@ -196,18 +295,6 @@ SECP256K1_INLINE static void secp256k1_fe_clear(secp256k1_fe_t *a) {
}
}
-SECP256K1_INLINE static int secp256k1_fe_equal(const secp256k1_fe_t *a, const secp256k1_fe_t *b) {
-#ifdef VERIFY
- VERIFY_CHECK(a->normalized);
- VERIFY_CHECK(b->normalized);
- secp256k1_fe_verify(a);
- secp256k1_fe_verify(b);
-#endif
- const uint32_t *t = a->n, *u = b->n;
- return ((t[0]^u[0]) | (t[1]^u[1]) | (t[2]^u[2]) | (t[3]^u[3]) | (t[4]^u[4])
- | (t[5]^u[5]) | (t[6]^u[6]) | (t[7]^u[7]) | (t[8]^u[8]) | (t[9]^u[9])) == 0;
-}
-
static int secp256k1_fe_cmp_var(const secp256k1_fe_t *a, const secp256k1_fe_t *b) {
#ifdef VERIFY
VERIFY_CHECK(a->normalized);
diff --git a/src/secp256k1/src/field_5x52_impl.h b/src/secp256k1/src/field_5x52_impl.h
index 63176d6de4..4db9e6f5ff 100644
--- a/src/secp256k1/src/field_5x52_impl.h
+++ b/src/secp256k1/src/field_5x52_impl.h
@@ -16,12 +16,10 @@
#include "num.h"
#include "field.h"
-#if defined(USE_FIELD_5X52_ASM)
+#if defined(USE_ASM_X86_64)
#include "field_5x52_asm_impl.h"
-#elif defined(USE_FIELD_5X52_INT128)
-#include "field_5x52_int128_impl.h"
#else
-#error "Please select field_5x52 implementation"
+#include "field_5x52_int128_impl.h"
#endif
/** Implements arithmetic modulo FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE FFFFFC2F,
@@ -45,6 +43,7 @@ static void secp256k1_fe_verify(const secp256k1_fe_t *a) {
r &= (d[3] <= 0xFFFFFFFFFFFFFULL * m);
r &= (d[4] <= 0x0FFFFFFFFFFFFULL * m);
r &= (a->magnitude >= 0);
+ r &= (a->magnitude <= 2048);
if (a->normalized) {
r &= (a->magnitude <= 1);
if (r && (d[4] == 0x0FFFFFFFFFFFFULL) && ((d[3] & d[2] & d[1]) == 0xFFFFFFFFFFFFFULL)) {
@@ -102,6 +101,30 @@ static void secp256k1_fe_normalize(secp256k1_fe_t *r) {
#endif
}
+static void secp256k1_fe_normalize_weak(secp256k1_fe_t *r) {
+ uint64_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4];
+
+ /* Reduce t4 at the start so there will be at most a single carry from the first pass */
+ uint64_t x = t4 >> 48; t4 &= 0x0FFFFFFFFFFFFULL;
+
+ /* The first pass ensures the magnitude is 1, ... */
+ t0 += x * 0x1000003D1ULL;
+ t1 += (t0 >> 52); t0 &= 0xFFFFFFFFFFFFFULL;
+ t2 += (t1 >> 52); t1 &= 0xFFFFFFFFFFFFFULL;
+ t3 += (t2 >> 52); t2 &= 0xFFFFFFFFFFFFFULL;
+ t4 += (t3 >> 52); t3 &= 0xFFFFFFFFFFFFFULL;
+
+ /* ... except for a possible carry at bit 48 of t4 (i.e. bit 256 of the field element) */
+ VERIFY_CHECK(t4 >> 49 == 0);
+
+ r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4;
+
+#ifdef VERIFY
+ r->magnitude = 1;
+ secp256k1_fe_verify(r);
+#endif
+}
+
static void secp256k1_fe_normalize_var(secp256k1_fe_t *r) {
uint64_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4];
@@ -146,6 +169,60 @@ static void secp256k1_fe_normalize_var(secp256k1_fe_t *r) {
#endif
}
+static int secp256k1_fe_normalizes_to_zero(secp256k1_fe_t *r) {
+ uint64_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4];
+
+ /* Reduce t4 at the start so there will be at most a single carry from the first pass */
+ uint64_t x = t4 >> 48; t4 &= 0x0FFFFFFFFFFFFULL;
+
+ /* z0 tracks a possible raw value of 0, z1 tracks a possible raw value of P */
+ uint64_t z0, z1;
+
+ /* The first pass ensures the magnitude is 1, ... */
+ t0 += x * 0x1000003D1ULL;
+ t1 += (t0 >> 52); t0 &= 0xFFFFFFFFFFFFFULL; z0 = t0; z1 = t0 ^ 0x1000003D0ULL;
+ t2 += (t1 >> 52); t1 &= 0xFFFFFFFFFFFFFULL; z0 |= t1; z1 &= t1;
+ t3 += (t2 >> 52); t2 &= 0xFFFFFFFFFFFFFULL; z0 |= t2; z1 &= t2;
+ t4 += (t3 >> 52); t3 &= 0xFFFFFFFFFFFFFULL; z0 |= t3; z1 &= t3;
+ z0 |= t4; z1 &= t4 ^ 0xF000000000000ULL;
+
+ /* ... except for a possible carry at bit 48 of t4 (i.e. bit 256 of the field element) */
+ VERIFY_CHECK(t4 >> 49 == 0);
+
+ return (z0 == 0) | (z1 == 0xFFFFFFFFFFFFFULL);
+}
+
+static int secp256k1_fe_normalizes_to_zero_var(secp256k1_fe_t *r) {
+ uint64_t t0 = r->n[0], t4 = r->n[4];
+
+ /* Reduce t4 at the start so there will be at most a single carry from the first pass */
+ uint64_t x = t4 >> 48;
+
+ /* The first pass ensures the magnitude is 1, ... */
+ t0 += x * 0x1000003D1ULL;
+
+ /* z0 tracks a possible raw value of 0, z1 tracks a possible raw value of P */
+ uint64_t z0 = t0 & 0xFFFFFFFFFFFFFULL, z1 = z0 ^ 0x1000003D0ULL;
+
+ /* Fast return path should catch the majority of cases */
+ if ((z0 != 0ULL) & (z1 != 0xFFFFFFFFFFFFFULL))
+ return 0;
+
+ uint64_t t1 = r->n[1], t2 = r->n[2], t3 = r->n[3];
+ t4 &= 0x0FFFFFFFFFFFFULL;
+
+ t1 += (t0 >> 52); t0 = z0;
+ t2 += (t1 >> 52); t1 &= 0xFFFFFFFFFFFFFULL; z0 |= t1; z1 &= t1;
+ t3 += (t2 >> 52); t2 &= 0xFFFFFFFFFFFFFULL; z0 |= t2; z1 &= t2;
+ t4 += (t3 >> 52); t3 &= 0xFFFFFFFFFFFFFULL; z0 |= t3; z1 &= t3;
+ z0 |= t4; z1 &= t4 ^ 0xF000000000000ULL;
+
+ /* ... except for a possible carry at bit 48 of t4 (i.e. bit 256 of the field element) */
+ VERIFY_CHECK(t4 >> 49 == 0);
+
+ return (z0 == 0) | (z1 == 0xFFFFFFFFFFFFFULL);
+}
+
SECP256K1_INLINE static void secp256k1_fe_set_int(secp256k1_fe_t *r, int a) {
r->n[0] = a;
r->n[1] = r->n[2] = r->n[3] = r->n[4] = 0;
@@ -183,17 +260,6 @@ SECP256K1_INLINE static void secp256k1_fe_clear(secp256k1_fe_t *a) {
}
}
-SECP256K1_INLINE static int secp256k1_fe_equal(const secp256k1_fe_t *a, const secp256k1_fe_t *b) {
-#ifdef VERIFY
- VERIFY_CHECK(a->normalized);
- VERIFY_CHECK(b->normalized);
- secp256k1_fe_verify(a);
- secp256k1_fe_verify(b);
-#endif
- const uint64_t *t = a->n, *u = b->n;
- return ((t[0]^u[0]) | (t[1]^u[1]) | (t[2]^u[2]) | (t[3]^u[3]) | (t[4]^u[4])) == 0;
-}
-
static int secp256k1_fe_cmp_var(const secp256k1_fe_t *a, const secp256k1_fe_t *b) {
#ifdef VERIFY
VERIFY_CHECK(a->normalized);
diff --git a/src/secp256k1/src/field_gmp.h b/src/secp256k1/src/field_gmp.h
deleted file mode 100644
index b390fd9de8..0000000000
--- a/src/secp256k1/src/field_gmp.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/**********************************************************************
- * Copyright (c) 2013, 2014 Pieter Wuille *
- * Distributed under the MIT software license, see the accompanying *
- * file COPYING or http://www.opensource.org/licenses/mit-license.php.*
- **********************************************************************/
-
-#ifndef _SECP256K1_FIELD_REPR_
-#define _SECP256K1_FIELD_REPR_
-
-#include <gmp.h>
-
-#define FIELD_LIMBS ((256 + GMP_NUMB_BITS - 1) / GMP_NUMB_BITS)
-
-typedef struct {
- mp_limb_t n[FIELD_LIMBS+1];
-} secp256k1_fe_t;
-
-#endif
diff --git a/src/secp256k1/src/field_gmp_impl.h b/src/secp256k1/src/field_gmp_impl.h
deleted file mode 100644
index 73a55c4f00..0000000000
--- a/src/secp256k1/src/field_gmp_impl.h
+++ /dev/null
@@ -1,184 +0,0 @@
-/**********************************************************************
- * Copyright (c) 2013, 2014 Pieter Wuille *
- * Distributed under the MIT software license, see the accompanying *
- * file COPYING or http://www.opensource.org/licenses/mit-license.php.*
- **********************************************************************/
-
-#ifndef _SECP256K1_FIELD_REPR_IMPL_H_
-#define _SECP256K1_FIELD_REPR_IMPL_H_
-
-#include <stdio.h>
-#include <string.h>
-#include "num.h"
-#include "field.h"
-
-static mp_limb_t secp256k1_field_p[FIELD_LIMBS];
-static mp_limb_t secp256k1_field_pc[(33+GMP_NUMB_BITS-1)/GMP_NUMB_BITS];
-
-static void secp256k1_fe_inner_start(void) {
- for (int i=0; i<(33+GMP_NUMB_BITS-1)/GMP_NUMB_BITS; i++)
- secp256k1_field_pc[i] = 0;
- secp256k1_field_pc[0] += 0x3D1UL;
- secp256k1_field_pc[32/GMP_NUMB_BITS] += (((mp_limb_t)1) << (32 % GMP_NUMB_BITS));
- for (int i=0; i<FIELD_LIMBS; i++) {
- secp256k1_field_p[i] = 0;
- }
- mpn_sub(secp256k1_field_p, secp256k1_field_p, FIELD_LIMBS, secp256k1_field_pc, (33+GMP_NUMB_BITS-1)/GMP_NUMB_BITS);
-}
-
-static void secp256k1_fe_inner_stop(void) {
-}
-
-static void secp256k1_fe_normalize(secp256k1_fe_t *r) {
- if (r->n[FIELD_LIMBS] != 0) {
-#if (GMP_NUMB_BITS >= 40)
- mp_limb_t carry = mpn_add_1(r->n, r->n, FIELD_LIMBS, 0x1000003D1ULL * r->n[FIELD_LIMBS]);
- mpn_add_1(r->n, r->n, FIELD_LIMBS, 0x1000003D1ULL * carry);
-#else
- mp_limb_t carry = mpn_add_1(r->n, r->n, FIELD_LIMBS, 0x3D1UL * r->n[FIELD_LIMBS]) +
- mpn_add_1(r->n+(32/GMP_NUMB_BITS), r->n+(32/GMP_NUMB_BITS), FIELD_LIMBS-(32/GMP_NUMB_BITS), r->n[FIELD_LIMBS] << (32 % GMP_NUMB_BITS));
- mpn_add_1(r->n, r->n, FIELD_LIMBS, 0x3D1UL * carry);
- mpn_add_1(r->n+(32/GMP_NUMB_BITS), r->n+(32/GMP_NUMB_BITS), FIELD_LIMBS-(32/GMP_NUMB_BITS), carry << (32%GMP_NUMB_BITS));
-#endif
- r->n[FIELD_LIMBS] = 0;
- }
- if (mpn_cmp(r->n, secp256k1_field_p, FIELD_LIMBS) >= 0)
- mpn_sub(r->n, r->n, FIELD_LIMBS, secp256k1_field_p, FIELD_LIMBS);
-}
-
-static void secp256k1_fe_normalize_var(secp256k1_fe_t *r) {
- secp256k1_fe_normalize(r);
-}
-
-SECP256K1_INLINE static void secp256k1_fe_set_int(secp256k1_fe_t *r, int a) {
- r->n[0] = a;
- for (int i=1; i<FIELD_LIMBS+1; i++)
- r->n[i] = 0;
-}
-
-SECP256K1_INLINE static void secp256k1_fe_clear(secp256k1_fe_t *r) {
- for (int i=0; i<FIELD_LIMBS+1; i++)
- r->n[i] = 0;
-}
-
-SECP256K1_INLINE static int secp256k1_fe_is_zero(const secp256k1_fe_t *a) {
- int ret = 1;
- for (int i=0; i<FIELD_LIMBS+1; i++)
- ret &= (a->n[i] == 0);
- return ret;
-}
-
-SECP256K1_INLINE static int secp256k1_fe_is_odd(const secp256k1_fe_t *a) {
- return a->n[0] & 1;
-}
-
-SECP256K1_INLINE static int secp256k1_fe_equal(const secp256k1_fe_t *a, const secp256k1_fe_t *b) {
- int ret = 1;
- for (int i=0; i<FIELD_LIMBS+1; i++)
- ret &= (a->n[i] == b->n[i]);
- return ret;
-}
-
-SECP256K1_INLINE static int secp256k1_fe_cmp_var(const secp256k1_fe_t *a, const secp256k1_fe_t *b) {
- for (int i=FIELD_LIMBS; i>=0; i--) {
- if (a->n[i] > b->n[i]) return 1;
- if (a->n[i] < b->n[i]) return -1;
- }
- return 0;
-}
-
-static int secp256k1_fe_set_b32(secp256k1_fe_t *r, const unsigned char *a) {
- for (int i=0; i<FIELD_LIMBS+1; i++)
- r->n[i] = 0;
- for (int i=0; i<256; i++) {
- int limb = i/GMP_NUMB_BITS;
- int shift = i%GMP_NUMB_BITS;
- r->n[limb] |= (mp_limb_t)((a[31-i/8] >> (i%8)) & 0x1) << shift;
- }
- return (mpn_cmp(r->n, secp256k1_field_p, FIELD_LIMBS) < 0);
-}
-
-/** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */
-static void secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe_t *a) {
- for (int i=0; i<32; i++) {
- int c = 0;
- for (int j=0; j<8; j++) {
- int limb = (8*i+j)/GMP_NUMB_BITS;
- int shift = (8*i+j)%GMP_NUMB_BITS;
- c |= ((a->n[limb] >> shift) & 0x1) << j;
- }
- r[31-i] = c;
- }
-}
-
-SECP256K1_INLINE static void secp256k1_fe_negate(secp256k1_fe_t *r, const secp256k1_fe_t *a, int m) {
- (void)m;
- *r = *a;
- secp256k1_fe_normalize(r);
- for (int i=0; i<FIELD_LIMBS; i++)
- r->n[i] = ~(r->n[i]);
-#if (GMP_NUMB_BITS >= 33)
- mpn_sub_1(r->n, r->n, FIELD_LIMBS, 0x1000003D0ULL);
-#else
- mpn_sub_1(r->n, r->n, FIELD_LIMBS, 0x3D0UL);
- mpn_sub_1(r->n+(32/GMP_NUMB_BITS), r->n+(32/GMP_NUMB_BITS), FIELD_LIMBS-(32/GMP_NUMB_BITS), 0x1UL << (32%GMP_NUMB_BITS));
-#endif
-}
-
-SECP256K1_INLINE static void secp256k1_fe_mul_int(secp256k1_fe_t *r, int a) {
- mpn_mul_1(r->n, r->n, FIELD_LIMBS+1, a);
-}
-
-SECP256K1_INLINE static void secp256k1_fe_add(secp256k1_fe_t *r, const secp256k1_fe_t *a) {
- mpn_add(r->n, r->n, FIELD_LIMBS+1, a->n, FIELD_LIMBS+1);
-}
-
-static void secp256k1_fe_reduce(secp256k1_fe_t *r, mp_limb_t *tmp) {
- /** <A1 A2 A3 A4> <B1 B2 B3 B4>
- * B1 B2 B3 B4
- * + C * A1 A2 A3 A4
- * + A1 A2 A3 A4
- */
-
-#if (GMP_NUMB_BITS >= 33)
- mp_limb_t o = mpn_addmul_1(tmp, tmp+FIELD_LIMBS, FIELD_LIMBS, 0x1000003D1ULL);
-#else
- mp_limb_t o = mpn_addmul_1(tmp, tmp+FIELD_LIMBS, FIELD_LIMBS, 0x3D1UL) +
- mpn_addmul_1(tmp+(32/GMP_NUMB_BITS), tmp+FIELD_LIMBS, FIELD_LIMBS-(32/GMP_NUMB_BITS), 0x1UL << (32%GMP_NUMB_BITS));
-#endif
- mp_limb_t q[1+(33+GMP_NUMB_BITS-1)/GMP_NUMB_BITS];
- q[(33+GMP_NUMB_BITS-1)/GMP_NUMB_BITS] = mpn_mul_1(q, secp256k1_field_pc, (33+GMP_NUMB_BITS-1)/GMP_NUMB_BITS, o);
-#if (GMP_NUMB_BITS <= 32)
- mp_limb_t o2 = tmp[2*FIELD_LIMBS-(32/GMP_NUMB_BITS)] << (32%GMP_NUMB_BITS);
- q[(33+GMP_NUMB_BITS-1)/GMP_NUMB_BITS] += mpn_addmul_1(q, secp256k1_field_pc, (33+GMP_NUMB_BITS-1)/GMP_NUMB_BITS, o2);
-#endif
- r->n[FIELD_LIMBS] = mpn_add(r->n, tmp, FIELD_LIMBS, q, 1+(33+GMP_NUMB_BITS-1)/GMP_NUMB_BITS);
-}
-
-static void secp256k1_fe_mul(secp256k1_fe_t *r, const secp256k1_fe_t *a, const secp256k1_fe_t * SECP256K1_RESTRICT b) {
- VERIFY_CHECK(r != b);
- secp256k1_fe_t ac = *a;
- secp256k1_fe_t bc = *b;
- secp256k1_fe_normalize(&ac);
- secp256k1_fe_normalize(&bc);
- mp_limb_t tmp[2*FIELD_LIMBS];
- mpn_mul_n(tmp, ac.n, bc.n, FIELD_LIMBS);
- secp256k1_fe_reduce(r, tmp);
-}
-
-static void secp256k1_fe_sqr(secp256k1_fe_t *r, const secp256k1_fe_t *a) {
- secp256k1_fe_t ac = *a;
- secp256k1_fe_normalize(&ac);
- mp_limb_t tmp[2*FIELD_LIMBS];
- mpn_sqr(tmp, ac.n, FIELD_LIMBS);
- secp256k1_fe_reduce(r, tmp);
-}
-
-static void secp256k1_fe_cmov(secp256k1_fe_t *r, const secp256k1_fe_t *a, int flag) {
- mp_limb_t mask0 = flag + ~((mp_limb_t)0), mask1 = ~mask0;
- for (int i = 0; i <= FIELD_LIMBS; i++) {
- r->n[i] = (r->n[i] & mask0) | (a->n[i] & mask1);
- }
-}
-
-#endif
diff --git a/src/secp256k1/src/field_impl.h b/src/secp256k1/src/field_impl.h
index 24d3104ed1..4e2c24aa15 100644
--- a/src/secp256k1/src/field_impl.h
+++ b/src/secp256k1/src/field_impl.h
@@ -13,9 +13,7 @@
#include "util.h"
-#if defined(USE_FIELD_GMP)
-#include "field_gmp_impl.h"
-#elif defined(USE_FIELD_10X26)
+#if defined(USE_FIELD_10X26)
#include "field_10x26_impl.h"
#elif defined(USE_FIELD_5X52)
#include "field_5x52_impl.h"
@@ -66,6 +64,13 @@ static int secp256k1_fe_set_hex(secp256k1_fe_t *r, const char *a, int alen) {
return secp256k1_fe_set_b32(r, tmp);
}
+SECP256K1_INLINE static int secp256k1_fe_equal_var(const secp256k1_fe_t *a, const secp256k1_fe_t *b) {
+ secp256k1_fe_t na;
+ secp256k1_fe_negate(&na, a, 1);
+ secp256k1_fe_add(&na, b);
+ return secp256k1_fe_normalizes_to_zero_var(&na);
+}
+
static int secp256k1_fe_sqrt_var(secp256k1_fe_t *r, const secp256k1_fe_t *a) {
/** The binary representation of (p + 1)/4 has 3 blocks of 1s, with lengths in
@@ -130,10 +135,7 @@ static int secp256k1_fe_sqrt_var(secp256k1_fe_t *r, const secp256k1_fe_t *a) {
/* Check that a square root was actually calculated */
secp256k1_fe_sqr(&t1, r);
- secp256k1_fe_negate(&t1, &t1, 1);
- secp256k1_fe_add(&t1, a);
- secp256k1_fe_normalize_var(&t1);
- return secp256k1_fe_is_zero(&t1);
+ return secp256k1_fe_equal_var(&t1, a);
}
static void secp256k1_fe_inv(secp256k1_fe_t *r, const secp256k1_fe_t *a) {
diff --git a/src/secp256k1/src/group.h b/src/secp256k1/src/group.h
index ecfebcdc0c..6dea6bb5ac 100644
--- a/src/secp256k1/src/group.h
+++ b/src/secp256k1/src/group.h
@@ -60,7 +60,6 @@ static int secp256k1_ge_is_infinity(const secp256k1_ge_t *a);
static int secp256k1_ge_is_valid_var(const secp256k1_ge_t *a);
static void secp256k1_ge_neg(secp256k1_ge_t *r, const secp256k1_ge_t *a);
-static void secp256k1_ge_neg_var(secp256k1_ge_t *r, const secp256k1_ge_t *a);
/** Get a hex representation of a point. *rlen will be overwritten with the real length. */
static void secp256k1_ge_get_hex(char *r, int *rlen, const secp256k1_ge_t *a);
@@ -81,11 +80,11 @@ static void secp256k1_gej_set_xy(secp256k1_gej_t *r, const secp256k1_fe_t *x, co
/** Set a group element (jacobian) equal to another which is given in affine coordinates. */
static void secp256k1_gej_set_ge(secp256k1_gej_t *r, const secp256k1_ge_t *a);
-/** Get the X coordinate of a group element (jacobian). */
-static void secp256k1_gej_get_x_var(secp256k1_fe_t *r, const secp256k1_gej_t *a);
+/** Compare the X coordinate of a group element (jacobian). */
+static int secp256k1_gej_eq_x_var(const secp256k1_fe_t *x, const secp256k1_gej_t *a);
/** Set r equal to the inverse of a (i.e., mirrored around the X axis) */
-static void secp256k1_gej_neg_var(secp256k1_gej_t *r, const secp256k1_gej_t *a);
+static void secp256k1_gej_neg(secp256k1_gej_t *r, const secp256k1_gej_t *a);
/** Check whether a group element is the point at infinity. */
static int secp256k1_gej_is_infinity(const secp256k1_gej_t *a);
diff --git a/src/secp256k1/src/group_impl.h b/src/secp256k1/src/group_impl.h
index 1ab5d5fe7b..fef06df289 100644
--- a/src/secp256k1/src/group_impl.h
+++ b/src/secp256k1/src/group_impl.h
@@ -29,13 +29,7 @@ static int secp256k1_ge_is_infinity(const secp256k1_ge_t *a) {
static void secp256k1_ge_neg(secp256k1_ge_t *r, const secp256k1_ge_t *a) {
*r = *a;
- secp256k1_fe_normalize(&r->y);
- secp256k1_fe_negate(&r->y, &r->y, 1);
-}
-
-static void secp256k1_ge_neg_var(secp256k1_ge_t *r, const secp256k1_ge_t *a) {
- *r = *a;
- secp256k1_fe_normalize_var(&r->y);
+ secp256k1_fe_normalize_weak(&r->y);
secp256k1_fe_negate(&r->y, &r->y, 1);
}
@@ -163,17 +157,19 @@ static void secp256k1_gej_set_ge(secp256k1_gej_t *r, const secp256k1_ge_t *a) {
secp256k1_fe_set_int(&r->z, 1);
}
-static void secp256k1_gej_get_x_var(secp256k1_fe_t *r, const secp256k1_gej_t *a) {
- secp256k1_fe_t zi2; secp256k1_fe_inv_var(&zi2, &a->z); secp256k1_fe_sqr(&zi2, &zi2);
- secp256k1_fe_mul(r, &a->x, &zi2);
+static int secp256k1_gej_eq_x_var(const secp256k1_fe_t *x, const secp256k1_gej_t *a) {
+ VERIFY_CHECK(!a->infinity);
+ secp256k1_fe_t r; secp256k1_fe_sqr(&r, &a->z); secp256k1_fe_mul(&r, &r, x);
+ secp256k1_fe_t r2 = a->x; secp256k1_fe_normalize_weak(&r2);
+ return secp256k1_fe_equal_var(&r, &r2);
}
-static void secp256k1_gej_neg_var(secp256k1_gej_t *r, const secp256k1_gej_t *a) {
+static void secp256k1_gej_neg(secp256k1_gej_t *r, const secp256k1_gej_t *a) {
r->infinity = a->infinity;
r->x = a->x;
r->y = a->y;
r->z = a->z;
- secp256k1_fe_normalize_var(&r->y);
+ secp256k1_fe_normalize_weak(&r->y);
secp256k1_fe_negate(&r->y, &r->y, 1);
}
@@ -195,9 +191,8 @@ static int secp256k1_gej_is_valid_var(const secp256k1_gej_t *a) {
secp256k1_fe_t z6; secp256k1_fe_sqr(&z6, &z2); secp256k1_fe_mul(&z6, &z6, &z2);
secp256k1_fe_mul_int(&z6, 7);
secp256k1_fe_add(&x3, &z6);
- secp256k1_fe_normalize_var(&y2);
- secp256k1_fe_normalize_var(&x3);
- return secp256k1_fe_equal(&y2, &x3);
+ secp256k1_fe_normalize_weak(&x3);
+ return secp256k1_fe_equal_var(&y2, &x3);
}
static int secp256k1_ge_is_valid_var(const secp256k1_ge_t *a) {
@@ -208,9 +203,8 @@ static int secp256k1_ge_is_valid_var(const secp256k1_ge_t *a) {
secp256k1_fe_t x3; secp256k1_fe_sqr(&x3, &a->x); secp256k1_fe_mul(&x3, &x3, &a->x);
secp256k1_fe_t c; secp256k1_fe_set_int(&c, 7);
secp256k1_fe_add(&x3, &c);
- secp256k1_fe_normalize_var(&y2);
- secp256k1_fe_normalize_var(&x3);
- return secp256k1_fe_equal(&y2, &x3);
+ secp256k1_fe_normalize_weak(&x3);
+ return secp256k1_fe_equal_var(&y2, &x3);
}
static void secp256k1_gej_double_var(secp256k1_gej_t *r, const secp256k1_gej_t *a) {
@@ -261,20 +255,16 @@ static void secp256k1_gej_add_var(secp256k1_gej_t *r, const secp256k1_gej_t *a,
secp256k1_fe_t u2; secp256k1_fe_mul(&u2, &b->x, &z12);
secp256k1_fe_t s1; secp256k1_fe_mul(&s1, &a->y, &z22); secp256k1_fe_mul(&s1, &s1, &b->z);
secp256k1_fe_t s2; secp256k1_fe_mul(&s2, &b->y, &z12); secp256k1_fe_mul(&s2, &s2, &a->z);
- secp256k1_fe_normalize_var(&u1);
- secp256k1_fe_normalize_var(&u2);
- if (secp256k1_fe_equal(&u1, &u2)) {
- secp256k1_fe_normalize_var(&s1);
- secp256k1_fe_normalize_var(&s2);
- if (secp256k1_fe_equal(&s1, &s2)) {
+ secp256k1_fe_t h; secp256k1_fe_negate(&h, &u1, 1); secp256k1_fe_add(&h, &u2);
+ secp256k1_fe_t i; secp256k1_fe_negate(&i, &s1, 1); secp256k1_fe_add(&i, &s2);
+ if (secp256k1_fe_normalizes_to_zero_var(&h)) {
+ if (secp256k1_fe_normalizes_to_zero_var(&i)) {
secp256k1_gej_double_var(r, a);
} else {
r->infinity = 1;
}
return;
}
- secp256k1_fe_t h; secp256k1_fe_negate(&h, &u1, 1); secp256k1_fe_add(&h, &u2);
- secp256k1_fe_t i; secp256k1_fe_negate(&i, &s1, 1); secp256k1_fe_add(&i, &s2);
secp256k1_fe_t i2; secp256k1_fe_sqr(&i2, &i);
secp256k1_fe_t h2; secp256k1_fe_sqr(&h2, &h);
secp256k1_fe_t h3; secp256k1_fe_mul(&h3, &h, &h2);
@@ -300,23 +290,20 @@ static void secp256k1_gej_add_ge_var(secp256k1_gej_t *r, const secp256k1_gej_t *
}
r->infinity = 0;
secp256k1_fe_t z12; secp256k1_fe_sqr(&z12, &a->z);
- secp256k1_fe_t u1 = a->x;
+ secp256k1_fe_t u1 = a->x; secp256k1_fe_normalize_weak(&u1);
secp256k1_fe_t u2; secp256k1_fe_mul(&u2, &b->x, &z12);
- secp256k1_fe_t s1 = a->y; secp256k1_fe_normalize_var(&s1);
+ secp256k1_fe_t s1 = a->y; secp256k1_fe_normalize_weak(&s1);
secp256k1_fe_t s2; secp256k1_fe_mul(&s2, &b->y, &z12); secp256k1_fe_mul(&s2, &s2, &a->z);
- secp256k1_fe_normalize_var(&u1);
- secp256k1_fe_normalize_var(&u2);
- if (secp256k1_fe_equal(&u1, &u2)) {
- secp256k1_fe_normalize_var(&s2);
- if (secp256k1_fe_equal(&s1, &s2)) {
+ secp256k1_fe_t h; secp256k1_fe_negate(&h, &u1, 1); secp256k1_fe_add(&h, &u2);
+ secp256k1_fe_t i; secp256k1_fe_negate(&i, &s1, 1); secp256k1_fe_add(&i, &s2);
+ if (secp256k1_fe_normalizes_to_zero_var(&h)) {
+ if (secp256k1_fe_normalizes_to_zero_var(&i)) {
secp256k1_gej_double_var(r, a);
} else {
r->infinity = 1;
}
return;
}
- secp256k1_fe_t h; secp256k1_fe_negate(&h, &u1, 1); secp256k1_fe_add(&h, &u2);
- secp256k1_fe_t i; secp256k1_fe_negate(&i, &s1, 1); secp256k1_fe_add(&i, &s2);
secp256k1_fe_t i2; secp256k1_fe_sqr(&i2, &i);
secp256k1_fe_t h2; secp256k1_fe_sqr(&h2, &h);
secp256k1_fe_t h3; secp256k1_fe_mul(&h3, &h, &h2);
@@ -355,9 +342,9 @@ static void secp256k1_gej_add_ge(secp256k1_gej_t *r, const secp256k1_gej_t *a, c
*/
secp256k1_fe_t zz; secp256k1_fe_sqr(&zz, &a->z); /* z = Z1^2 */
- secp256k1_fe_t u1 = a->x; secp256k1_fe_normalize(&u1); /* u1 = U1 = X1*Z2^2 (1) */
+ secp256k1_fe_t u1 = a->x; secp256k1_fe_normalize_weak(&u1); /* u1 = U1 = X1*Z2^2 (1) */
secp256k1_fe_t u2; secp256k1_fe_mul(&u2, &b->x, &zz); /* u2 = U2 = X2*Z1^2 (1) */
- secp256k1_fe_t s1 = a->y; secp256k1_fe_normalize(&s1); /* s1 = S1 = Y1*Z2^3 (1) */
+ secp256k1_fe_t s1 = a->y; secp256k1_fe_normalize_weak(&s1); /* s1 = S1 = Y1*Z2^3 (1) */
secp256k1_fe_t s2; secp256k1_fe_mul(&s2, &b->y, &zz); /* s2 = Y2*Z2^2 (1) */
secp256k1_fe_mul(&s2, &s2, &a->z); /* s2 = S2 = Y2*Z1^3 (1) */
secp256k1_fe_t z = a->z; /* z = Z = Z1*Z2 (8) */
@@ -371,8 +358,7 @@ static void secp256k1_gej_add_ge(secp256k1_gej_t *r, const secp256k1_gej_t *a, c
secp256k1_fe_add(&rr, &t); /* rr = R = T^2-U1*U2 (3) */
secp256k1_fe_sqr(&t, &rr); /* t = R^2 (1) */
secp256k1_fe_mul(&r->z, &m, &z); /* r->z = M*Z (1) */
- secp256k1_fe_normalize(&r->z);
- int infinity = secp256k1_fe_is_zero(&r->z) * (1 - a->infinity);
+ int infinity = secp256k1_fe_normalizes_to_zero(&r->z) * (1 - a->infinity);
secp256k1_fe_mul_int(&r->z, 2 * (1 - a->infinity)); /* r->z = Z3 = 2*M*Z (2) */
r->x = t; /* r->x = R^2 (1) */
secp256k1_fe_negate(&q, &q, 1); /* q = -Q (2) */
@@ -384,7 +370,7 @@ static void secp256k1_gej_add_ge(secp256k1_gej_t *r, const secp256k1_gej_t *a, c
secp256k1_fe_mul(&t, &t, &rr); /* t = R*(2*R^2-3*Q) (1) */
secp256k1_fe_add(&t, &n); /* t = R*(2*R^2-3*Q)+M^4 (2) */
secp256k1_fe_negate(&r->y, &t, 2); /* r->y = R*(3*Q-2*R^2)-M^4 (3) */
- secp256k1_fe_normalize(&r->y);
+ secp256k1_fe_normalize_weak(&r->y);
secp256k1_fe_mul_int(&r->x, 4 * (1 - a->infinity)); /* r->x = X3 = 4*(R^2-Q) */
secp256k1_fe_mul_int(&r->y, 4 * (1 - a->infinity)); /* r->y = Y3 = 4*R*(3*Q-2*R^2)-4*M^4 (4) */
diff --git a/src/secp256k1/src/hash.h b/src/secp256k1/src/hash.h
new file mode 100644
index 0000000000..d1e65b968a
--- /dev/null
+++ b/src/secp256k1/src/hash.h
@@ -0,0 +1,41 @@
+/**********************************************************************
+ * Copyright (c) 2014 Pieter Wuille *
+ * Distributed under the MIT software license, see the accompanying *
+ * file COPYING or http://www.opensource.org/licenses/mit-license.php.*
+ **********************************************************************/
+
+#ifndef _SECP256K1_HASH_
+#define _SECP256K1_HASH_
+
+#include <stdlib.h>
+#include <stdint.h>
+
+typedef struct {
+ uint32_t s[32];
+ unsigned char buf[64];
+ size_t bytes;
+} secp256k1_sha256_t;
+
+static void secp256k1_sha256_initialize(secp256k1_sha256_t *hash);
+static void secp256k1_sha256_write(secp256k1_sha256_t *hash, const unsigned char *data, size_t size);
+static void secp256k1_sha256_finalize(secp256k1_sha256_t *hash, unsigned char *out32);
+
+typedef struct {
+ secp256k1_sha256_t inner, outer;
+} secp256k1_hmac_sha256_t;
+
+static void secp256k1_hmac_sha256_initialize(secp256k1_hmac_sha256_t *hash, const unsigned char *key, size_t size);
+static void secp256k1_hmac_sha256_write(secp256k1_hmac_sha256_t *hash, const unsigned char *data, size_t size);
+static void secp256k1_hmac_sha256_finalize(secp256k1_hmac_sha256_t *hash, unsigned char *out32);
+
+typedef struct {
+ unsigned char v[32];
+ unsigned char k[32];
+ int retry;
+} secp256k1_rfc6979_hmac_sha256_t;
+
+static void secp256k1_rfc6979_hmac_sha256_initialize(secp256k1_rfc6979_hmac_sha256_t *rng, const unsigned char *key, size_t keylen, const unsigned char *msg, size_t msglen);
+static void secp256k1_rfc6979_hmac_sha256_generate(secp256k1_rfc6979_hmac_sha256_t *rng, unsigned char *out, size_t outlen);
+static void secp256k1_rfc6979_hmac_sha256_finalize(secp256k1_rfc6979_hmac_sha256_t *rng);
+
+#endif
diff --git a/src/secp256k1/src/hash_impl.h b/src/secp256k1/src/hash_impl.h
new file mode 100644
index 0000000000..f35c5f7a82
--- /dev/null
+++ b/src/secp256k1/src/hash_impl.h
@@ -0,0 +1,291 @@
+/**********************************************************************
+ * Copyright (c) 2014 Pieter Wuille *
+ * Distributed under the MIT software license, see the accompanying *
+ * file COPYING or http://www.opensource.org/licenses/mit-license.php.*
+ **********************************************************************/
+
+#ifndef _SECP256K1_HASH_IMPL_H_
+#define _SECP256K1_HASH_IMPL_H_
+
+#include "hash.h"
+
+#include <stdlib.h>
+#include <stdint.h>
+
+#define Ch(x,y,z) ((z) ^ ((x) & ((y) ^ (z))))
+#define Maj(x,y,z) (((x) & (y)) | ((z) & ((x) | (y))))
+#define Sigma0(x) (((x) >> 2 | (x) << 30) ^ ((x) >> 13 | (x) << 19) ^ ((x) >> 22 | (x) << 10))
+#define Sigma1(x) (((x) >> 6 | (x) << 26) ^ ((x) >> 11 | (x) << 21) ^ ((x) >> 25 | (x) << 7))
+#define sigma0(x) (((x) >> 7 | (x) << 25) ^ ((x) >> 18 | (x) << 14) ^ ((x) >> 3))
+#define sigma1(x) (((x) >> 17 | (x) << 15) ^ ((x) >> 19 | (x) << 13) ^ ((x) >> 10))
+
+#define Round(a,b,c,d,e,f,g,h,k,w) do { \
+ uint32_t t1 = (h) + Sigma1(e) + Ch((e), (f), (g)) + (k) + (w); \
+ uint32_t t2 = Sigma0(a) + Maj((a), (b), (c)); \
+ (d) += t1; \
+ (h) = t1 + t2; \
+} while(0)
+
+#define ReadBE32(p) (((uint32_t)((p)[0])) << 24 | ((uint32_t)((p)[1])) << 16 | ((uint32_t)((p)[2])) << 8 | ((uint32_t)((p)[3])))
+#define WriteBE32(p, v) do { (p)[0] = (v) >> 24; (p)[1] = (v) >> 16; (p)[2] = (v) >> 8; (p)[3] = (v); } while(0)
+
+static void secp256k1_sha256_initialize(secp256k1_sha256_t *hash) {
+ hash->s[0] = 0x6a09e667ul;
+ hash->s[1] = 0xbb67ae85ul;
+ hash->s[2] = 0x3c6ef372ul;
+ hash->s[3] = 0xa54ff53aul;
+ hash->s[4] = 0x510e527ful;
+ hash->s[5] = 0x9b05688cul;
+ hash->s[6] = 0x1f83d9abul;
+ hash->s[7] = 0x5be0cd19ul;
+ hash->bytes = 0;
+}
+
+/** Perform one SHA-256 transformation, processing a 64-byte chunk. */
+static void secp256k1_sha256_transform(uint32_t* s, const unsigned char* chunk) {
+ uint32_t a = s[0], b = s[1], c = s[2], d = s[3], e = s[4], f = s[5], g = s[6], h = s[7];
+ uint32_t w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15;
+
+ Round(a, b, c, d, e, f, g, h, 0x428a2f98, w0 = ReadBE32(chunk + 0));
+ Round(h, a, b, c, d, e, f, g, 0x71374491, w1 = ReadBE32(chunk + 4));
+ Round(g, h, a, b, c, d, e, f, 0xb5c0fbcf, w2 = ReadBE32(chunk + 8));
+ Round(f, g, h, a, b, c, d, e, 0xe9b5dba5, w3 = ReadBE32(chunk + 12));
+ Round(e, f, g, h, a, b, c, d, 0x3956c25b, w4 = ReadBE32(chunk + 16));
+ Round(d, e, f, g, h, a, b, c, 0x59f111f1, w5 = ReadBE32(chunk + 20));
+ Round(c, d, e, f, g, h, a, b, 0x923f82a4, w6 = ReadBE32(chunk + 24));
+ Round(b, c, d, e, f, g, h, a, 0xab1c5ed5, w7 = ReadBE32(chunk + 28));
+ Round(a, b, c, d, e, f, g, h, 0xd807aa98, w8 = ReadBE32(chunk + 32));
+ Round(h, a, b, c, d, e, f, g, 0x12835b01, w9 = ReadBE32(chunk + 36));
+ Round(g, h, a, b, c, d, e, f, 0x243185be, w10 = ReadBE32(chunk + 40));
+ Round(f, g, h, a, b, c, d, e, 0x550c7dc3, w11 = ReadBE32(chunk + 44));
+ Round(e, f, g, h, a, b, c, d, 0x72be5d74, w12 = ReadBE32(chunk + 48));
+ Round(d, e, f, g, h, a, b, c, 0x80deb1fe, w13 = ReadBE32(chunk + 52));
+ Round(c, d, e, f, g, h, a, b, 0x9bdc06a7, w14 = ReadBE32(chunk + 56));
+ Round(b, c, d, e, f, g, h, a, 0xc19bf174, w15 = ReadBE32(chunk + 60));
+
+ Round(a, b, c, d, e, f, g, h, 0xe49b69c1, w0 += sigma1(w14) + w9 + sigma0(w1));
+ Round(h, a, b, c, d, e, f, g, 0xefbe4786, w1 += sigma1(w15) + w10 + sigma0(w2));
+ Round(g, h, a, b, c, d, e, f, 0x0fc19dc6, w2 += sigma1(w0) + w11 + sigma0(w3));
+ Round(f, g, h, a, b, c, d, e, 0x240ca1cc, w3 += sigma1(w1) + w12 + sigma0(w4));
+ Round(e, f, g, h, a, b, c, d, 0x2de92c6f, w4 += sigma1(w2) + w13 + sigma0(w5));
+ Round(d, e, f, g, h, a, b, c, 0x4a7484aa, w5 += sigma1(w3) + w14 + sigma0(w6));
+ Round(c, d, e, f, g, h, a, b, 0x5cb0a9dc, w6 += sigma1(w4) + w15 + sigma0(w7));
+ Round(b, c, d, e, f, g, h, a, 0x76f988da, w7 += sigma1(w5) + w0 + sigma0(w8));
+ Round(a, b, c, d, e, f, g, h, 0x983e5152, w8 += sigma1(w6) + w1 + sigma0(w9));
+ Round(h, a, b, c, d, e, f, g, 0xa831c66d, w9 += sigma1(w7) + w2 + sigma0(w10));
+ Round(g, h, a, b, c, d, e, f, 0xb00327c8, w10 += sigma1(w8) + w3 + sigma0(w11));
+ Round(f, g, h, a, b, c, d, e, 0xbf597fc7, w11 += sigma1(w9) + w4 + sigma0(w12));
+ Round(e, f, g, h, a, b, c, d, 0xc6e00bf3, w12 += sigma1(w10) + w5 + sigma0(w13));
+ Round(d, e, f, g, h, a, b, c, 0xd5a79147, w13 += sigma1(w11) + w6 + sigma0(w14));
+ Round(c, d, e, f, g, h, a, b, 0x06ca6351, w14 += sigma1(w12) + w7 + sigma0(w15));
+ Round(b, c, d, e, f, g, h, a, 0x14292967, w15 += sigma1(w13) + w8 + sigma0(w0));
+
+ Round(a, b, c, d, e, f, g, h, 0x27b70a85, w0 += sigma1(w14) + w9 + sigma0(w1));
+ Round(h, a, b, c, d, e, f, g, 0x2e1b2138, w1 += sigma1(w15) + w10 + sigma0(w2));
+ Round(g, h, a, b, c, d, e, f, 0x4d2c6dfc, w2 += sigma1(w0) + w11 + sigma0(w3));
+ Round(f, g, h, a, b, c, d, e, 0x53380d13, w3 += sigma1(w1) + w12 + sigma0(w4));
+ Round(e, f, g, h, a, b, c, d, 0x650a7354, w4 += sigma1(w2) + w13 + sigma0(w5));
+ Round(d, e, f, g, h, a, b, c, 0x766a0abb, w5 += sigma1(w3) + w14 + sigma0(w6));
+ Round(c, d, e, f, g, h, a, b, 0x81c2c92e, w6 += sigma1(w4) + w15 + sigma0(w7));
+ Round(b, c, d, e, f, g, h, a, 0x92722c85, w7 += sigma1(w5) + w0 + sigma0(w8));
+ Round(a, b, c, d, e, f, g, h, 0xa2bfe8a1, w8 += sigma1(w6) + w1 + sigma0(w9));
+ Round(h, a, b, c, d, e, f, g, 0xa81a664b, w9 += sigma1(w7) + w2 + sigma0(w10));
+ Round(g, h, a, b, c, d, e, f, 0xc24b8b70, w10 += sigma1(w8) + w3 + sigma0(w11));
+ Round(f, g, h, a, b, c, d, e, 0xc76c51a3, w11 += sigma1(w9) + w4 + sigma0(w12));
+ Round(e, f, g, h, a, b, c, d, 0xd192e819, w12 += sigma1(w10) + w5 + sigma0(w13));
+ Round(d, e, f, g, h, a, b, c, 0xd6990624, w13 += sigma1(w11) + w6 + sigma0(w14));
+ Round(c, d, e, f, g, h, a, b, 0xf40e3585, w14 += sigma1(w12) + w7 + sigma0(w15));
+ Round(b, c, d, e, f, g, h, a, 0x106aa070, w15 += sigma1(w13) + w8 + sigma0(w0));
+
+ Round(a, b, c, d, e, f, g, h, 0x19a4c116, w0 += sigma1(w14) + w9 + sigma0(w1));
+ Round(h, a, b, c, d, e, f, g, 0x1e376c08, w1 += sigma1(w15) + w10 + sigma0(w2));
+ Round(g, h, a, b, c, d, e, f, 0x2748774c, w2 += sigma1(w0) + w11 + sigma0(w3));
+ Round(f, g, h, a, b, c, d, e, 0x34b0bcb5, w3 += sigma1(w1) + w12 + sigma0(w4));
+ Round(e, f, g, h, a, b, c, d, 0x391c0cb3, w4 += sigma1(w2) + w13 + sigma0(w5));
+ Round(d, e, f, g, h, a, b, c, 0x4ed8aa4a, w5 += sigma1(w3) + w14 + sigma0(w6));
+ Round(c, d, e, f, g, h, a, b, 0x5b9cca4f, w6 += sigma1(w4) + w15 + sigma0(w7));
+ Round(b, c, d, e, f, g, h, a, 0x682e6ff3, w7 += sigma1(w5) + w0 + sigma0(w8));
+ Round(a, b, c, d, e, f, g, h, 0x748f82ee, w8 += sigma1(w6) + w1 + sigma0(w9));
+ Round(h, a, b, c, d, e, f, g, 0x78a5636f, w9 += sigma1(w7) + w2 + sigma0(w10));
+ Round(g, h, a, b, c, d, e, f, 0x84c87814, w10 += sigma1(w8) + w3 + sigma0(w11));
+ Round(f, g, h, a, b, c, d, e, 0x8cc70208, w11 += sigma1(w9) + w4 + sigma0(w12));
+ Round(e, f, g, h, a, b, c, d, 0x90befffa, w12 += sigma1(w10) + w5 + sigma0(w13));
+ Round(d, e, f, g, h, a, b, c, 0xa4506ceb, w13 += sigma1(w11) + w6 + sigma0(w14));
+ Round(c, d, e, f, g, h, a, b, 0xbef9a3f7, w14 + sigma1(w12) + w7 + sigma0(w15));
+ Round(b, c, d, e, f, g, h, a, 0xc67178f2, w15 + sigma1(w13) + w8 + sigma0(w0));
+
+ s[0] += a;
+ s[1] += b;
+ s[2] += c;
+ s[3] += d;
+ s[4] += e;
+ s[5] += f;
+ s[6] += g;
+ s[7] += h;
+}
+
+static void secp256k1_sha256_write(secp256k1_sha256_t *hash, const unsigned char *data, size_t len) {
+ const unsigned char* end = data + len;
+ size_t bufsize = hash->bytes % 64;
+ if (bufsize && bufsize + len >= 64) {
+ // Fill the buffer, and process it.
+ memcpy(hash->buf + bufsize, data, 64 - bufsize);
+ hash->bytes += 64 - bufsize;
+ data += 64 - bufsize;
+ secp256k1_sha256_transform(hash->s, hash->buf);
+ bufsize = 0;
+ }
+ while (end >= data + 64) {
+ // Process full chunks directly from the source.
+ secp256k1_sha256_transform(hash->s, data);
+ hash->bytes += 64;
+ data += 64;
+ }
+ if (end > data) {
+ // Fill the buffer with what remains.
+ memcpy(hash->buf + bufsize, data, end - data);
+ hash->bytes += end - data;
+ }
+}
+
+static void secp256k1_sha256_finalize(secp256k1_sha256_t *hash, unsigned char *out32) {
+ static const unsigned char pad[64] = {0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ unsigned char sizedesc[8];
+ WriteBE32(sizedesc, hash->bytes >> 29);
+ WriteBE32(sizedesc + 4, hash->bytes << 3);
+ secp256k1_sha256_write(hash, pad, 1 + ((119 - (hash->bytes % 64)) % 64));
+ secp256k1_sha256_write(hash, sizedesc, 8);
+ WriteBE32(out32, hash->s[0]);
+ hash->s[0] = 0;
+ WriteBE32(out32 + 4, hash->s[1]);
+ hash->s[1] = 0;
+ WriteBE32(out32 + 8, hash->s[2]);
+ hash->s[2] = 0;
+ WriteBE32(out32 + 12, hash->s[3]);
+ hash->s[3] = 0;
+ WriteBE32(out32 + 16, hash->s[4]);
+ hash->s[4] = 0;
+ WriteBE32(out32 + 20, hash->s[5]);
+ hash->s[5] = 0;
+ WriteBE32(out32 + 24, hash->s[6]);
+ hash->s[6] = 0;
+ WriteBE32(out32 + 28, hash->s[7]);
+ hash->s[7] = 0;
+}
+
+static void secp256k1_hmac_sha256_initialize(secp256k1_hmac_sha256_t *hash, const unsigned char *key, size_t keylen) {
+ unsigned char rkey[64];
+ if (keylen <= 64) {
+ memcpy(rkey, key, keylen);
+ memset(rkey + keylen, 0, 64 - keylen);
+ } else {
+ secp256k1_sha256_t sha256;
+ secp256k1_sha256_initialize(&sha256);
+ secp256k1_sha256_write(&sha256, key, keylen);
+ secp256k1_sha256_finalize(&sha256, rkey);
+ memset(rkey + 32, 0, 32);
+ }
+
+ secp256k1_sha256_initialize(&hash->outer);
+ for (int n = 0; n < 64; n++)
+ rkey[n] ^= 0x5c;
+ secp256k1_sha256_write(&hash->outer, rkey, 64);
+
+ secp256k1_sha256_initialize(&hash->inner);
+ for (int n = 0; n < 64; n++)
+ rkey[n] ^= 0x5c ^ 0x36;
+ secp256k1_sha256_write(&hash->inner, rkey, 64);
+ memset(rkey, 0, 64);
+}
+
+static void secp256k1_hmac_sha256_write(secp256k1_hmac_sha256_t *hash, const unsigned char *data, size_t size) {
+ secp256k1_sha256_write(&hash->inner, data, size);
+}
+
+static void secp256k1_hmac_sha256_finalize(secp256k1_hmac_sha256_t *hash, unsigned char *out32) {
+ unsigned char temp[32];
+ secp256k1_sha256_finalize(&hash->inner, temp);
+ secp256k1_sha256_write(&hash->outer, temp, 32);
+ memset(temp, 0, 32);
+ secp256k1_sha256_finalize(&hash->outer, out32);
+}
+
+
+static void secp256k1_rfc6979_hmac_sha256_initialize(secp256k1_rfc6979_hmac_sha256_t *rng, const unsigned char *key, size_t keylen, const unsigned char *msg, size_t msglen) {
+ static const unsigned char zero[1] = {0x00};
+ static const unsigned char one[1] = {0x01};
+
+ memset(rng->v, 0x01, 32);
+ memset(rng->k, 0x00, 32);
+
+ secp256k1_hmac_sha256_t hmac;
+ secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32);
+ secp256k1_hmac_sha256_write(&hmac, rng->v, 32);
+ secp256k1_hmac_sha256_write(&hmac, zero, 1);
+ secp256k1_hmac_sha256_write(&hmac, key, keylen);
+ secp256k1_hmac_sha256_write(&hmac, msg, msglen);
+ secp256k1_hmac_sha256_finalize(&hmac, rng->k);
+ secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32);
+ secp256k1_hmac_sha256_write(&hmac, rng->v, 32);
+ secp256k1_hmac_sha256_finalize(&hmac, rng->v);
+
+ secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32);
+ secp256k1_hmac_sha256_write(&hmac, rng->v, 32);
+ secp256k1_hmac_sha256_write(&hmac, one, 1);
+ secp256k1_hmac_sha256_write(&hmac, key, keylen);
+ secp256k1_hmac_sha256_write(&hmac, msg, msglen);
+ secp256k1_hmac_sha256_finalize(&hmac, rng->k);
+ secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32);
+ secp256k1_hmac_sha256_write(&hmac, rng->v, 32);
+ secp256k1_hmac_sha256_finalize(&hmac, rng->v);
+ rng->retry = 0;
+}
+
+static void secp256k1_rfc6979_hmac_sha256_generate(secp256k1_rfc6979_hmac_sha256_t *rng, unsigned char *out, size_t outlen) {
+ static const unsigned char zero[1] = {0x00};
+ if (rng->retry) {
+ secp256k1_hmac_sha256_t hmac;
+ secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32);
+ secp256k1_hmac_sha256_write(&hmac, rng->v, 32);
+ secp256k1_hmac_sha256_write(&hmac, zero, 1);
+ secp256k1_hmac_sha256_finalize(&hmac, rng->k);
+ secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32);
+ secp256k1_hmac_sha256_write(&hmac, rng->v, 32);
+ secp256k1_hmac_sha256_finalize(&hmac, rng->v);
+ }
+
+ while (outlen > 0) {
+ secp256k1_hmac_sha256_t hmac;
+ secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32);
+ secp256k1_hmac_sha256_write(&hmac, rng->v, 32);
+ secp256k1_hmac_sha256_finalize(&hmac, rng->v);
+ int now = outlen;
+ if (now > 32) {
+ now = 32;
+ }
+ memcpy(out, rng->v, now);
+ out += now;
+ outlen -= now;
+ }
+
+ rng->retry = 1;
+}
+
+static void secp256k1_rfc6979_hmac_sha256_finalize(secp256k1_rfc6979_hmac_sha256_t *rng) {
+ memset(rng->k, 0, 32);
+ memset(rng->v, 0, 32);
+ rng->retry = 0;
+}
+
+
+#undef Round
+#undef sigma0
+#undef sigma1
+#undef Sigma0
+#undef Sigma1
+#undef Ch
+#undef Maj
+#undef ReadBE32
+#undef WriteBE32
+
+#endif
diff --git a/src/secp256k1/src/secp256k1.c b/src/secp256k1/src/secp256k1.c
index 0328db88fc..58bcd8d009 100644
--- a/src/secp256k1/src/secp256k1.c
+++ b/src/secp256k1/src/secp256k1.c
@@ -17,6 +17,7 @@
#include "ecmult_gen_impl.h"
#include "ecdsa_impl.h"
#include "eckey_impl.h"
+#include "hash_impl.h"
void secp256k1_start(unsigned int flags) {
secp256k1_fe_start();
@@ -69,26 +70,54 @@ end:
return ret;
}
-int secp256k1_ecdsa_sign(const unsigned char *msg32, unsigned char *signature, int *signaturelen, const unsigned char *seckey, const unsigned char *nonce) {
+static int nonce_function_rfc6979(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, unsigned int counter, const void *data) {
+ (void)data;
+ secp256k1_rfc6979_hmac_sha256_t rng;
+ secp256k1_rfc6979_hmac_sha256_initialize(&rng, key32, 32, msg32, 32);
+ for (unsigned int i = 0; i <= counter; i++) {
+ secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32);
+ }
+ secp256k1_rfc6979_hmac_sha256_finalize(&rng);
+ return 1;
+}
+
+const secp256k1_nonce_function_t secp256k1_nonce_function_rfc6979 = nonce_function_rfc6979;
+const secp256k1_nonce_function_t secp256k1_nonce_function_default = nonce_function_rfc6979;
+
+int secp256k1_ecdsa_sign(const unsigned char *msg32, unsigned char *signature, int *signaturelen, const unsigned char *seckey, secp256k1_nonce_function_t noncefp, const void* noncedata) {
DEBUG_CHECK(secp256k1_ecmult_gen_consts != NULL);
DEBUG_CHECK(msg32 != NULL);
DEBUG_CHECK(signature != NULL);
DEBUG_CHECK(signaturelen != NULL);
DEBUG_CHECK(seckey != NULL);
- DEBUG_CHECK(nonce != NULL);
+ if (noncefp == NULL) {
+ noncefp = secp256k1_nonce_function_default;
+ }
secp256k1_scalar_t sec, non, msg;
secp256k1_scalar_set_b32(&sec, seckey, NULL);
- int overflow = 0;
- secp256k1_scalar_set_b32(&non, nonce, &overflow);
secp256k1_scalar_set_b32(&msg, msg32, NULL);
- int ret = !secp256k1_scalar_is_zero(&non) && !overflow;
+ int overflow = 0;
+ int ret = 0;
+ unsigned int count = 0;
secp256k1_ecdsa_sig_t sig;
- if (ret) {
- ret = secp256k1_ecdsa_sig_sign(&sig, &sec, &msg, &non, NULL);
+ while (1) {
+ unsigned char nonce32[32];
+ ret = noncefp(nonce32, msg32, seckey, count, noncedata);
+ if (!ret) {
+ break;
+ }
+ secp256k1_scalar_set_b32(&non, nonce32, &overflow);
+ memset(nonce32, 0, 32);
+ if (!secp256k1_scalar_is_zero(&non) && !overflow) {
+ if (secp256k1_ecdsa_sig_sign(&sig, &sec, &msg, &non, NULL)) {
+ break;
+ }
+ }
+ count++;
}
if (ret) {
- secp256k1_ecdsa_sig_serialize(signature, signaturelen, &sig);
+ ret = secp256k1_ecdsa_sig_serialize(signature, signaturelen, &sig);
}
secp256k1_scalar_clear(&msg);
secp256k1_scalar_clear(&non);
@@ -96,22 +125,36 @@ int secp256k1_ecdsa_sign(const unsigned char *msg32, unsigned char *signature, i
return ret;
}
-int secp256k1_ecdsa_sign_compact(const unsigned char *msg32, unsigned char *sig64, const unsigned char *seckey, const unsigned char *nonce, int *recid) {
+int secp256k1_ecdsa_sign_compact(const unsigned char *msg32, unsigned char *sig64, const unsigned char *seckey, secp256k1_nonce_function_t noncefp, const void* noncedata, int *recid) {
DEBUG_CHECK(secp256k1_ecmult_gen_consts != NULL);
DEBUG_CHECK(msg32 != NULL);
DEBUG_CHECK(sig64 != NULL);
DEBUG_CHECK(seckey != NULL);
- DEBUG_CHECK(nonce != NULL);
+ if (noncefp == NULL) {
+ noncefp = secp256k1_nonce_function_default;
+ }
secp256k1_scalar_t sec, non, msg;
secp256k1_scalar_set_b32(&sec, seckey, NULL);
- int overflow = 0;
- secp256k1_scalar_set_b32(&non, nonce, &overflow);
secp256k1_scalar_set_b32(&msg, msg32, NULL);
- int ret = !secp256k1_scalar_is_zero(&non) && !overflow;
+ int overflow = 0;
+ int ret = 0;
+ unsigned int count = 0;
secp256k1_ecdsa_sig_t sig;
- if (ret) {
- ret = secp256k1_ecdsa_sig_sign(&sig, &sec, &msg, &non, recid);
+ while (1) {
+ unsigned char nonce32[32];
+ ret = noncefp(nonce32, msg32, seckey, count, noncedata);
+ if (!ret) {
+ break;
+ }
+ secp256k1_scalar_set_b32(&non, nonce32, &overflow);
+ memset(nonce32, 0, 32);
+ if (!secp256k1_scalar_is_zero(&non) && !overflow) {
+ if (secp256k1_ecdsa_sig_sign(&sig, &sec, &msg, &non, recid)) {
+ break;
+ }
+ }
+ count++;
}
if (ret) {
secp256k1_scalar_get_b32(sig64, &sig.r);
diff --git a/src/secp256k1/src/tests.c b/src/secp256k1/src/tests.c
index 7ebb19ff99..cff32f1d06 100644
--- a/src/secp256k1/src/tests.c
+++ b/src/secp256k1/src/tests.c
@@ -36,12 +36,19 @@ void random_field_element_test(secp256k1_fe_t *fe) {
}
void random_field_element_magnitude(secp256k1_fe_t *fe) {
+ int n = secp256k1_rand32() % 9;
secp256k1_fe_normalize(fe);
- int n = secp256k1_rand32() % 4;
- for (int i = 0; i < n; i++) {
- secp256k1_fe_negate(fe, fe, 1 + 2*i);
- secp256k1_fe_negate(fe, fe, 2 + 2*i);
+ if (n == 0) {
+ return;
}
+ secp256k1_fe_t zero;
+ secp256k1_fe_clear(&zero);
+ secp256k1_fe_negate(&zero, &zero, 0);
+ secp256k1_fe_mul_int(&zero, n - 1);
+ secp256k1_fe_add(fe, &zero);
+#ifdef VERIFY
+ CHECK(fe->magnitude == n);
+#endif
}
void random_group_element_test(secp256k1_ge_t *ge) {
@@ -91,6 +98,121 @@ void random_scalar_order(secp256k1_scalar_t *num) {
} while(1);
}
+/***** HASH TESTS *****/
+
+void run_sha256_tests(void) {
+ static const char *inputs[8] = {
+ "", "abc", "message digest", "secure hash algorithm", "SHA256 is considered to be safe",
+ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+ "For this sample, this 63-byte string will be used as input data",
+ "This is exactly 64 bytes long, not counting the terminating byte"
+ };
+ static const unsigned char outputs[8][32] = {
+ {0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55},
+ {0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea, 0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23, 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c, 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad},
+ {0xf7, 0x84, 0x6f, 0x55, 0xcf, 0x23, 0xe1, 0x4e, 0xeb, 0xea, 0xb5, 0xb4, 0xe1, 0x55, 0x0c, 0xad, 0x5b, 0x50, 0x9e, 0x33, 0x48, 0xfb, 0xc4, 0xef, 0xa3, 0xa1, 0x41, 0x3d, 0x39, 0x3c, 0xb6, 0x50},
+ {0xf3, 0x0c, 0xeb, 0x2b, 0xb2, 0x82, 0x9e, 0x79, 0xe4, 0xca, 0x97, 0x53, 0xd3, 0x5a, 0x8e, 0xcc, 0x00, 0x26, 0x2d, 0x16, 0x4c, 0xc0, 0x77, 0x08, 0x02, 0x95, 0x38, 0x1c, 0xbd, 0x64, 0x3f, 0x0d},
+ {0x68, 0x19, 0xd9, 0x15, 0xc7, 0x3f, 0x4d, 0x1e, 0x77, 0xe4, 0xe1, 0xb5, 0x2d, 0x1f, 0xa0, 0xf9, 0xcf, 0x9b, 0xea, 0xea, 0xd3, 0x93, 0x9f, 0x15, 0x87, 0x4b, 0xd9, 0x88, 0xe2, 0xa2, 0x36, 0x30},
+ {0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8, 0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39, 0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67, 0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1},
+ {0xf0, 0x8a, 0x78, 0xcb, 0xba, 0xee, 0x08, 0x2b, 0x05, 0x2a, 0xe0, 0x70, 0x8f, 0x32, 0xfa, 0x1e, 0x50, 0xc5, 0xc4, 0x21, 0xaa, 0x77, 0x2b, 0xa5, 0xdb, 0xb4, 0x06, 0xa2, 0xea, 0x6b, 0xe3, 0x42},
+ {0xab, 0x64, 0xef, 0xf7, 0xe8, 0x8e, 0x2e, 0x46, 0x16, 0x5e, 0x29, 0xf2, 0xbc, 0xe4, 0x18, 0x26, 0xbd, 0x4c, 0x7b, 0x35, 0x52, 0xf6, 0xb3, 0x82, 0xa9, 0xe7, 0xd3, 0xaf, 0x47, 0xc2, 0x45, 0xf8}
+ };
+ for (int i = 0; i < 8; i++) {
+ secp256k1_sha256_t hasher;
+ secp256k1_sha256_initialize(&hasher);
+ secp256k1_sha256_write(&hasher, (const unsigned char*)(inputs[i]), strlen(inputs[i]));
+ unsigned char out[32];
+ secp256k1_sha256_finalize(&hasher, out);
+ CHECK(memcmp(out, outputs[i], 32) == 0);
+ if (strlen(inputs[i]) > 0) {
+ secp256k1_sha256_initialize(&hasher);
+ int split = secp256k1_rand32() % strlen(inputs[i]);
+ secp256k1_sha256_write(&hasher, (const unsigned char*)(inputs[i]), split);
+ secp256k1_sha256_write(&hasher, (const unsigned char*)(inputs[i] + split), strlen(inputs[i]) - split);
+ secp256k1_sha256_finalize(&hasher, out);
+ CHECK(memcmp(out, outputs[i], 32) == 0);
+ }
+ }
+}
+
+void run_hmac_sha256_tests(void) {
+ static const char *keys[6] = {
+ "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b",
+ "\x4a\x65\x66\x65",
+ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa",
+ "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19",
+ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa",
+ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+ };
+ static const char *inputs[6] = {
+ "\x48\x69\x20\x54\x68\x65\x72\x65",
+ "\x77\x68\x61\x74\x20\x64\x6f\x20\x79\x61\x20\x77\x61\x6e\x74\x20\x66\x6f\x72\x20\x6e\x6f\x74\x68\x69\x6e\x67\x3f",
+ "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd",
+ "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd",
+ "\x54\x65\x73\x74\x20\x55\x73\x69\x6e\x67\x20\x4c\x61\x72\x67\x65\x72\x20\x54\x68\x61\x6e\x20\x42\x6c\x6f\x63\x6b\x2d\x53\x69\x7a\x65\x20\x4b\x65\x79\x20\x2d\x20\x48\x61\x73\x68\x20\x4b\x65\x79\x20\x46\x69\x72\x73\x74",
+ "\x54\x68\x69\x73\x20\x69\x73\x20\x61\x20\x74\x65\x73\x74\x20\x75\x73\x69\x6e\x67\x20\x61\x20\x6c\x61\x72\x67\x65\x72\x20\x74\x68\x61\x6e\x20\x62\x6c\x6f\x63\x6b\x2d\x73\x69\x7a\x65\x20\x6b\x65\x79\x20\x61\x6e\x64\x20\x61\x20\x6c\x61\x72\x67\x65\x72\x20\x74\x68\x61\x6e\x20\x62\x6c\x6f\x63\x6b\x2d\x73\x69\x7a\x65\x20\x64\x61\x74\x61\x2e\x20\x54\x68\x65\x20\x6b\x65\x79\x20\x6e\x65\x65\x64\x73\x20\x74\x6f\x20\x62\x65\x20\x68\x61\x73\x68\x65\x64\x20\x62\x65\x66\x6f\x72\x65\x20\x62\x65\x69\x6e\x67\x20\x75\x73\x65\x64\x20\x62\x79\x20\x74\x68\x65\x20\x48\x4d\x41\x43\x20\x61\x6c\x67\x6f\x72\x69\x74\x68\x6d\x2e"
+ };
+ static const unsigned char outputs[6][32] = {
+ {0xb0, 0x34, 0x4c, 0x61, 0xd8, 0xdb, 0x38, 0x53, 0x5c, 0xa8, 0xaf, 0xce, 0xaf, 0x0b, 0xf1, 0x2b, 0x88, 0x1d, 0xc2, 0x00, 0xc9, 0x83, 0x3d, 0xa7, 0x26, 0xe9, 0x37, 0x6c, 0x2e, 0x32, 0xcf, 0xf7},
+ {0x5b, 0xdc, 0xc1, 0x46, 0xbf, 0x60, 0x75, 0x4e, 0x6a, 0x04, 0x24, 0x26, 0x08, 0x95, 0x75, 0xc7, 0x5a, 0x00, 0x3f, 0x08, 0x9d, 0x27, 0x39, 0x83, 0x9d, 0xec, 0x58, 0xb9, 0x64, 0xec, 0x38, 0x43},
+ {0x77, 0x3e, 0xa9, 0x1e, 0x36, 0x80, 0x0e, 0x46, 0x85, 0x4d, 0xb8, 0xeb, 0xd0, 0x91, 0x81, 0xa7, 0x29, 0x59, 0x09, 0x8b, 0x3e, 0xf8, 0xc1, 0x22, 0xd9, 0x63, 0x55, 0x14, 0xce, 0xd5, 0x65, 0xfe},
+ {0x82, 0x55, 0x8a, 0x38, 0x9a, 0x44, 0x3c, 0x0e, 0xa4, 0xcc, 0x81, 0x98, 0x99, 0xf2, 0x08, 0x3a, 0x85, 0xf0, 0xfa, 0xa3, 0xe5, 0x78, 0xf8, 0x07, 0x7a, 0x2e, 0x3f, 0xf4, 0x67, 0x29, 0x66, 0x5b},
+ {0x60, 0xe4, 0x31, 0x59, 0x1e, 0xe0, 0xb6, 0x7f, 0x0d, 0x8a, 0x26, 0xaa, 0xcb, 0xf5, 0xb7, 0x7f, 0x8e, 0x0b, 0xc6, 0x21, 0x37, 0x28, 0xc5, 0x14, 0x05, 0x46, 0x04, 0x0f, 0x0e, 0xe3, 0x7f, 0x54},
+ {0x9b, 0x09, 0xff, 0xa7, 0x1b, 0x94, 0x2f, 0xcb, 0x27, 0x63, 0x5f, 0xbc, 0xd5, 0xb0, 0xe9, 0x44, 0xbf, 0xdc, 0x63, 0x64, 0x4f, 0x07, 0x13, 0x93, 0x8a, 0x7f, 0x51, 0x53, 0x5c, 0x3a, 0x35, 0xe2}
+ };
+ for (int i = 0; i < 6; i++) {
+ secp256k1_hmac_sha256_t hasher;
+ secp256k1_hmac_sha256_initialize(&hasher, (const unsigned char*)(keys[i]), strlen(keys[i]));
+ secp256k1_hmac_sha256_write(&hasher, (const unsigned char*)(inputs[i]), strlen(inputs[i]));
+ unsigned char out[32];
+ secp256k1_hmac_sha256_finalize(&hasher, out);
+ CHECK(memcmp(out, outputs[i], 32) == 0);
+ if (strlen(inputs[i]) > 0) {
+ secp256k1_hmac_sha256_initialize(&hasher, (const unsigned char*)(keys[i]), strlen(keys[i]));
+ int split = secp256k1_rand32() % strlen(inputs[i]);
+ secp256k1_hmac_sha256_write(&hasher, (const unsigned char*)(inputs[i]), split);
+ secp256k1_hmac_sha256_write(&hasher, (const unsigned char*)(inputs[i] + split), strlen(inputs[i]) - split);
+ secp256k1_hmac_sha256_finalize(&hasher, out);
+ CHECK(memcmp(out, outputs[i], 32) == 0);
+ }
+ }
+}
+
+void run_rfc6979_hmac_sha256_tests(void) {
+ static const unsigned char key1[32] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x00};
+ static const unsigned char msg1[32] = {0x4b, 0xf5, 0x12, 0x2f, 0x34, 0x45, 0x54, 0xc5, 0x3b, 0xde, 0x2e, 0xbb, 0x8c, 0xd2, 0xb7, 0xe3, 0xd1, 0x60, 0x0a, 0xd6, 0x31, 0xc3, 0x85, 0xa5, 0xd7, 0xcc, 0xe2, 0x3c, 0x77, 0x85, 0x45, 0x9a};
+ static const unsigned char out1[3][32] = {
+ {0x4f, 0xe2, 0x95, 0x25, 0xb2, 0x08, 0x68, 0x09, 0x15, 0x9a, 0xcd, 0xf0, 0x50, 0x6e, 0xfb, 0x86, 0xb0, 0xec, 0x93, 0x2c, 0x7b, 0xa4, 0x42, 0x56, 0xab, 0x32, 0x1e, 0x42, 0x1e, 0x67, 0xe9, 0xfb},
+ {0x2b, 0xf0, 0xff, 0xf1, 0xd3, 0xc3, 0x78, 0xa2, 0x2d, 0xc5, 0xde, 0x1d, 0x85, 0x65, 0x22, 0x32, 0x5c, 0x65, 0xb5, 0x04, 0x49, 0x1a, 0x0c, 0xbd, 0x01, 0xcb, 0x8f, 0x3a, 0xa6, 0x7f, 0xfd, 0x4a},
+ {0xf5, 0x28, 0xb4, 0x10, 0xcb, 0x54, 0x1f, 0x77, 0x00, 0x0d, 0x7a, 0xfb, 0x6c, 0x5b, 0x53, 0xc5, 0xc4, 0x71, 0xea, 0xb4, 0x3e, 0x46, 0x6d, 0x9a, 0xc5, 0x19, 0x0c, 0x39, 0xc8, 0x2f, 0xd8, 0x2e}
+ };
+
+ static const unsigned char key2[32] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+ static const unsigned char msg2[32] = {0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55};
+ static const unsigned char out2[3][32] = {
+ {0x9c, 0x23, 0x6c, 0x16, 0x5b, 0x82, 0xae, 0x0c, 0xd5, 0x90, 0x65, 0x9e, 0x10, 0x0b, 0x6b, 0xab, 0x30, 0x36, 0xe7, 0xba, 0x8b, 0x06, 0x74, 0x9b, 0xaf, 0x69, 0x81, 0xe1, 0x6f, 0x1a, 0x2b, 0x95},
+ {0xdf, 0x47, 0x10, 0x61, 0x62, 0x5b, 0xc0, 0xea, 0x14, 0xb6, 0x82, 0xfe, 0xee, 0x2c, 0x9c, 0x02, 0xf2, 0x35, 0xda, 0x04, 0x20, 0x4c, 0x1d, 0x62, 0xa1, 0x53, 0x6c, 0x6e, 0x17, 0xae, 0xd7, 0xa9},
+ {0x75, 0x97, 0x88, 0x7c, 0xbd, 0x76, 0x32, 0x1f, 0x32, 0xe3, 0x04, 0x40, 0x67, 0x9a, 0x22, 0xcf, 0x7f, 0x8d, 0x9d, 0x2e, 0xac, 0x39, 0x0e, 0x58, 0x1f, 0xea, 0x09, 0x1c, 0xe2, 0x02, 0xba, 0x94}
+ };
+
+ secp256k1_rfc6979_hmac_sha256_t rng;
+ unsigned char out[32];
+
+ secp256k1_rfc6979_hmac_sha256_initialize(&rng, key1, 32, msg1, 32);
+ for (int i = 0; i < 3; i++) {
+ secp256k1_rfc6979_hmac_sha256_generate(&rng, out, 32);
+ CHECK(memcmp(out, out1[i], 32) == 0);
+ }
+ secp256k1_rfc6979_hmac_sha256_finalize(&rng);
+
+ secp256k1_rfc6979_hmac_sha256_initialize(&rng, key2, 32, msg2, 32);
+ for (int i = 0; i < 3; i++) {
+ secp256k1_rfc6979_hmac_sha256_generate(&rng, out, 32);
+ CHECK(memcmp(out, out2[i], 32) == 0);
+ }
+ secp256k1_rfc6979_hmac_sha256_finalize(&rng);
+}
+
/***** NUM TESTS *****/
#ifndef USE_NUM_NONE
@@ -494,9 +616,9 @@ void random_fe_non_square(secp256k1_fe_t *ns) {
}
int check_fe_equal(const secp256k1_fe_t *a, const secp256k1_fe_t *b) {
- secp256k1_fe_t an = *a; secp256k1_fe_normalize(&an);
+ secp256k1_fe_t an = *a; secp256k1_fe_normalize_weak(&an);
secp256k1_fe_t bn = *b; secp256k1_fe_normalize_var(&bn);
- return secp256k1_fe_equal(&an, &bn);
+ return secp256k1_fe_equal_var(&an, &bn);
}
int check_fe_inverse(const secp256k1_fe_t *a, const secp256k1_fe_t *ai) {
@@ -523,16 +645,16 @@ void run_field_misc(void) {
random_fe_non_zero(&y);
/* Test the fe equality and comparison operations. */
CHECK(secp256k1_fe_cmp_var(&x, &x) == 0);
- CHECK(secp256k1_fe_equal(&x, &x));
+ CHECK(secp256k1_fe_equal_var(&x, &x));
z = x;
secp256k1_fe_add(&z,&y);
secp256k1_fe_normalize(&z);
/* Test the conditional move. */
secp256k1_fe_cmov(&z, &x, 0);
- CHECK(secp256k1_fe_equal(&x, &z) == 0);
+ CHECK(secp256k1_fe_equal_var(&x, &z) == 0);
CHECK(secp256k1_fe_cmp_var(&x, &z) != 0);
secp256k1_fe_cmov(&y, &x, 1);
- CHECK(secp256k1_fe_equal(&x, &y));
+ CHECK(secp256k1_fe_equal_var(&x, &y));
/* Test that mul_int, mul, and add agree. */
secp256k1_fe_add(&y, &x);
secp256k1_fe_add(&y, &x);
@@ -656,108 +778,148 @@ void run_sqrt(void) {
/***** GROUP TESTS *****/
-int ge_equals_ge(const secp256k1_ge_t *a, const secp256k1_ge_t *b) {
- if (a->infinity && b->infinity)
- return 1;
- return check_fe_equal(&a->x, &b->x) && check_fe_equal(&a->y, &b->y);
+void ge_equals_ge(const secp256k1_ge_t *a, const secp256k1_ge_t *b) {
+ CHECK(a->infinity == b->infinity);
+ if (a->infinity)
+ return;
+ CHECK(secp256k1_fe_equal_var(&a->x, &b->x));
+ CHECK(secp256k1_fe_equal_var(&b->y, &b->y));
}
void ge_equals_gej(const secp256k1_ge_t *a, const secp256k1_gej_t *b) {
- secp256k1_ge_t bb;
- secp256k1_gej_t bj = *b;
- secp256k1_ge_set_gej_var(&bb, &bj);
- CHECK(ge_equals_ge(a, &bb));
-}
-
-void gej_equals_gej(const secp256k1_gej_t *a, const secp256k1_gej_t *b) {
- secp256k1_ge_t aa, bb;
- secp256k1_gej_t aj = *a, bj = *b;
- secp256k1_ge_set_gej_var(&aa, &aj);
- secp256k1_ge_set_gej_var(&bb, &bj);
- CHECK(ge_equals_ge(&aa, &bb));
+ CHECK(a->infinity == b->infinity);
+ if (a->infinity)
+ return;
+ /* Check a.x * b.z^2 == b.x && a.y * b.z^3 == b.y, to avoid inverses. */
+ secp256k1_fe_t z2s;
+ secp256k1_fe_sqr(&z2s, &b->z);
+ secp256k1_fe_t u1, u2, s1, s2;
+ secp256k1_fe_mul(&u1, &a->x, &z2s);
+ u2 = b->x; secp256k1_fe_normalize_weak(&u2);
+ secp256k1_fe_mul(&s1, &a->y, &z2s); secp256k1_fe_mul(&s1, &s1, &b->z);
+ s2 = b->y; secp256k1_fe_normalize_weak(&s2);
+ CHECK(secp256k1_fe_equal_var(&u1, &u2));
+ CHECK(secp256k1_fe_equal_var(&s1, &s2));
}
void test_ge(void) {
- char ca[135];
- char cb[68];
- int rlen;
- secp256k1_ge_t a, b, i, n;
- random_group_element_test(&a);
- random_group_element_test(&b);
- rlen = sizeof(ca);
- secp256k1_ge_get_hex(ca,&rlen,&a);
- CHECK(rlen > 4 && rlen <= (int)sizeof(ca));
- rlen = sizeof(cb);
- secp256k1_ge_get_hex(cb,&rlen,&b); /* Intentionally undersized buffer. */
- n = a;
- secp256k1_fe_normalize(&a.y);
- secp256k1_fe_negate(&n.y, &a.y, 1);
- secp256k1_ge_set_infinity(&i);
- random_field_element_magnitude(&a.x);
- random_field_element_magnitude(&a.y);
- random_field_element_magnitude(&b.x);
- random_field_element_magnitude(&b.y);
- random_field_element_magnitude(&n.x);
- random_field_element_magnitude(&n.y);
-
- secp256k1_gej_t aj, bj, ij, nj;
- random_group_element_jacobian_test(&aj, &a);
- random_group_element_jacobian_test(&bj, &b);
- secp256k1_gej_set_infinity(&ij);
- random_group_element_jacobian_test(&nj, &n);
- random_field_element_magnitude(&aj.x);
- random_field_element_magnitude(&aj.y);
- random_field_element_magnitude(&aj.z);
- random_field_element_magnitude(&bj.x);
- random_field_element_magnitude(&bj.y);
- random_field_element_magnitude(&bj.z);
- random_field_element_magnitude(&nj.x);
- random_field_element_magnitude(&nj.y);
- random_field_element_magnitude(&nj.z);
-
- /* gej + gej adds */
- secp256k1_gej_t aaj; secp256k1_gej_add_var(&aaj, &aj, &aj);
- secp256k1_gej_t abj; secp256k1_gej_add_var(&abj, &aj, &bj);
- secp256k1_gej_t aij; secp256k1_gej_add_var(&aij, &aj, &ij);
- secp256k1_gej_t anj; secp256k1_gej_add_var(&anj, &aj, &nj);
- secp256k1_gej_t iaj; secp256k1_gej_add_var(&iaj, &ij, &aj);
- secp256k1_gej_t iij; secp256k1_gej_add_var(&iij, &ij, &ij);
-
- /* gej + ge adds */
- secp256k1_gej_t aa; secp256k1_gej_add_ge_var(&aa, &aj, &a);
- secp256k1_gej_t ab; secp256k1_gej_add_ge_var(&ab, &aj, &b);
- secp256k1_gej_t ai; secp256k1_gej_add_ge_var(&ai, &aj, &i);
- secp256k1_gej_t an; secp256k1_gej_add_ge_var(&an, &aj, &n);
- secp256k1_gej_t ia; secp256k1_gej_add_ge_var(&ia, &ij, &a);
- secp256k1_gej_t ii; secp256k1_gej_add_ge_var(&ii, &ij, &i);
-
- /* const gej + ge adds */
- secp256k1_gej_t aac; secp256k1_gej_add_ge(&aac, &aj, &a);
- secp256k1_gej_t abc; secp256k1_gej_add_ge(&abc, &aj, &b);
- secp256k1_gej_t anc; secp256k1_gej_add_ge(&anc, &aj, &n);
- secp256k1_gej_t iac; secp256k1_gej_add_ge(&iac, &ij, &a);
-
- CHECK(secp256k1_gej_is_infinity(&an));
- CHECK(secp256k1_gej_is_infinity(&anj));
- CHECK(secp256k1_gej_is_infinity(&anc));
- gej_equals_gej(&aa, &aaj);
- gej_equals_gej(&aa, &aac);
- gej_equals_gej(&ab, &abj);
- gej_equals_gej(&ab, &abc);
- gej_equals_gej(&an, &anj);
- gej_equals_gej(&an, &anc);
- gej_equals_gej(&ia, &iaj);
- gej_equals_gej(&ai, &aij);
- gej_equals_gej(&ii, &iij);
- ge_equals_gej(&a, &ai);
- ge_equals_gej(&a, &ai);
- ge_equals_gej(&a, &iaj);
- ge_equals_gej(&a, &iaj);
- ge_equals_gej(&a, &iac);
+ int runs = 4;
+ /* Points: (infinity, p1, p1, -p1, -p1, p2, p2, -p2, -p2, p3, p3, -p3, -p3, p4, p4, -p4, -p4).
+ * The second in each pair of identical points uses a random Z coordinate in the Jacobian form.
+ * All magnitudes are randomized.
+ * All 17*17 combinations of points are added to eachother, using all applicable methods.
+ */
+ secp256k1_ge_t *ge = malloc(sizeof(secp256k1_ge_t) * (1 + 4 * runs));
+ secp256k1_gej_t *gej = malloc(sizeof(secp256k1_gej_t) * (1 + 4 * runs));
+ secp256k1_gej_set_infinity(&gej[0]);
+ secp256k1_ge_clear(&ge[0]);
+ secp256k1_ge_set_gej_var(&ge[0], &gej[0]);
+ for (int i = 0; i < runs; i++) {
+ secp256k1_ge_t g;
+ random_group_element_test(&g);
+ ge[1 + 4 * i] = g;
+ ge[2 + 4 * i] = g;
+ secp256k1_ge_neg(&ge[3 + 4 * i], &g);
+ secp256k1_ge_neg(&ge[4 + 4 * i], &g);
+ secp256k1_gej_set_ge(&gej[1 + 4 * i], &ge[1 + 4 * i]);
+ random_group_element_jacobian_test(&gej[2 + 4 * i], &ge[2 + 4 * i]);
+ secp256k1_gej_set_ge(&gej[3 + 4 * i], &ge[3 + 4 * i]);
+ random_group_element_jacobian_test(&gej[4 + 4 * i], &ge[4 + 4 * i]);
+ for (int j = 0; j < 4; j++) {
+ random_field_element_magnitude(&ge[1 + j + 4 * i].x);
+ random_field_element_magnitude(&ge[1 + j + 4 * i].y);
+ random_field_element_magnitude(&gej[1 + j + 4 * i].x);
+ random_field_element_magnitude(&gej[1 + j + 4 * i].y);
+ random_field_element_magnitude(&gej[1 + j + 4 * i].z);
+ }
+ }
+
+ for (int i1 = 0; i1 < 1 + 4 * runs; i1++) {
+ for (int i2 = 0; i2 < 1 + 4 * runs; i2++) {
+ /* Compute reference result using gej + gej (var). */
+ secp256k1_gej_t refj, resj;
+ secp256k1_ge_t ref;
+ secp256k1_gej_add_var(&refj, &gej[i1], &gej[i2]);
+ secp256k1_ge_set_gej_var(&ref, &refj);
+
+ /* Test gej + ge (var). */
+ secp256k1_gej_add_ge_var(&resj, &gej[i1], &ge[i2]);
+ ge_equals_gej(&ref, &resj);
+
+ /* Test gej + ge (const). */
+ if (i2 != 0) {
+ /* secp256k1_gej_add_ge does not support its second argument being infinity. */
+ secp256k1_gej_add_ge(&resj, &gej[i1], &ge[i2]);
+ ge_equals_gej(&ref, &resj);
+ }
+
+ /* Test doubling (var). */
+ if ((i1 == 0 && i2 == 0) || ((i1 + 3)/4 == (i2 + 3)/4 && ((i1 + 3)%4)/2 == ((i2 + 3)%4)/2)) {
+ /* Normal doubling. */
+ secp256k1_gej_double_var(&resj, &gej[i1]);
+ ge_equals_gej(&ref, &resj);
+ secp256k1_gej_double_var(&resj, &gej[i2]);
+ ge_equals_gej(&ref, &resj);
+ }
+
+ /* Test adding opposites. */
+ if ((i1 == 0 && i2 == 0) || ((i1 + 3)/4 == (i2 + 3)/4 && ((i1 + 3)%4)/2 != ((i2 + 3)%4)/2)) {
+ CHECK(secp256k1_ge_is_infinity(&ref));
+ }
+
+ /* Test adding infinity. */
+ if (i1 == 0) {
+ CHECK(secp256k1_ge_is_infinity(&ge[i1]));
+ CHECK(secp256k1_gej_is_infinity(&gej[i1]));
+ ge_equals_gej(&ref, &gej[i2]);
+ }
+ if (i2 == 0) {
+ CHECK(secp256k1_ge_is_infinity(&ge[i2]));
+ CHECK(secp256k1_gej_is_infinity(&gej[i2]));
+ ge_equals_gej(&ref, &gej[i1]);
+ }
+ }
+ }
+
+ /* Test adding all points together in random order equals infinity. */
+ {
+ secp256k1_gej_t *gej_shuffled = malloc((4 * runs + 1) * sizeof(secp256k1_gej_t));
+ for (int i = 0; i < 4 * runs + 1; i++) {
+ gej_shuffled[i] = gej[i];
+ }
+ for (int i = 0; i < 4 * runs + 1; i++) {
+ int swap = i + secp256k1_rand32() % (4 * runs + 1 - i);
+ if (swap != i) {
+ secp256k1_gej_t t = gej_shuffled[i];
+ gej_shuffled[i] = gej_shuffled[swap];
+ gej_shuffled[swap] = t;
+ }
+ }
+ secp256k1_gej_t sum;
+ secp256k1_gej_set_infinity(&sum);
+ for (int i = 0; i < 4 * runs + 1; i++) {
+ secp256k1_gej_add_var(&sum, &sum, &gej_shuffled[i]);
+ }
+ CHECK(secp256k1_gej_is_infinity(&sum));
+ free(gej_shuffled);
+ }
+
+ /* Test batch gej -> ge conversion. */
+ {
+ secp256k1_ge_t *ge_set_all = malloc((4 * runs + 1) * sizeof(secp256k1_ge_t));
+ secp256k1_ge_set_all_gej_var(4 * runs + 1, ge_set_all, gej);
+ for (int i = 0; i < 4 * runs + 1; i++) {
+ ge_equals_gej(&ge_set_all[i], &gej[i]);
+ }
+ free(ge_set_all);
+ }
+
+ free(ge);
+ free(gej);
}
void run_ge(void) {
- for (int i = 0; i < 2000*count; i++) {
+ for (int i = 0; i < count * 32; i++) {
test_ge();
}
}
@@ -949,6 +1111,44 @@ void run_ecdsa_sign_verify(void) {
}
}
+/** Dummy nonce generation function that just uses a precomputed nonce, and fails if it is not accepted. Use only for testing. */
+static int precomputed_nonce_function(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, unsigned int counter, const void *data) {
+ (void)msg32;
+ (void)key32;
+ memcpy(nonce32, data, 32);
+ return (counter == 0);
+}
+
+static int nonce_function_test_fail(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, unsigned int counter, const void *data) {
+ /* Dummy nonce generator that has a fatal error on the first counter value. */
+ if (counter == 0) return 0;
+ return nonce_function_rfc6979(nonce32, msg32, key32, counter - 1, data);
+}
+
+static int nonce_function_test_retry(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, unsigned int counter, const void *data) {
+ /* Dummy nonce generator that produces unacceptable nonces for the first several counter values. */
+ if (counter < 3) {
+ memset(nonce32, counter==0 ? 0 : 255, 32);
+ if (counter == 2) nonce32[31]--;
+ return 1;
+ }
+ if (counter < 5) {
+ static const unsigned char order[] = {
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,
+ 0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B,
+ 0xBF,0xD2,0x5E,0x8C,0xD0,0x36,0x41,0x41
+ };
+ memcpy(nonce32, order, 32);
+ if (counter == 4) nonce32[31]++;
+ return 1;
+ }
+ /* Retry rate of 6979 is negligible esp. as we only call this in determinstic tests. */
+ /* If someone does fine a case where it retries for secp256k1, we'd like to know. */
+ if (counter > 5) return 0;
+ return nonce_function_rfc6979(nonce32, msg32, key32, counter - 5, data);
+}
+
void test_ecdsa_end_to_end(void) {
unsigned char privkey[32];
unsigned char message[32];
@@ -1006,13 +1206,7 @@ void test_ecdsa_end_to_end(void) {
/* Sign. */
unsigned char signature[72]; int signaturelen = 72;
- while(1) {
- unsigned char rnd[32];
- secp256k1_rand256_test(rnd);
- if (secp256k1_ecdsa_sign(message, signature, &signaturelen, privkey, rnd) == 1) {
- break;
- }
- }
+ CHECK(secp256k1_ecdsa_sign(message, signature, &signaturelen, privkey, NULL, NULL) == 1);
/* Verify. */
CHECK(secp256k1_ecdsa_verify(message, signature, signaturelen, pubkey, pubkeylen) == 1);
/* Destroy signature and verify again. */
@@ -1021,13 +1215,7 @@ void test_ecdsa_end_to_end(void) {
/* Compact sign. */
unsigned char csignature[64]; int recid = 0;
- while(1) {
- unsigned char rnd[32];
- secp256k1_rand256_test(rnd);
- if (secp256k1_ecdsa_sign_compact(message, csignature, privkey, rnd, &recid) == 1) {
- break;
- }
- }
+ CHECK(secp256k1_ecdsa_sign_compact(message, csignature, privkey, NULL, NULL, &recid) == 1);
/* Recover. */
unsigned char recpubkey[65]; int recpubkeylen = 0;
CHECK(secp256k1_ecdsa_recover_compact(message, csignature, recpubkey, &recpubkeylen, pubkeylen == 33, recid) == 1);
@@ -1077,7 +1265,7 @@ void test_random_pubkeys(void) {
CHECK(secp256k1_eckey_pubkey_serialize(&elem, in, &size, 0));
CHECK(size == 65);
CHECK(secp256k1_eckey_pubkey_parse(&elem2, in, size));
- CHECK(ge_equals_ge(&elem,&elem2));
+ ge_equals_ge(&elem,&elem2);
/* Check that the X9.62 hybrid type is checked. */
in[0] = (r & 1) ? 6 : 7;
res = secp256k1_eckey_pubkey_parse(&elem2, in, size);
@@ -1086,7 +1274,7 @@ void test_random_pubkeys(void) {
else CHECK(!res);
}
if (res) {
- CHECK(ge_equals_ge(&elem,&elem2));
+ ge_equals_ge(&elem,&elem2);
CHECK(secp256k1_eckey_pubkey_serialize(&elem, out, &size, 0));
CHECK(memcmp(&in[1], &out[1], 64) == 0);
}
@@ -1280,6 +1468,12 @@ void test_ecdsa_edge_cases(void) {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
};
+ static const unsigned char nonce2[32] = {
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,
+ 0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B,
+ 0xBF,0xD2,0x5E,0x8C,0xD0,0x36,0x41,0x40
+ };
const unsigned char key[32] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -1294,10 +1488,74 @@ void test_ecdsa_edge_cases(void) {
};
unsigned char sig[72];
int siglen = 72;
- CHECK(secp256k1_ecdsa_sign(msg, sig, &siglen, key, nonce) == 0);
+ CHECK(secp256k1_ecdsa_sign(msg, sig, &siglen, key, precomputed_nonce_function, nonce) == 0);
+ CHECK(secp256k1_ecdsa_sign(msg, sig, &siglen, key, precomputed_nonce_function, nonce2) == 0);
msg[31] = 0xaa;
siglen = 72;
- CHECK(secp256k1_ecdsa_sign(msg, sig, &siglen, key, nonce) == 1);
+ CHECK(secp256k1_ecdsa_sign(msg, sig, &siglen, key, precomputed_nonce_function, nonce) == 1);
+ CHECK(secp256k1_ecdsa_sign(msg, sig, &siglen, key, precomputed_nonce_function, nonce2) == 1);
+ siglen = 10;
+ CHECK(secp256k1_ecdsa_sign(msg, sig, &siglen, key, precomputed_nonce_function, nonce) != 1);
+ }
+
+ /* Nonce function corner cases. */
+ {
+ unsigned char key[32];
+ unsigned char msg[32];
+ unsigned char sig[72];
+ memset(key, 0, 32);
+ memset(msg, 0, 32);
+ key[31] = 1;
+ msg[31] = 1;
+ int siglen = 72;
+ int recid;
+ /* Nonce function failure results in signature failure. */
+ CHECK(secp256k1_ecdsa_sign(msg, sig, &siglen, key, nonce_function_test_fail, NULL) == 0);
+ CHECK(secp256k1_ecdsa_sign_compact(msg, sig, key, nonce_function_test_fail, NULL, &recid) == 0);
+ /* The retry loop successfully makes its way to the first good value. */
+ unsigned char sig2[72];
+ int siglen2 = 72;
+ siglen = 72;
+ CHECK(secp256k1_ecdsa_sign(msg, sig, &siglen, key, nonce_function_test_retry, NULL) == 1);
+ CHECK(secp256k1_ecdsa_sign(msg, sig2, &siglen2, key, nonce_function_rfc6979, NULL) == 1);
+ CHECK((siglen == siglen2) && (memcmp(sig, sig2, siglen) == 0));
+ int recid2;
+ CHECK(secp256k1_ecdsa_sign_compact(msg, sig, key, nonce_function_test_retry, NULL, &recid) == 1);
+ CHECK(secp256k1_ecdsa_sign_compact(msg, sig2, key, nonce_function_rfc6979, NULL, &recid2) == 1);
+ CHECK((recid == recid2) && (memcmp(sig, sig2, 64) == 0));
+ /* The default nonce function is determinstic. */
+ siglen = 72;
+ siglen2 = 72;
+ CHECK(secp256k1_ecdsa_sign(msg, sig, &siglen, key, NULL, NULL) == 1);
+ CHECK(secp256k1_ecdsa_sign(msg, sig2, &siglen2, key, NULL, NULL) == 1);
+ CHECK((siglen == siglen2) && (memcmp(sig, sig2, siglen) == 0));
+ CHECK(secp256k1_ecdsa_sign_compact(msg, sig, key, NULL, NULL, &recid) == 1);
+ CHECK(secp256k1_ecdsa_sign_compact(msg, sig2, key, NULL, NULL, &recid2) == 1);
+ CHECK((recid == recid2) && (memcmp(sig, sig2, 64) == 0));
+ /* The default nonce function changes output with different messages. */
+ secp256k1_ecdsa_sig_t s[512];
+ for(int i=0; i<256; i++) {
+ siglen2 = 72;
+ msg[0] = i;
+ CHECK(secp256k1_ecdsa_sign(msg, sig2, &siglen2, key, NULL, NULL) == 1);
+ CHECK(secp256k1_ecdsa_sig_parse(&s[i], sig2, siglen2));
+ for (int j=0; j<i; j++) {
+ CHECK(!secp256k1_scalar_eq(&s[i].r, &s[j].r));
+ }
+ }
+ msg[0] = 0;
+ msg[31] = 2;
+ /* The default nonce function changes output with different keys. */
+ for(int i=256; i<512; i++) {
+ siglen2 = 72;
+ key[0] = i - 256;
+ CHECK(secp256k1_ecdsa_sign(msg, sig2, &siglen2, key, NULL, NULL) == 1);
+ CHECK(secp256k1_ecdsa_sig_parse(&s[i], sig2, siglen2));
+ for (int j=0; j<i; j++) {
+ CHECK(!secp256k1_scalar_eq(&s[i].r, &s[j].r));
+ }
+ }
+ key[0] = 0;
}
/* Privkey export where pubkey is the point at infinity. */
@@ -1405,6 +1663,10 @@ int main(int argc, char **argv) {
secp256k1_scalar_start();
secp256k1_ecdsa_start();
+ run_sha256_tests();
+ run_hmac_sha256_tests();
+ run_rfc6979_hmac_sha256_tests();
+
#ifndef USE_NUM_NONE
/* num tests */
run_num_smalltests();
diff --git a/src/serialize.h b/src/serialize.h
index e4a4039c71..a62760a793 100644
--- a/src/serialize.h
+++ b/src/serialize.h
@@ -249,7 +249,7 @@ uint64_t ReadCompactSize(Stream& is)
throw std::ios_base::failure("non-canonical ReadCompactSize()");
}
if (nSizeRet > (uint64_t)MAX_SIZE)
- throw std::ios_base::failure("ReadCompactSize() : size too large");
+ throw std::ios_base::failure("ReadCompactSize(): size too large");
return nSizeRet;
}
diff --git a/src/streams.h b/src/streams.h
index 6bd6d2b920..bd8568b1af 100644
--- a/src/streams.h
+++ b/src/streams.h
@@ -224,7 +224,7 @@ public:
{
if (nReadPosNext > vch.size())
{
- throw std::ios_base::failure("CDataStream::read() : end of data");
+ throw std::ios_base::failure("CDataStream::read(): end of data");
}
memcpy(pch, &vch[nReadPos], nSize);
nReadPos = 0;
@@ -244,7 +244,7 @@ public:
if (nReadPosNext >= vch.size())
{
if (nReadPosNext > vch.size())
- throw std::ios_base::failure("CDataStream::ignore() : end of data");
+ throw std::ios_base::failure("CDataStream::ignore(): end of data");
nReadPos = 0;
vch.clear();
return (*this);
@@ -374,18 +374,18 @@ public:
CAutoFile& read(char* pch, size_t nSize)
{
if (!file)
- throw std::ios_base::failure("CAutoFile::read : file handle is NULL");
+ throw std::ios_base::failure("CAutoFile::read: file handle is NULL");
if (fread(pch, 1, nSize, file) != nSize)
- throw std::ios_base::failure(feof(file) ? "CAutoFile::read : end of file" : "CAutoFile::read : fread failed");
+ throw std::ios_base::failure(feof(file) ? "CAutoFile::read: end of file" : "CAutoFile::read: fread failed");
return (*this);
}
CAutoFile& write(const char* pch, size_t nSize)
{
if (!file)
- throw std::ios_base::failure("CAutoFile::write : file handle is NULL");
+ throw std::ios_base::failure("CAutoFile::write: file handle is NULL");
if (fwrite(pch, 1, nSize, file) != nSize)
- throw std::ios_base::failure("CAutoFile::write : write failed");
+ throw std::ios_base::failure("CAutoFile::write: write failed");
return (*this);
}
@@ -401,7 +401,7 @@ public:
{
// Serialize to this stream
if (!file)
- throw std::ios_base::failure("CAutoFile::operator<< : file handle is NULL");
+ throw std::ios_base::failure("CAutoFile::operator<<: file handle is NULL");
::Serialize(*this, obj, nType, nVersion);
return (*this);
}
@@ -411,7 +411,7 @@ public:
{
// Unserialize from this stream
if (!file)
- throw std::ios_base::failure("CAutoFile::operator>> : file handle is NULL");
+ throw std::ios_base::failure("CAutoFile::operator>>: file handle is NULL");
::Unserialize(*this, obj, nType, nVersion);
return (*this);
}
@@ -452,7 +452,7 @@ protected:
return false;
size_t read = fread((void*)&vchBuf[pos], 1, readNow, src);
if (read == 0) {
- throw std::ios_base::failure(feof(src) ? "CBufferedFile::Fill : end of file" : "CBufferedFile::Fill : fread failed");
+ throw std::ios_base::failure(feof(src) ? "CBufferedFile::Fill: end of file" : "CBufferedFile::Fill: fread failed");
} else {
nSrcPos += read;
return true;
diff --git a/src/sync.h b/src/sync.h
index 7891e41560..27e80e813b 100644
--- a/src/sync.h
+++ b/src/sync.h
@@ -142,6 +142,17 @@ public:
Enter(pszName, pszFile, nLine);
}
+ CMutexLock(Mutex* pmutexIn, const char* pszName, const char* pszFile, int nLine, bool fTry = false)
+ {
+ if (!pmutexIn) return;
+
+ lock = boost::unique_lock<Mutex>(*pmutexIn, boost::defer_lock);
+ if (fTry)
+ TryEnter(pszName, pszFile, nLine);
+ else
+ Enter(pszName, pszFile, nLine);
+ }
+
~CMutexLock()
{
if (lock.owns_lock())
diff --git a/src/test/accounting_tests.cpp b/src/test/accounting_tests.cpp
index bed63991e6..da07b8c7a6 100644
--- a/src/test/accounting_tests.cpp
+++ b/src/test/accounting_tests.cpp
@@ -46,7 +46,7 @@ BOOST_AUTO_TEST_CASE(acc_orderupgrade)
walletdb.WriteAccountingEntry(ae);
wtx.mapValue["comment"] = "z";
- pwalletMain->AddToWallet(wtx);
+ pwalletMain->AddToWallet(wtx, false, &walletdb);
vpwtx.push_back(&pwalletMain->mapWallet[wtx.GetHash()]);
vpwtx[0]->nTimeReceived = (unsigned int)1333333335;
vpwtx[0]->nOrderPos = -1;
@@ -88,7 +88,7 @@ BOOST_AUTO_TEST_CASE(acc_orderupgrade)
--tx.nLockTime; // Just to change the hash :)
*static_cast<CTransaction*>(&wtx) = CTransaction(tx);
}
- pwalletMain->AddToWallet(wtx);
+ pwalletMain->AddToWallet(wtx, false, &walletdb);
vpwtx.push_back(&pwalletMain->mapWallet[wtx.GetHash()]);
vpwtx[1]->nTimeReceived = (unsigned int)1333333336;
@@ -98,7 +98,7 @@ BOOST_AUTO_TEST_CASE(acc_orderupgrade)
--tx.nLockTime; // Just to change the hash :)
*static_cast<CTransaction*>(&wtx) = CTransaction(tx);
}
- pwalletMain->AddToWallet(wtx);
+ pwalletMain->AddToWallet(wtx, false, &walletdb);
vpwtx.push_back(&pwalletMain->mapWallet[wtx.GetHash()]);
vpwtx[2]->nTimeReceived = (unsigned int)1333333329;
vpwtx[2]->nOrderPos = -1;
diff --git a/src/test/bignum.h b/src/test/bignum.h
index 365b17a1c5..e7aeee9db6 100644
--- a/src/test/bignum.h
+++ b/src/test/bignum.h
@@ -37,14 +37,14 @@ public:
if (!BN_copy(this, &b))
{
BN_clear_free(this);
- throw bignum_error("CBigNum::CBigNum(const CBigNum&) : BN_copy failed");
+ throw bignum_error("CBigNum::CBigNum(const CBigNum&): BN_copy failed");
}
}
CBigNum& operator=(const CBigNum& b)
{
if (!BN_copy(this, &b))
- throw bignum_error("CBigNum::operator= : BN_copy failed");
+ throw bignum_error("CBigNum::operator=: BN_copy failed");
return (*this);
}
@@ -151,7 +151,7 @@ inline const CBigNum operator+(const CBigNum& a, const CBigNum& b)
{
CBigNum r;
if (!BN_add(&r, &a, &b))
- throw bignum_error("CBigNum::operator+ : BN_add failed");
+ throw bignum_error("CBigNum::operator+: BN_add failed");
return r;
}
@@ -159,7 +159,7 @@ inline const CBigNum operator-(const CBigNum& a, const CBigNum& b)
{
CBigNum r;
if (!BN_sub(&r, &a, &b))
- throw bignum_error("CBigNum::operator- : BN_sub failed");
+ throw bignum_error("CBigNum::operator-: BN_sub failed");
return r;
}
diff --git a/src/test/crypto_tests.cpp b/src/test/crypto_tests.cpp
index 47bfd710cd..d5e595cd8a 100644
--- a/src/test/crypto_tests.cpp
+++ b/src/test/crypto_tests.cpp
@@ -2,7 +2,6 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include "crypto/rfc6979_hmac_sha256.h"
#include "crypto/ripemd160.h"
#include "crypto/sha1.h"
#include "crypto/sha256.h"
@@ -248,38 +247,4 @@ BOOST_AUTO_TEST_CASE(hmac_sha512_testvectors) {
"b6022cac3c4982b10d5eeb55c3e4de15134676fb6de0446065c97440fa8c6a58");
}
-void TestRFC6979(const std::string& hexkey, const std::string& hexmsg, const std::vector<std::string>& hexout)
-{
- std::vector<unsigned char> key = ParseHex(hexkey);
- std::vector<unsigned char> msg = ParseHex(hexmsg);
- RFC6979_HMAC_SHA256 rng(&key[0], key.size(), &msg[0], msg.size());
-
- for (unsigned int i = 0; i < hexout.size(); i++) {
- std::vector<unsigned char> out = ParseHex(hexout[i]);
- std::vector<unsigned char> gen;
- gen.resize(out.size());
- rng.Generate(&gen[0], gen.size());
- BOOST_CHECK(out == gen);
- }
-}
-
-BOOST_AUTO_TEST_CASE(rfc6979_hmac_sha256)
-{
- TestRFC6979(
- "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f00",
- "4bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459a",
- boost::assign::list_of
- ("4fe29525b2086809159acdf0506efb86b0ec932c7ba44256ab321e421e67e9fb")
- ("2bf0fff1d3c378a22dc5de1d856522325c65b504491a0cbd01cb8f3aa67ffd4a")
- ("f528b410cb541f77000d7afb6c5b53c5c471eab43e466d9ac5190c39c82fd82e"));
-
- TestRFC6979(
- "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
- "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
- boost::assign::list_of
- ("9c236c165b82ae0cd590659e100b6bab3036e7ba8b06749baf6981e16f1a2b95")
- ("df471061625bc0ea14b682feee2c9c02f235da04204c1d62a1536c6e17aed7a9")
- ("7597887cbd76321f32e30440679a22cf7f8d9d2eac390e581fea091ce202ba94"));
-}
-
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/data/script_invalid.json b/src/test/data/script_invalid.json
index 42b79e7470..a67c157aff 100644
--- a/src/test/data/script_invalid.json
+++ b/src/test/data/script_invalid.json
@@ -504,12 +504,22 @@
"2-of-2 CHECKMULTISIG NOT with the first pubkey invalid, and both signatures validly encoded."
],
[
- "0 0x47 0x3044022044dc17b0887c161bb67ba9635bf758735bdde503e4b0a0987f587f14a4e1143d022009a215772d49a85dae40d8ca03955af26ad3978a0ff965faa12915e9586249a501 0",
+ "0 0x47 0x3044022044dc17b0887c161bb67ba9635bf758735bdde503e4b0a0987f587f14a4e1143d022009a215772d49a85dae40d8ca03955af26ad3978a0ff965faa12915e9586249a501 1",
"2 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 2 CHECKMULTISIG NOT",
"STRICTENC",
"2-of-2 CHECKMULTISIG NOT with both pubkeys valid, but first signature invalid."
],
+["Increase DERSIG test coverage"],
+["0x4a 0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "0 CHECKSIG NOT", "DERSIG", "Overly long signature is incorrectly encoded for DERSIG"],
+["0x25 0x30220220000000000000000000000000000000000000000000000000000000000000000000", "0 CHECKSIG NOT", "DERSIG", "Missing S is incorrectly encoded for DERSIG"],
+["0x27 0x3024021077777777777777777777777777777777020a7777777777777777777777777777777701", "0 CHECKSIG NOT", "DERSIG", "S with invalid S length is incorrectly encoded for DERSIG"],
+["0x27 0x302403107777777777777777777777777777777702107777777777777777777777777777777701", "0 CHECKSIG NOT", "DERSIG", "Non-integer R is incorrectly encoded for DERSIG"],
+["0x27 0x302402107777777777777777777777777777777703107777777777777777777777777777777701", "0 CHECKSIG NOT", "DERSIG", "Non-integer S is incorrectly encoded for DERSIG"],
+["0x17 0x3014020002107777777777777777777777777777777701", "0 CHECKSIG NOT", "DERSIG", "Zero-length R is incorrectly encoded for DERSIG"],
+["0x17 0x3014021077777777777777777777777777777777020001", "0 CHECKSIG NOT", "DERSIG", "Zero-length S is incorrectly encoded for DERSIG"],
+["0x27 0x302402107777777777777777777777777777777702108777777777777777777777777777777701", "0 CHECKSIG NOT", "DERSIG", "Negative S is incorrectly encoded for DERSIG"],
+
["Automatically generated test cases"],
[
"0x47 0x3044022053205076a7bb12d2db3162a2d97d8197631f829b065948b7019b15482af819a902204328dcc02c994ca086b1226d0d5f1674d23cfae0d846143df812b81cab3391e801",
@@ -590,6 +600,102 @@
"P2PK NOT with too much R padding"
],
[
+ "0x47 0x30440220d7a0417c3f6d1a15094d1cf2a3378ca0503eb8a57630953a9e2987e21ddd0a6502207a6266d686c99090920249991d3d42065b6d43eb70187b219c0db82e4f94d1a201",
+ "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
+ "DERSIG",
+ "BIP66 example 1, with DERSIG"
+],
+[
+ "0x47 0x304402208e43c0b91f7c1e5bc58e41c8185f8a6086e111b0090187968a86f2822462d3c902200a58f4076b1133b18ff1dc83ee51676e44c60cc608d9534e0df5ace0424fc0be01",
+ "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT",
+ "",
+ "BIP66 example 2, without DERSIG"
+],
+[
+ "0x47 0x304402208e43c0b91f7c1e5bc58e41c8185f8a6086e111b0090187968a86f2822462d3c902200a58f4076b1133b18ff1dc83ee51676e44c60cc608d9534e0df5ace0424fc0be01",
+ "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT",
+ "DERSIG",
+ "BIP66 example 2, with DERSIG"
+],
+[
+ "0",
+ "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
+ "",
+ "BIP66 example 3, without DERSIG"
+],
+[
+ "0",
+ "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
+ "DERSIG",
+ "BIP66 example 3, with DERSIG"
+],
+[
+ "1",
+ "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
+ "",
+ "BIP66 example 5, without DERSIG"
+],
+[
+ "1",
+ "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
+ "DERSIG",
+ "BIP66 example 5, with DERSIG"
+],
+[
+ "1",
+ "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT",
+ "DERSIG",
+ "BIP66 example 6, with DERSIG"
+],
+[
+ "0 0x47 0x30440220cae00b1444babfbf6071b0ba8707f6bd373da3df494d6e74119b0430c5db810502205d5231b8c5939c8ff0c82242656d6e06edb073d42af336c99fe8837c36ea39d501 0x47 0x304402200b3d0b0375bb15c14620afa4aa10ae90a0d6a046ce217bc20fe0bc1ced68c1b802204b550acab90ae6d3478057c9ad24f9df743815b799b6449dd7e7f6d3bc6e274c01",
+ "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG",
+ "DERSIG",
+ "BIP66 example 7, with DERSIG"
+],
+[
+ "0 0x47 0x30440220f00a77260d34ec2f0c59621dc710f58169d0ca06df1a88cd4b1f1b97bd46991b02201ee220c7e04f26aed03f94aa97fb09ca5627163bf4ba07e6979972ec737db22601 0x47 0x3044022079ea80afd538d9ada421b5101febeb6bc874e01dde5bca108c1d0479aec339a4022004576db8f66130d1df686ccf00935703689d69cf539438da1edab208b0d63c4801",
+ "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG NOT",
+ "",
+ "BIP66 example 8, without DERSIG"
+],
+[
+ "0 0x47 0x30440220f00a77260d34ec2f0c59621dc710f58169d0ca06df1a88cd4b1f1b97bd46991b02201ee220c7e04f26aed03f94aa97fb09ca5627163bf4ba07e6979972ec737db22601 0x47 0x3044022079ea80afd538d9ada421b5101febeb6bc874e01dde5bca108c1d0479aec339a4022004576db8f66130d1df686ccf00935703689d69cf539438da1edab208b0d63c4801",
+ "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG NOT",
+ "DERSIG",
+ "BIP66 example 8, with DERSIG"
+],
+[
+ "0 0 0x47 0x3044022081aa9d436f2154e8b6d600516db03d78de71df685b585a9807ead4210bd883490220534bb6bdf318a419ac0749660b60e78d17d515558ef369bf872eff405b676b2e01",
+ "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG",
+ "",
+ "BIP66 example 9, without DERSIG"
+],
+[
+ "0 0 0x47 0x3044022081aa9d436f2154e8b6d600516db03d78de71df685b585a9807ead4210bd883490220534bb6bdf318a419ac0749660b60e78d17d515558ef369bf872eff405b676b2e01",
+ "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG",
+ "DERSIG",
+ "BIP66 example 9, with DERSIG"
+],
+[
+ "0 0 0x47 0x30440220afa76a8f60622f813b05711f051c6c3407e32d1b1b70b0576c1f01b54e4c05c702200d58e9df044fd1845cabfbeef6e624ba0401daf7d7e084736f9ff601c3783bf501",
+ "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG NOT",
+ "DERSIG",
+ "BIP66 example 10, with DERSIG"
+],
+[
+ "0 0x47 0x30440220cae00b1444babfbf6071b0ba8707f6bd373da3df494d6e74119b0430c5db810502205d5231b8c5939c8ff0c82242656d6e06edb073d42af336c99fe8837c36ea39d501 0",
+ "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG",
+ "",
+ "BIP66 example 11, without DERSIG"
+],
+[
+ "0 0x47 0x30440220cae00b1444babfbf6071b0ba8707f6bd373da3df494d6e74119b0430c5db810502205d5231b8c5939c8ff0c82242656d6e06edb073d42af336c99fe8837c36ea39d501 0",
+ "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG",
+ "DERSIG",
+ "BIP66 example 11, with DERSIG"
+],
+[
"0x49 0x304502203e4516da7253cf068effec6b95c41221c0cf3a8e6ccb8cbf1725b562e9afde2c022100ab1e3da73d67e32045a20e0b999e049978ea8d6ee5480d485fcf2ce0d03b2ef05101",
"0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG",
"LOW_S",
diff --git a/src/test/data/script_valid.json b/src/test/data/script_valid.json
index 5253d5e39e..fb81fcb1f5 100644
--- a/src/test/data/script_valid.json
+++ b/src/test/data/script_valid.json
@@ -662,6 +662,11 @@
["0 0 0x02 0x0000", "CHECKMULTISIGVERIFY 1", ""],
["0 0x02 0x0000 0", "CHECKMULTISIGVERIFY 1", ""],
+["While not really correctly DER encoded, the empty signature is allowed by"],
+["STRICTENC to provide a compact way to provide a delibrately invalid signature."],
+["0", "0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 CHECKSIG NOT", "STRICTENC"],
+["0 0", "1 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 1 CHECKMULTISIG NOT", "STRICTENC"],
+
["CHECKMULTISIG evaluation order tests. CHECKMULTISIG evaluates signatures and"],
["pubkeys in a specific order, and will exit early if the number of signatures"],
["left to check is greater than the number of keys left. As STRICTENC fails the"],
@@ -683,6 +688,16 @@
"2-of-2 CHECKMULTISIG NOT with both pubkeys valid, but second signature invalid. Valid pubkey fails, and CHECKMULTISIG exits early, prior to evaluation of second invalid signature."
],
+["Increase test coverage for DERSIG"],
+["0x4a 0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "0 CHECKSIG NOT", "", "Overly long signature is correctly encoded"],
+["0x25 0x30220220000000000000000000000000000000000000000000000000000000000000000000", "0 CHECKSIG NOT", "", "Missing S is correctly encoded"],
+["0x27 0x3024021077777777777777777777777777777777020a7777777777777777777777777777777701", "0 CHECKSIG NOT", "", "S with invalid S length is correctly encoded"],
+["0x27 0x302403107777777777777777777777777777777702107777777777777777777777777777777701", "0 CHECKSIG NOT", "", "Non-integer R is correctly encoded"],
+["0x27 0x302402107777777777777777777777777777777703107777777777777777777777777777777701", "0 CHECKSIG NOT", "", "Non-integer S is correctly encoded"],
+["0x17 0x3014020002107777777777777777777777777777777701", "0 CHECKSIG NOT", "", "Zero-length R is correctly encoded"],
+["0x17 0x3014021077777777777777777777777777777777020001", "0 CHECKSIG NOT", "", "Zero-length S is correctly encoded for DERSIG"],
+["0x27 0x302402107777777777777777777777777777777702108777777777777777777777777777777701", "0 CHECKSIG NOT", "", "Negative S is correctly encoded"],
+
["Automatically generated test cases"],
[
"0x47 0x3044022053205076a7bb13d2db3162a2d97d8197631f829b065948b7019b15482af819a902204328dcc02c994ca086b1226d0d5f1674d23cfae0d846143df812b81cab3391e801",
@@ -751,6 +766,54 @@
"P2PK NOT with bad sig with too much R padding but no DERSIG"
],
[
+ "0x47 0x30440220d7a0417c3f6d1a15094d1cf2a3378ca0503eb8a57630953a9e2987e21ddd0a6502207a6266d686c99090920249991d3d42065b6d43eb70187b219c0db82e4f94d1a201",
+ "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
+ "",
+ "BIP66 example 1, without DERSIG"
+],
+[
+ "0",
+ "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT",
+ "",
+ "BIP66 example 4, without DERSIG"
+],
+[
+ "0",
+ "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT",
+ "DERSIG",
+ "BIP66 example 4, with DERSIG"
+],
+[
+ "1",
+ "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT",
+ "",
+ "BIP66 example 6, without DERSIG"
+],
+[
+ "0 0x47 0x30440220cae00b1444babfbf6071b0ba8707f6bd373da3df494d6e74119b0430c5db810502205d5231b8c5939c8ff0c82242656d6e06edb073d42af336c99fe8837c36ea39d501 0x47 0x304402200b3d0b0375bb15c14620afa4aa10ae90a0d6a046ce217bc20fe0bc1ced68c1b802204b550acab90ae6d3478057c9ad24f9df743815b799b6449dd7e7f6d3bc6e274c01",
+ "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG",
+ "",
+ "BIP66 example 7, without DERSIG"
+],
+[
+ "0 0 0x47 0x30440220afa76a8f60622f813b05711f051c6c3407e32d1b1b70b0576c1f01b54e4c05c702200d58e9df044fd1845cabfbeef6e624ba0401daf7d7e084736f9ff601c3783bf501",
+ "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG NOT",
+ "",
+ "BIP66 example 10, without DERSIG"
+],
+[
+ "0 0x47 0x30440220f00a77260d34ec2f0c59621dc710f58169d0ca06df1a88cd4b1f1b97bd46991b02201ee220c7e04f26aed03f94aa97fb09ca5627163bf4ba07e6979972ec737db22601 0",
+ "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG NOT",
+ "",
+ "BIP66 example 12, without DERSIG"
+],
+[
+ "0 0x47 0x30440220f00a77260d34ec2f0c59621dc710f58169d0ca06df1a88cd4b1f1b97bd46991b02201ee220c7e04f26aed03f94aa97fb09ca5627163bf4ba07e6979972ec737db22601 0",
+ "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG NOT",
+ "DERSIG",
+ "BIP66 example 12, with DERSIG"
+],
+[
"0x49 0x304502203e4516da7253cf068effec6b95c41221c0cf3a8e6ccb8cbf1725b562e9afde2c022100ab1e3da73d67e32045a20e0b999e049978ea8d6ee5480d485fcf2ce0d03b2ef05101",
"0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG",
"",
diff --git a/src/test/data/sig_canonical.json b/src/test/data/sig_canonical.json
deleted file mode 100644
index e43a08629a..0000000000
--- a/src/test/data/sig_canonical.json
+++ /dev/null
@@ -1,7 +0,0 @@
-[
- "300602010002010001",
- "3008020200ff020200ff01",
- "304402203932c892e2e550f3af8ee4ce9c215a87f9bb831dcac87b2838e2c2eaa891df0c022030b61dd36543125d56b9f9f3a1f9353189e5af33cdda8d77a5209aec03978fa001",
- "30450220076045be6f9eca28ff1ec606b833d0b87e70b2a630f5e3a496b110967a40f90a0221008fffd599910eefe00bc803c688c2eca1d2ba7f6b180620eaa03488e6585db6ba01",
- "3046022100876045be6f9eca28ff1ec606b833d0b87e70b2a630f5e3a496b110967a40f90a0221008fffd599910eefe00bc803c688c2eca1d2ba7f6b180620eaa03488e6585db6ba01"
-]
diff --git a/src/test/data/sig_noncanonical.json b/src/test/data/sig_noncanonical.json
deleted file mode 100644
index d9a6c1cdd8..0000000000
--- a/src/test/data/sig_noncanonical.json
+++ /dev/null
@@ -1,22 +0,0 @@
-[
- "non-hex strings are ignored",
-
- "too short:", "30050201FF020001",
- "too long:", "30470221005990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba6105022200002d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed01",
- "hashtype:", "304402205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba610502202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed11",
- "type:", "314402205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba610502202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed01",
- "total length:", "304502205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba610502202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed01",
- "S len oob:", "301F01205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb101",
- "R+S:", "304502205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba610502202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed0001",
-
- "R type:", "304401205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba610502202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed01",
- "R len = 0:", "3024020002202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed01",
- "R<0:", "304402208990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba610502202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed01",
- "R padded:", "30450221005990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba610502202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed01",
-
-
- "S type:", "304402205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba610501202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed01",
- "S len = 0:", "302402205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba6105020001",
- "S<0:", "304402205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba61050220fd5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed01",
- "S padded:", "304502205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba61050221002d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed01"
-]
diff --git a/src/test/multisig_tests.cpp b/src/test/multisig_tests.cpp
index 69d8522188..2168a5fef1 100644
--- a/src/test/multisig_tests.cpp
+++ b/src/test/multisig_tests.cpp
@@ -82,20 +82,20 @@ BOOST_AUTO_TEST_CASE(multisig_verify)
keys.assign(1,key[0]);
keys.push_back(key[1]);
s = sign_multisig(a_and_b, keys, txTo[0], 0);
- BOOST_CHECK(VerifyScript(s, a_and_b, flags, SignatureChecker(txTo[0], 0), &err));
+ BOOST_CHECK(VerifyScript(s, a_and_b, flags, MutableTransactionSignatureChecker(&txTo[0], 0), &err));
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
for (int i = 0; i < 4; i++)
{
keys.assign(1,key[i]);
s = sign_multisig(a_and_b, keys, txTo[0], 0);
- BOOST_CHECK_MESSAGE(!VerifyScript(s, a_and_b, flags, SignatureChecker(txTo[0], 0), &err), strprintf("a&b 1: %d", i));
+ BOOST_CHECK_MESSAGE(!VerifyScript(s, a_and_b, flags, MutableTransactionSignatureChecker(&txTo[0], 0), &err), strprintf("a&b 1: %d", i));
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_INVALID_STACK_OPERATION, ScriptErrorString(err));
keys.assign(1,key[1]);
keys.push_back(key[i]);
s = sign_multisig(a_and_b, keys, txTo[0], 0);
- BOOST_CHECK_MESSAGE(!VerifyScript(s, a_and_b, flags, SignatureChecker(txTo[0], 0), &err), strprintf("a&b 2: %d", i));
+ BOOST_CHECK_MESSAGE(!VerifyScript(s, a_and_b, flags, MutableTransactionSignatureChecker(&txTo[0], 0), &err), strprintf("a&b 2: %d", i));
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
}
@@ -106,22 +106,18 @@ BOOST_AUTO_TEST_CASE(multisig_verify)
s = sign_multisig(a_or_b, keys, txTo[1], 0);
if (i == 0 || i == 1)
{
- BOOST_CHECK_MESSAGE(VerifyScript(s, a_or_b, flags, SignatureChecker(txTo[1], 0), &err), strprintf("a|b: %d", i));
+ BOOST_CHECK_MESSAGE(VerifyScript(s, a_or_b, flags, MutableTransactionSignatureChecker(&txTo[1], 0), &err), strprintf("a|b: %d", i));
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
}
else
{
- BOOST_CHECK_MESSAGE(!VerifyScript(s, a_or_b, flags, SignatureChecker(txTo[1], 0), &err), strprintf("a|b: %d", i));
+ BOOST_CHECK_MESSAGE(!VerifyScript(s, a_or_b, flags, MutableTransactionSignatureChecker(&txTo[1], 0), &err), strprintf("a|b: %d", i));
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
}
}
s.clear();
- s << OP_0 << OP_0;
- BOOST_CHECK(!VerifyScript(s, a_or_b, flags, SignatureChecker(txTo[1], 0), &err));
- BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_SIG_DER, ScriptErrorString(err));
- s.clear();
s << OP_0 << OP_1;
- BOOST_CHECK(!VerifyScript(s, a_or_b, flags, SignatureChecker(txTo[1], 0), &err));
+ BOOST_CHECK(!VerifyScript(s, a_or_b, flags, MutableTransactionSignatureChecker(&txTo[1], 0), &err));
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_SIG_DER, ScriptErrorString(err));
@@ -133,12 +129,12 @@ BOOST_AUTO_TEST_CASE(multisig_verify)
s = sign_multisig(escrow, keys, txTo[2], 0);
if (i < j && i < 3 && j < 3)
{
- BOOST_CHECK_MESSAGE(VerifyScript(s, escrow, flags, SignatureChecker(txTo[2], 0), &err), strprintf("escrow 1: %d %d", i, j));
+ BOOST_CHECK_MESSAGE(VerifyScript(s, escrow, flags, MutableTransactionSignatureChecker(&txTo[2], 0), &err), strprintf("escrow 1: %d %d", i, j));
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
}
else
{
- BOOST_CHECK_MESSAGE(!VerifyScript(s, escrow, flags, SignatureChecker(txTo[2], 0), &err), strprintf("escrow 2: %d %d", i, j));
+ BOOST_CHECK_MESSAGE(!VerifyScript(s, escrow, flags, MutableTransactionSignatureChecker(&txTo[2], 0), &err), strprintf("escrow 2: %d %d", i, j));
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
}
}
diff --git a/src/test/script_P2SH_tests.cpp b/src/test/script_P2SH_tests.cpp
index 77e70022df..94f2ce1a29 100644
--- a/src/test/script_P2SH_tests.cpp
+++ b/src/test/script_P2SH_tests.cpp
@@ -43,7 +43,7 @@ Verify(const CScript& scriptSig, const CScript& scriptPubKey, bool fStrict, Scri
txTo.vin[0].scriptSig = scriptSig;
txTo.vout[0].nValue = 1;
- return VerifyScript(scriptSig, scriptPubKey, fStrict ? SCRIPT_VERIFY_P2SH : SCRIPT_VERIFY_NONE, SignatureChecker(txTo, 0), &err);
+ return VerifyScript(scriptSig, scriptPubKey, fStrict ? SCRIPT_VERIFY_P2SH : SCRIPT_VERIFY_NONE, MutableTransactionSignatureChecker(&txTo, 0), &err);
}
diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp
index 4db8942fa1..6092afd782 100644
--- a/src/test/script_tests.cpp
+++ b/src/test/script_tests.cpp
@@ -93,7 +93,7 @@ void DoTest(const CScript& scriptPubKey, const CScript& scriptSig, int flags, bo
ScriptError err;
CMutableTransaction tx = BuildSpendingTransaction(scriptSig, BuildCreditingTransaction(scriptPubKey));
CMutableTransaction tx2 = tx;
- BOOST_CHECK_MESSAGE(VerifyScript(scriptSig, scriptPubKey, flags, SignatureChecker(tx, 0), &err) == expect, message);
+ BOOST_CHECK_MESSAGE(VerifyScript(scriptSig, scriptPubKey, flags, MutableTransactionSignatureChecker(&tx, 0), &err) == expect, message);
BOOST_CHECK_MESSAGE(expect == (err == SCRIPT_ERR_OK), std::string(ScriptErrorString(err)) + ": " + message);
#if defined(HAVE_CONSENSUS_LIB)
CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
@@ -406,6 +406,79 @@ BOOST_AUTO_TEST_CASE(script_build)
"P2PK NOT with too much R padding", SCRIPT_VERIFY_DERSIG
).PushSig(keys.key2, SIGHASH_ALL, 31, 32).EditPush(1, "43021F", "44022000"));
+ good.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG,
+ "BIP66 example 1, without DERSIG", 0
+ ).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220"));
+ bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG,
+ "BIP66 example 1, with DERSIG", SCRIPT_VERIFY_DERSIG
+ ).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220"));
+ bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG << OP_NOT,
+ "BIP66 example 2, without DERSIG", 0
+ ).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220"));
+ bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG << OP_NOT,
+ "BIP66 example 2, with DERSIG", SCRIPT_VERIFY_DERSIG
+ ).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220"));
+ bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG,
+ "BIP66 example 3, without DERSIG", 0
+ ).Num(0));
+ bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG,
+ "BIP66 example 3, with DERSIG", SCRIPT_VERIFY_DERSIG
+ ).Num(0));
+ good.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG << OP_NOT,
+ "BIP66 example 4, without DERSIG", 0
+ ).Num(0));
+ good.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG << OP_NOT,
+ "BIP66 example 4, with DERSIG", SCRIPT_VERIFY_DERSIG
+ ).Num(0));
+ bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG,
+ "BIP66 example 5, without DERSIG", 0
+ ).Num(1));
+ bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG,
+ "BIP66 example 5, with DERSIG", SCRIPT_VERIFY_DERSIG
+ ).Num(1));
+ good.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG << OP_NOT,
+ "BIP66 example 6, without DERSIG", 0
+ ).Num(1));
+ bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG << OP_NOT,
+ "BIP66 example 6, with DERSIG", SCRIPT_VERIFY_DERSIG
+ ).Num(1));
+ good.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_2 << OP_CHECKMULTISIG,
+ "BIP66 example 7, without DERSIG", 0
+ ).Num(0).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220").PushSig(keys.key2));
+ bad.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_2 << OP_CHECKMULTISIG,
+ "BIP66 example 7, with DERSIG", SCRIPT_VERIFY_DERSIG
+ ).Num(0).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220").PushSig(keys.key2));
+ bad.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_2 << OP_CHECKMULTISIG << OP_NOT,
+ "BIP66 example 8, without DERSIG", 0
+ ).Num(0).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220").PushSig(keys.key2));
+ bad.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_2 << OP_CHECKMULTISIG << OP_NOT,
+ "BIP66 example 8, with DERSIG", SCRIPT_VERIFY_DERSIG
+ ).Num(0).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220").PushSig(keys.key2));
+ bad.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_2 << OP_CHECKMULTISIG,
+ "BIP66 example 9, without DERSIG", 0
+ ).Num(0).Num(0).PushSig(keys.key2, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220"));
+ bad.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_2 << OP_CHECKMULTISIG,
+ "BIP66 example 9, with DERSIG", SCRIPT_VERIFY_DERSIG
+ ).Num(0).Num(0).PushSig(keys.key2, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220"));
+ good.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_2 << OP_CHECKMULTISIG << OP_NOT,
+ "BIP66 example 10, without DERSIG", 0
+ ).Num(0).Num(0).PushSig(keys.key2, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220"));
+ bad.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_2 << OP_CHECKMULTISIG << OP_NOT,
+ "BIP66 example 10, with DERSIG", SCRIPT_VERIFY_DERSIG
+ ).Num(0).Num(0).PushSig(keys.key2, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220"));
+ bad.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_2 << OP_CHECKMULTISIG,
+ "BIP66 example 11, without DERSIG", 0
+ ).Num(0).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220").Num(0));
+ bad.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_2 << OP_CHECKMULTISIG,
+ "BIP66 example 11, with DERSIG", SCRIPT_VERIFY_DERSIG
+ ).Num(0).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220").Num(0));
+ good.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_2 << OP_CHECKMULTISIG << OP_NOT,
+ "BIP66 example 12, without DERSIG", 0
+ ).Num(0).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220").Num(0));
+ good.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_2 << OP_CHECKMULTISIG << OP_NOT,
+ "BIP66 example 12, with DERSIG", SCRIPT_VERIFY_DERSIG
+ ).Num(0).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220").Num(0));
+
good.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey2C) << OP_CHECKSIG,
"P2PK with high S but no LOW_S", 0
).PushSig(keys.key2, SIGHASH_ALL, 32, 33));
@@ -682,18 +755,18 @@ BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG12)
CMutableTransaction txTo12 = BuildSpendingTransaction(CScript(), txFrom12);
CScript goodsig1 = sign_multisig(scriptPubKey12, key1, txTo12);
- BOOST_CHECK(VerifyScript(goodsig1, scriptPubKey12, flags, SignatureChecker(txTo12, 0), &err));
+ BOOST_CHECK(VerifyScript(goodsig1, scriptPubKey12, flags, MutableTransactionSignatureChecker(&txTo12, 0), &err));
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
txTo12.vout[0].nValue = 2;
- BOOST_CHECK(!VerifyScript(goodsig1, scriptPubKey12, flags, SignatureChecker(txTo12, 0), &err));
+ BOOST_CHECK(!VerifyScript(goodsig1, scriptPubKey12, flags, MutableTransactionSignatureChecker(&txTo12, 0), &err));
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
CScript goodsig2 = sign_multisig(scriptPubKey12, key2, txTo12);
- BOOST_CHECK(VerifyScript(goodsig2, scriptPubKey12, flags, SignatureChecker(txTo12, 0), &err));
+ BOOST_CHECK(VerifyScript(goodsig2, scriptPubKey12, flags, MutableTransactionSignatureChecker(&txTo12, 0), &err));
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
CScript badsig1 = sign_multisig(scriptPubKey12, key3, txTo12);
- BOOST_CHECK(!VerifyScript(badsig1, scriptPubKey12, flags, SignatureChecker(txTo12, 0), &err));
+ BOOST_CHECK(!VerifyScript(badsig1, scriptPubKey12, flags, MutableTransactionSignatureChecker(&txTo12, 0), &err));
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
}
@@ -715,54 +788,54 @@ BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG23)
std::vector<CKey> keys;
keys.push_back(key1); keys.push_back(key2);
CScript goodsig1 = sign_multisig(scriptPubKey23, keys, txTo23);
- BOOST_CHECK(VerifyScript(goodsig1, scriptPubKey23, flags, SignatureChecker(txTo23, 0), &err));
+ BOOST_CHECK(VerifyScript(goodsig1, scriptPubKey23, flags, MutableTransactionSignatureChecker(&txTo23, 0), &err));
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
keys.clear();
keys.push_back(key1); keys.push_back(key3);
CScript goodsig2 = sign_multisig(scriptPubKey23, keys, txTo23);
- BOOST_CHECK(VerifyScript(goodsig2, scriptPubKey23, flags, SignatureChecker(txTo23, 0), &err));
+ BOOST_CHECK(VerifyScript(goodsig2, scriptPubKey23, flags, MutableTransactionSignatureChecker(&txTo23, 0), &err));
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
keys.clear();
keys.push_back(key2); keys.push_back(key3);
CScript goodsig3 = sign_multisig(scriptPubKey23, keys, txTo23);
- BOOST_CHECK(VerifyScript(goodsig3, scriptPubKey23, flags, SignatureChecker(txTo23, 0), &err));
+ BOOST_CHECK(VerifyScript(goodsig3, scriptPubKey23, flags, MutableTransactionSignatureChecker(&txTo23, 0), &err));
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
keys.clear();
keys.push_back(key2); keys.push_back(key2); // Can't re-use sig
CScript badsig1 = sign_multisig(scriptPubKey23, keys, txTo23);
- BOOST_CHECK(!VerifyScript(badsig1, scriptPubKey23, flags, SignatureChecker(txTo23, 0), &err));
+ BOOST_CHECK(!VerifyScript(badsig1, scriptPubKey23, flags, MutableTransactionSignatureChecker(&txTo23, 0), &err));
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
keys.clear();
keys.push_back(key2); keys.push_back(key1); // sigs must be in correct order
CScript badsig2 = sign_multisig(scriptPubKey23, keys, txTo23);
- BOOST_CHECK(!VerifyScript(badsig2, scriptPubKey23, flags, SignatureChecker(txTo23, 0), &err));
+ BOOST_CHECK(!VerifyScript(badsig2, scriptPubKey23, flags, MutableTransactionSignatureChecker(&txTo23, 0), &err));
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
keys.clear();
keys.push_back(key3); keys.push_back(key2); // sigs must be in correct order
CScript badsig3 = sign_multisig(scriptPubKey23, keys, txTo23);
- BOOST_CHECK(!VerifyScript(badsig3, scriptPubKey23, flags, SignatureChecker(txTo23, 0), &err));
+ BOOST_CHECK(!VerifyScript(badsig3, scriptPubKey23, flags, MutableTransactionSignatureChecker(&txTo23, 0), &err));
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
keys.clear();
keys.push_back(key4); keys.push_back(key2); // sigs must match pubkeys
CScript badsig4 = sign_multisig(scriptPubKey23, keys, txTo23);
- BOOST_CHECK(!VerifyScript(badsig4, scriptPubKey23, flags, SignatureChecker(txTo23, 0), &err));
+ BOOST_CHECK(!VerifyScript(badsig4, scriptPubKey23, flags, MutableTransactionSignatureChecker(&txTo23, 0), &err));
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
keys.clear();
keys.push_back(key1); keys.push_back(key4); // sigs must match pubkeys
CScript badsig5 = sign_multisig(scriptPubKey23, keys, txTo23);
- BOOST_CHECK(!VerifyScript(badsig5, scriptPubKey23, flags, SignatureChecker(txTo23, 0), &err));
+ BOOST_CHECK(!VerifyScript(badsig5, scriptPubKey23, flags, MutableTransactionSignatureChecker(&txTo23, 0), &err));
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
keys.clear(); // Must have signatures
CScript badsig6 = sign_multisig(scriptPubKey23, keys, txTo23);
- BOOST_CHECK(!VerifyScript(badsig6, scriptPubKey23, flags, SignatureChecker(txTo23, 0), &err));
+ BOOST_CHECK(!VerifyScript(badsig6, scriptPubKey23, flags, MutableTransactionSignatureChecker(&txTo23, 0), &err));
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_INVALID_STACK_OPERATION, ScriptErrorString(err));
}
diff --git a/src/test/sighash_tests.cpp b/src/test/sighash_tests.cpp
index 662f765a0b..ea41dbcde2 100644
--- a/src/test/sighash_tests.cpp
+++ b/src/test/sighash_tests.cpp
@@ -27,7 +27,7 @@ uint256 static SignatureHashOld(CScript scriptCode, const CTransaction& txTo, un
static const uint256 one(uint256S("0000000000000000000000000000000000000000000000000000000000000001"));
if (nIn >= txTo.vin.size())
{
- printf("ERROR: SignatureHash() : nIn=%d out of range\n", nIn);
+ printf("ERROR: SignatureHash(): nIn=%d out of range\n", nIn);
return one;
}
CMutableTransaction txTmp(txTo);
@@ -58,7 +58,7 @@ uint256 static SignatureHashOld(CScript scriptCode, const CTransaction& txTo, un
unsigned int nOut = nIn;
if (nOut >= txTmp.vout.size())
{
- printf("ERROR: SignatureHash() : nOut=%d out of range\n", nOut);
+ printf("ERROR: SignatureHash(): nOut=%d out of range\n", nOut);
return one;
}
txTmp.vout.resize(nOut+1);
diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp
index 96134cd72e..52adfea992 100644
--- a/src/test/transaction_tests.cpp
+++ b/src/test/transaction_tests.cpp
@@ -145,7 +145,7 @@ BOOST_AUTO_TEST_CASE(tx_valid)
unsigned int verify_flags = ParseScriptFlags(test[2].get_str());
BOOST_CHECK_MESSAGE(VerifyScript(tx.vin[i].scriptSig, mapprevOutScriptPubKeys[tx.vin[i].prevout],
- verify_flags, SignatureChecker(tx, i), &err),
+ verify_flags, TransactionSignatureChecker(&tx, i), &err),
strTest);
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
}
@@ -220,7 +220,7 @@ BOOST_AUTO_TEST_CASE(tx_invalid)
unsigned int verify_flags = ParseScriptFlags(test[2].get_str());
fValid = VerifyScript(tx.vin[i].scriptSig, mapprevOutScriptPubKeys[tx.vin[i].prevout],
- verify_flags, SignatureChecker(tx, i), &err);
+ verify_flags, TransactionSignatureChecker(&tx, i), &err);
}
BOOST_CHECK_MESSAGE(!fValid, strTest);
BOOST_CHECK_MESSAGE(err != SCRIPT_ERR_OK, ScriptErrorString(err));
@@ -347,12 +347,12 @@ BOOST_AUTO_TEST_CASE(test_IsStandard)
t.vout[0].scriptPubKey = CScript() << OP_1;
BOOST_CHECK(!IsStandardTx(t, reason));
- // 40-byte TX_NULL_DATA (standard)
- t.vout[0].scriptPubKey = CScript() << OP_RETURN << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38");
+ // 80-byte TX_NULL_DATA (standard)
+ t.vout[0].scriptPubKey = CScript() << OP_RETURN << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef3804678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38");
BOOST_CHECK(IsStandardTx(t, reason));
- // 41-byte TX_NULL_DATA (non-standard)
- t.vout[0].scriptPubKey = CScript() << OP_RETURN << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef3800");
+ // 81-byte TX_NULL_DATA (non-standard)
+ t.vout[0].scriptPubKey = CScript() << OP_RETURN << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef3804678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef3800");
BOOST_CHECK(!IsStandardTx(t, reason));
// TX_NULL_DATA w/o PUSHDATA
diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp
index 1c5778abed..d829ec228d 100644
--- a/src/test/util_tests.cpp
+++ b/src/test/util_tests.cpp
@@ -282,21 +282,21 @@ BOOST_AUTO_TEST_CASE(strprintf_numbers)
{
int64_t s64t = -9223372036854775807LL; /* signed 64 bit test value */
uint64_t u64t = 18446744073709551615ULL; /* unsigned 64 bit test value */
- BOOST_CHECK(strprintf("%s %d %s", B, s64t, E) == B" -9223372036854775807 "E);
- BOOST_CHECK(strprintf("%s %u %s", B, u64t, E) == B" 18446744073709551615 "E);
- BOOST_CHECK(strprintf("%s %x %s", B, u64t, E) == B" ffffffffffffffff "E);
+ BOOST_CHECK(strprintf("%s %d %s", B, s64t, E) == B" -9223372036854775807 " E);
+ BOOST_CHECK(strprintf("%s %u %s", B, u64t, E) == B" 18446744073709551615 " E);
+ BOOST_CHECK(strprintf("%s %x %s", B, u64t, E) == B" ffffffffffffffff " E);
size_t st = 12345678; /* unsigned size_t test value */
ssize_t sst = -12345678; /* signed size_t test value */
- BOOST_CHECK(strprintf("%s %d %s", B, sst, E) == B" -12345678 "E);
- BOOST_CHECK(strprintf("%s %u %s", B, st, E) == B" 12345678 "E);
- BOOST_CHECK(strprintf("%s %x %s", B, st, E) == B" bc614e "E);
+ BOOST_CHECK(strprintf("%s %d %s", B, sst, E) == B" -12345678 " E);
+ BOOST_CHECK(strprintf("%s %u %s", B, st, E) == B" 12345678 " E);
+ BOOST_CHECK(strprintf("%s %x %s", B, st, E) == B" bc614e " E);
ptrdiff_t pt = 87654321; /* positive ptrdiff_t test value */
ptrdiff_t spt = -87654321; /* negative ptrdiff_t test value */
- BOOST_CHECK(strprintf("%s %d %s", B, spt, E) == B" -87654321 "E);
- BOOST_CHECK(strprintf("%s %u %s", B, pt, E) == B" 87654321 "E);
- BOOST_CHECK(strprintf("%s %x %s", B, pt, E) == B" 5397fb1 "E);
+ BOOST_CHECK(strprintf("%s %d %s", B, spt, E) == B" -87654321 " E);
+ BOOST_CHECK(strprintf("%s %u %s", B, pt, E) == B" 87654321 " E);
+ BOOST_CHECK(strprintf("%s %x %s", B, pt, E) == B" 5397fb1 " E);
}
#undef B
#undef E
diff --git a/src/txdb.cpp b/src/txdb.cpp
index 4467cdce70..da271bd5d1 100644
--- a/src/txdb.cpp
+++ b/src/txdb.cpp
@@ -14,31 +14,42 @@
using namespace std;
+static const char DB_COINS = 'c';
+static const char DB_BLOCK_FILES = 'f';
+static const char DB_TXINDEX = 't';
+static const char DB_BLOCK_INDEX = 'b';
+
+static const char DB_BEST_BLOCK = 'B';
+static const char DB_FLAG = 'F';
+static const char DB_REINDEX_FLAG = 'R';
+static const char DB_LAST_BLOCK = 'l';
+
+
void static BatchWriteCoins(CLevelDBBatch &batch, const uint256 &hash, const CCoins &coins) {
if (coins.IsPruned())
- batch.Erase(make_pair('c', hash));
+ batch.Erase(make_pair(DB_COINS, hash));
else
- batch.Write(make_pair('c', hash), coins);
+ batch.Write(make_pair(DB_COINS, hash), coins);
}
void static BatchWriteHashBestChain(CLevelDBBatch &batch, const uint256 &hash) {
- batch.Write('B', hash);
+ batch.Write(DB_BEST_BLOCK, hash);
}
CCoinsViewDB::CCoinsViewDB(size_t nCacheSize, bool fMemory, bool fWipe) : db(GetDataDir() / "chainstate", nCacheSize, fMemory, fWipe) {
}
bool CCoinsViewDB::GetCoins(const uint256 &txid, CCoins &coins) const {
- return db.Read(make_pair('c', txid), coins);
+ return db.Read(make_pair(DB_COINS, txid), coins);
}
bool CCoinsViewDB::HaveCoins(const uint256 &txid) const {
- return db.Exists(make_pair('c', txid));
+ return db.Exists(make_pair(DB_COINS, txid));
}
uint256 CCoinsViewDB::GetBestBlock() const {
uint256 hashBestChain;
- if (!db.Read('B', hashBestChain))
+ if (!db.Read(DB_BEST_BLOCK, hashBestChain))
return uint256();
return hashBestChain;
}
@@ -67,23 +78,23 @@ CBlockTreeDB::CBlockTreeDB(size_t nCacheSize, bool fMemory, bool fWipe) : CLevel
}
bool CBlockTreeDB::ReadBlockFileInfo(int nFile, CBlockFileInfo &info) {
- return Read(make_pair('f', nFile), info);
+ return Read(make_pair(DB_BLOCK_FILES, nFile), info);
}
bool CBlockTreeDB::WriteReindexing(bool fReindexing) {
if (fReindexing)
- return Write('R', '1');
+ return Write(DB_REINDEX_FLAG, '1');
else
- return Erase('R');
+ return Erase(DB_REINDEX_FLAG);
}
bool CBlockTreeDB::ReadReindexing(bool &fReindexing) {
- fReindexing = Exists('R');
+ fReindexing = Exists(DB_REINDEX_FLAG);
return true;
}
bool CBlockTreeDB::ReadLastBlockFile(int &nFile) {
- return Read('l', nFile);
+ return Read(DB_LAST_BLOCK, nFile);
}
bool CCoinsViewDB::GetStats(CCoinsStats &stats) const {
@@ -104,7 +115,7 @@ bool CCoinsViewDB::GetStats(CCoinsStats &stats) const {
CDataStream ssKey(slKey.data(), slKey.data()+slKey.size(), SER_DISK, CLIENT_VERSION);
char chType;
ssKey >> chType;
- if (chType == 'c') {
+ if (chType == DB_COINS) {
leveldb::Slice slValue = pcursor->value();
CDataStream ssValue(slValue.data(), slValue.data()+slValue.size(), SER_DISK, CLIENT_VERSION);
CCoins coins;
@@ -130,7 +141,7 @@ bool CCoinsViewDB::GetStats(CCoinsStats &stats) const {
}
pcursor->Next();
} catch (const std::exception& e) {
- return error("%s : Deserialize or I/O error - %s", __func__, e.what());
+ return error("%s: Deserialize or I/O error - %s", __func__, e.what());
}
}
stats.nHeight = mapBlockIndex.find(GetBestBlock())->second->nHeight;
@@ -142,33 +153,33 @@ bool CCoinsViewDB::GetStats(CCoinsStats &stats) const {
bool CBlockTreeDB::WriteBatchSync(const std::vector<std::pair<int, const CBlockFileInfo*> >& fileInfo, int nLastFile, const std::vector<const CBlockIndex*>& blockinfo) {
CLevelDBBatch batch;
for (std::vector<std::pair<int, const CBlockFileInfo*> >::const_iterator it=fileInfo.begin(); it != fileInfo.end(); it++) {
- batch.Write(make_pair('f', it->first), *it->second);
+ batch.Write(make_pair(DB_BLOCK_FILES, it->first), *it->second);
}
- batch.Write('l', nLastFile);
+ batch.Write(DB_LAST_BLOCK, nLastFile);
for (std::vector<const CBlockIndex*>::const_iterator it=blockinfo.begin(); it != blockinfo.end(); it++) {
- batch.Write(make_pair('b', (*it)->GetBlockHash()), CDiskBlockIndex(*it));
+ batch.Write(make_pair(DB_BLOCK_INDEX, (*it)->GetBlockHash()), CDiskBlockIndex(*it));
}
return WriteBatch(batch, true);
}
bool CBlockTreeDB::ReadTxIndex(const uint256 &txid, CDiskTxPos &pos) {
- return Read(make_pair('t', txid), pos);
+ return Read(make_pair(DB_TXINDEX, txid), pos);
}
bool CBlockTreeDB::WriteTxIndex(const std::vector<std::pair<uint256, CDiskTxPos> >&vect) {
CLevelDBBatch batch;
for (std::vector<std::pair<uint256,CDiskTxPos> >::const_iterator it=vect.begin(); it!=vect.end(); it++)
- batch.Write(make_pair('t', it->first), it->second);
+ batch.Write(make_pair(DB_TXINDEX, it->first), it->second);
return WriteBatch(batch);
}
bool CBlockTreeDB::WriteFlag(const std::string &name, bool fValue) {
- return Write(std::make_pair('F', name), fValue ? '1' : '0');
+ return Write(std::make_pair(DB_FLAG, name), fValue ? '1' : '0');
}
bool CBlockTreeDB::ReadFlag(const std::string &name, bool &fValue) {
char ch;
- if (!Read(std::make_pair('F', name), ch))
+ if (!Read(std::make_pair(DB_FLAG, name), ch))
return false;
fValue = ch == '1';
return true;
@@ -179,7 +190,7 @@ bool CBlockTreeDB::LoadBlockIndexGuts()
boost::scoped_ptr<leveldb::Iterator> pcursor(NewIterator());
CDataStream ssKeySet(SER_DISK, CLIENT_VERSION);
- ssKeySet << make_pair('b', uint256());
+ ssKeySet << make_pair(DB_BLOCK_INDEX, uint256());
pcursor->Seek(ssKeySet.str());
// Load mapBlockIndex
@@ -190,7 +201,7 @@ bool CBlockTreeDB::LoadBlockIndexGuts()
CDataStream ssKey(slKey.data(), slKey.data()+slKey.size(), SER_DISK, CLIENT_VERSION);
char chType;
ssKey >> chType;
- if (chType == 'b') {
+ if (chType == DB_BLOCK_INDEX) {
leveldb::Slice slValue = pcursor->value();
CDataStream ssValue(slValue.data(), slValue.data()+slValue.size(), SER_DISK, CLIENT_VERSION);
CDiskBlockIndex diskindex;
@@ -212,14 +223,14 @@ bool CBlockTreeDB::LoadBlockIndexGuts()
pindexNew->nTx = diskindex.nTx;
if (!CheckProofOfWork(pindexNew->GetBlockHash(), pindexNew->nBits))
- return error("LoadBlockIndex() : CheckProofOfWork failed: %s", pindexNew->ToString());
+ return error("LoadBlockIndex(): CheckProofOfWork failed: %s", pindexNew->ToString());
pcursor->Next();
} else {
break; // if shutdown requested or finished loading block index
}
} catch (const std::exception& e) {
- return error("%s : Deserialize or I/O error - %s", __func__, e.what());
+ return error("%s: Deserialize or I/O error - %s", __func__, e.what());
}
}
diff --git a/src/txmempool.cpp b/src/txmempool.cpp
index 01bf1ec080..6e0f7e9c5a 100644
--- a/src/txmempool.cpp
+++ b/src/txmempool.cpp
@@ -192,7 +192,7 @@ private:
// Neither or both fee and priority sufficient to get confirmed:
// don't know why they got confirmed.
}
- LogPrint("estimatefee", "Seen TX confirm: %s : %s fee/%g priority, took %d blocks\n",
+ LogPrint("estimatefee", "Seen TX confirm: %s: %s fee/%g priority, took %d blocks\n",
assignedTo, feeRate.ToString(), dPriority, nBlocksAgo);
}
@@ -658,7 +658,7 @@ CTxMemPool::WriteFeeEstimates(CAutoFile& fileout) const
minerPolicyEstimator->Write(fileout);
}
catch (const std::exception&) {
- LogPrintf("CTxMemPool::WriteFeeEstimates() : unable to write policy estimator data (non-fatal)");
+ LogPrintf("CTxMemPool::WriteFeeEstimates(): unable to write policy estimator data (non-fatal)");
return false;
}
return true;
@@ -671,13 +671,13 @@ CTxMemPool::ReadFeeEstimates(CAutoFile& filein)
int nVersionRequired, nVersionThatWrote;
filein >> nVersionRequired >> nVersionThatWrote;
if (nVersionRequired > CLIENT_VERSION)
- return error("CTxMemPool::ReadFeeEstimates() : up-version (%d) fee estimate file", nVersionRequired);
+ return error("CTxMemPool::ReadFeeEstimates(): up-version (%d) fee estimate file", nVersionRequired);
LOCK(cs);
minerPolicyEstimator->Read(filein, minRelayFee);
}
catch (const std::exception&) {
- LogPrintf("CTxMemPool::ReadFeeEstimates() : unable to read policy estimator data (non-fatal)");
+ LogPrintf("CTxMemPool::ReadFeeEstimates(): unable to read policy estimator data (non-fatal)");
return false;
}
return true;
diff --git a/src/wallet.cpp b/src/wallet.cpp
index 6c5af3bdc7..b51c4d4b14 100644
--- a/src/wallet.cpp
+++ b/src/wallet.cpp
@@ -88,7 +88,7 @@ CPubKey CWallet::GenerateNewKey()
nTimeFirstKey = nCreationTime;
if (!AddKeyPubKey(secret, pubkey))
- throw std::runtime_error("CWallet::GenerateNewKey() : AddKey failed");
+ throw std::runtime_error("CWallet::GenerateNewKey(): AddKey failed");
return pubkey;
}
@@ -555,7 +555,7 @@ void CWallet::MarkDirty()
}
}
-bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet)
+bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet, CWalletDB* pwalletdb)
{
uint256 hash = wtxIn.GetHash();
@@ -576,7 +576,7 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet)
if (fInsertedNew)
{
wtx.nTimeReceived = GetAdjustedTime();
- wtx.nOrderPos = IncOrderPosNext();
+ wtx.nOrderPos = IncOrderPosNext(pwalletdb);
wtx.nTimeSmart = wtx.nTimeReceived;
if (!wtxIn.hashBlock.IsNull())
@@ -619,7 +619,7 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet)
wtx.nTimeSmart = std::max(latestEntry, std::min(blocktime, latestNow));
}
else
- LogPrintf("AddToWallet() : found %s in block %s not in index\n",
+ LogPrintf("AddToWallet(): found %s in block %s not in index\n",
wtxIn.GetHash().ToString(),
wtxIn.hashBlock.ToString());
}
@@ -653,7 +653,7 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet)
// Write to disk
if (fInsertedNew || fUpdated)
- if (!wtx.WriteToDisk())
+ if (!wtx.WriteToDisk(pwalletdb))
return false;
// Break debit/credit balance caches:
@@ -689,10 +689,16 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pbl
if (fExisted || IsMine(tx) || IsFromMe(tx))
{
CWalletTx wtx(this,tx);
+
// Get merkle branch if transaction was found in a block
if (pblock)
wtx.SetMerkleBranch(*pblock);
- return AddToWallet(wtx);
+
+ // Do not flush the wallet here for performance reasons
+ // this is safe, as in case of a crash, we rescan the necessary blocks on startup through our SetBestChain-mechanism
+ CWalletDB walletdb(strWalletFile, "r+", false);
+
+ return AddToWallet(wtx, false, &walletdb);
}
}
return false;
@@ -916,9 +922,9 @@ void CWalletTx::GetAccountAmounts(const string& strAccount, CAmount& nReceived,
}
-bool CWalletTx::WriteToDisk()
+bool CWalletTx::WriteToDisk(CWalletDB *pwalletdb)
{
- return CWalletDB(pwallet->strWalletFile).WriteTx(GetHash(), *this);
+ return pwalletdb->WriteTx(GetHash(), *this);
}
/**
@@ -1009,6 +1015,193 @@ set<uint256> CWalletTx::GetConflicts() const
return result;
}
+CAmount CWalletTx::GetDebit(const isminefilter& filter) const
+{
+ if (vin.empty())
+ return 0;
+
+ CAmount debit = 0;
+ if(filter & ISMINE_SPENDABLE)
+ {
+ if (fDebitCached)
+ debit += nDebitCached;
+ else
+ {
+ nDebitCached = pwallet->GetDebit(*this, ISMINE_SPENDABLE);
+ fDebitCached = true;
+ debit += nDebitCached;
+ }
+ }
+ if(filter & ISMINE_WATCH_ONLY)
+ {
+ if(fWatchDebitCached)
+ debit += nWatchDebitCached;
+ else
+ {
+ nWatchDebitCached = pwallet->GetDebit(*this, ISMINE_WATCH_ONLY);
+ fWatchDebitCached = true;
+ debit += nWatchDebitCached;
+ }
+ }
+ return debit;
+}
+
+CAmount CWalletTx::GetCredit(const isminefilter& filter) const
+{
+ // Must wait until coinbase is safely deep enough in the chain before valuing it
+ if (IsCoinBase() && GetBlocksToMaturity() > 0)
+ return 0;
+
+ int64_t credit = 0;
+ if (filter & ISMINE_SPENDABLE)
+ {
+ // GetBalance can assume transactions in mapWallet won't change
+ if (fCreditCached)
+ credit += nCreditCached;
+ else
+ {
+ nCreditCached = pwallet->GetCredit(*this, ISMINE_SPENDABLE);
+ fCreditCached = true;
+ credit += nCreditCached;
+ }
+ }
+ if (filter & ISMINE_WATCH_ONLY)
+ {
+ if (fWatchCreditCached)
+ credit += nWatchCreditCached;
+ else
+ {
+ nWatchCreditCached = pwallet->GetCredit(*this, ISMINE_WATCH_ONLY);
+ fWatchCreditCached = true;
+ credit += nWatchCreditCached;
+ }
+ }
+ return credit;
+}
+
+CAmount CWalletTx::GetImmatureCredit(bool fUseCache) const
+{
+ if (IsCoinBase() && GetBlocksToMaturity() > 0 && IsInMainChain())
+ {
+ if (fUseCache && fImmatureCreditCached)
+ return nImmatureCreditCached;
+ nImmatureCreditCached = pwallet->GetCredit(*this, ISMINE_SPENDABLE);
+ fImmatureCreditCached = true;
+ return nImmatureCreditCached;
+ }
+
+ return 0;
+}
+
+CAmount CWalletTx::GetAvailableCredit(bool fUseCache) const
+{
+ if (pwallet == 0)
+ return 0;
+
+ // Must wait until coinbase is safely deep enough in the chain before valuing it
+ if (IsCoinBase() && GetBlocksToMaturity() > 0)
+ return 0;
+
+ if (fUseCache && fAvailableCreditCached)
+ return nAvailableCreditCached;
+
+ CAmount nCredit = 0;
+ uint256 hashTx = GetHash();
+ for (unsigned int i = 0; i < vout.size(); i++)
+ {
+ if (!pwallet->IsSpent(hashTx, i))
+ {
+ const CTxOut &txout = vout[i];
+ nCredit += pwallet->GetCredit(txout, ISMINE_SPENDABLE);
+ if (!MoneyRange(nCredit))
+ throw std::runtime_error("CWalletTx::GetAvailableCredit() : value out of range");
+ }
+ }
+
+ nAvailableCreditCached = nCredit;
+ fAvailableCreditCached = true;
+ return nCredit;
+}
+
+CAmount CWalletTx::GetImmatureWatchOnlyCredit(const bool& fUseCache) const
+{
+ if (IsCoinBase() && GetBlocksToMaturity() > 0 && IsInMainChain())
+ {
+ if (fUseCache && fImmatureWatchCreditCached)
+ return nImmatureWatchCreditCached;
+ nImmatureWatchCreditCached = pwallet->GetCredit(*this, ISMINE_WATCH_ONLY);
+ fImmatureWatchCreditCached = true;
+ return nImmatureWatchCreditCached;
+ }
+
+ return 0;
+}
+
+CAmount CWalletTx::GetAvailableWatchOnlyCredit(const bool& fUseCache) const
+{
+ if (pwallet == 0)
+ return 0;
+
+ // Must wait until coinbase is safely deep enough in the chain before valuing it
+ if (IsCoinBase() && GetBlocksToMaturity() > 0)
+ return 0;
+
+ if (fUseCache && fAvailableWatchCreditCached)
+ return nAvailableWatchCreditCached;
+
+ CAmount nCredit = 0;
+ for (unsigned int i = 0; i < vout.size(); i++)
+ {
+ if (!pwallet->IsSpent(GetHash(), i))
+ {
+ const CTxOut &txout = vout[i];
+ nCredit += pwallet->GetCredit(txout, ISMINE_WATCH_ONLY);
+ if (!MoneyRange(nCredit))
+ throw std::runtime_error("CWalletTx::GetAvailableCredit() : value out of range");
+ }
+ }
+
+ nAvailableWatchCreditCached = nCredit;
+ fAvailableWatchCreditCached = true;
+ return nCredit;
+}
+
+CAmount CWalletTx::GetChange() const
+{
+ if (fChangeCached)
+ return nChangeCached;
+ nChangeCached = pwallet->GetChange(*this);
+ fChangeCached = true;
+ return nChangeCached;
+}
+
+bool CWalletTx::IsTrusted() const
+{
+ // Quick answer in most cases
+ if (!IsFinalTx(*this))
+ return false;
+ int nDepth = GetDepthInMainChain();
+ if (nDepth >= 1)
+ return true;
+ if (nDepth < 0)
+ return false;
+ if (!bSpendZeroConfChange || !IsFromMe(ISMINE_ALL)) // using wtx's cached debit
+ return false;
+
+ // Trusted if all inputs are from us and are in the mempool:
+ BOOST_FOREACH(const CTxIn& txin, vin)
+ {
+ // Transactions not sent by us: not trusted
+ const CWalletTx* parent = pwallet->GetWalletTx(txin.prevout.hash);
+ if (parent == NULL)
+ return false;
+ const CTxOut& parentOut = parent->vout[txin.prevout.n];
+ if (pwallet->IsMine(parentOut) != ISMINE_SPENDABLE)
+ return false;
+ }
+ return true;
+}
+
void CWallet::ResendWalletTransactions()
{
// Do this infrequently and randomly to avoid giving away
@@ -1439,10 +1632,14 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, CAmount> >& vecSend,
BOOST_FOREACH(PAIRTYPE(const CWalletTx*, unsigned int) pcoin, setCoins)
{
CAmount nCredit = pcoin.first->vout[pcoin.second].nValue;
- //The priority after the next block (depth+1) is used instead of the current,
+ //The coin age after the next block (depth+1) is used instead of the current,
//reflecting an assumption the user would accept a bit more delay for
//a chance at a free transaction.
- dPriority += (double)nCredit * (pcoin.first->GetDepthInMainChain()+1);
+ //But mempool inputs might still be in the mempool, so their age stays 0
+ int age = pcoin.first->GetDepthInMainChain();
+ if (age != 0)
+ age += 1;
+ dPriority += (double)nCredit * age;
}
CAmount nChange = nValueIn - nValue - nFeeRet;
@@ -1581,14 +1778,14 @@ bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey)
// This is only to keep the database open to defeat the auto-flush for the
// duration of this scope. This is the only place where this optimization
// maybe makes sense; please don't do it anywhere else.
- CWalletDB* pwalletdb = fFileBacked ? new CWalletDB(strWalletFile,"r") : NULL;
+ CWalletDB* pwalletdb = fFileBacked ? new CWalletDB(strWalletFile,"r+") : NULL;
// Take key pair from key pool so it won't be used again
reservekey.KeepKey();
// Add tx to wallet, because if it has change it's also ours,
// otherwise just for transaction history.
- AddToWallet(wtxNew);
+ AddToWallet(wtxNew, false, pwalletdb);
// Notify that old coins are spent
set<CWalletTx*> setCoins;
@@ -1610,7 +1807,7 @@ bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey)
if (!wtxNew.AcceptToMemoryPool(false))
{
// This must not fail. The transaction has already been signed and recorded.
- LogPrintf("CommitTransaction() : Error: Transaction not valid");
+ LogPrintf("CommitTransaction(): Error: Transaction not valid");
return false;
}
wtxNew.RelayWalletTransaction();
@@ -1803,7 +2000,7 @@ bool CWallet::TopUpKeyPool(unsigned int kpSize)
if (!setKeyPool.empty())
nEnd = *(--setKeyPool.end()) + 1;
if (!walletdb.WritePool(nEnd, CKeyPool(GenerateNewKey())))
- throw runtime_error("TopUpKeyPool() : writing generated key failed");
+ throw runtime_error("TopUpKeyPool(): writing generated key failed");
setKeyPool.insert(nEnd);
LogPrintf("keypool added key %d, size=%u\n", nEnd, setKeyPool.size());
}
@@ -1830,9 +2027,9 @@ void CWallet::ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool)
nIndex = *(setKeyPool.begin());
setKeyPool.erase(setKeyPool.begin());
if (!walletdb.ReadPool(nIndex, keypool))
- throw runtime_error("ReserveKeyFromKeyPool() : read failed");
+ throw runtime_error("ReserveKeyFromKeyPool(): read failed");
if (!HaveKey(keypool.vchPubKey.GetID()))
- throw runtime_error("ReserveKeyFromKeyPool() : unknown key in key pool");
+ throw runtime_error("ReserveKeyFromKeyPool(): unknown key in key pool");
assert(keypool.vchPubKey.IsValid());
LogPrintf("keypool reserve %d\n", nIndex);
}
@@ -2080,11 +2277,11 @@ void CWallet::GetAllReserveKeys(set<CKeyID>& setAddress) const
{
CKeyPool keypool;
if (!walletdb.ReadPool(id, keypool))
- throw runtime_error("GetAllReserveKeyHashes() : read failed");
+ throw runtime_error("GetAllReserveKeyHashes(): read failed");
assert(keypool.vchPubKey.IsValid());
CKeyID keyID = keypool.vchPubKey.GetID();
if (!HaveKey(keyID))
- throw runtime_error("GetAllReserveKeyHashes() : unknown key in key pool");
+ throw runtime_error("GetAllReserveKeyHashes(): unknown key in key pool");
setAddress.insert(keyID);
}
}
@@ -2297,7 +2494,7 @@ int CMerkleTx::SetMerkleBranch(const CBlock& block)
{
vMerkleBranch.clear();
nIndex = -1;
- LogPrintf("ERROR: SetMerkleBranch() : couldn't find tx in block\n");
+ LogPrintf("ERROR: SetMerkleBranch(): couldn't find tx in block\n");
return 0;
}
@@ -2359,9 +2556,9 @@ int CMerkleTx::GetBlocksToMaturity() const
}
-bool CMerkleTx::AcceptToMemoryPool(bool fLimitFree, bool fRejectInsaneFee)
+bool CMerkleTx::AcceptToMemoryPool(bool fLimitFree, bool fRejectAbsurdFee)
{
CValidationState state;
- return ::AcceptToMemoryPool(mempool, state, *this, fLimitFree, NULL, fRejectInsaneFee);
+ return ::AcceptToMemoryPool(mempool, state, *this, fLimitFree, NULL, fRejectAbsurdFee);
}
diff --git a/src/wallet.h b/src/wallet.h
index 1d0dc97c6c..6ed87d1e68 100644
--- a/src/wallet.h
+++ b/src/wallet.h
@@ -103,6 +103,329 @@ public:
StringMap destdata;
};
+
+typedef std::map<std::string, std::string> mapValue_t;
+
+
+static void ReadOrderPos(int64_t& nOrderPos, mapValue_t& mapValue)
+{
+ if (!mapValue.count("n"))
+ {
+ nOrderPos = -1; // TODO: calculate elsewhere
+ return;
+ }
+ nOrderPos = atoi64(mapValue["n"].c_str());
+}
+
+
+static void WriteOrderPos(const int64_t& nOrderPos, mapValue_t& mapValue)
+{
+ if (nOrderPos == -1)
+ return;
+ mapValue["n"] = i64tostr(nOrderPos);
+}
+
+struct COutputEntry
+{
+ CTxDestination destination;
+ CAmount amount;
+ int vout;
+};
+
+/** A transaction with a merkle branch linking it to the block chain. */
+class CMerkleTx : public CTransaction
+{
+private:
+ int GetDepthInMainChainINTERNAL(const CBlockIndex* &pindexRet) const;
+
+public:
+ uint256 hashBlock;
+ std::vector<uint256> vMerkleBranch;
+ int nIndex;
+
+ // memory only
+ mutable bool fMerkleVerified;
+
+
+ CMerkleTx()
+ {
+ Init();
+ }
+
+ CMerkleTx(const CTransaction& txIn) : CTransaction(txIn)
+ {
+ Init();
+ }
+
+ void Init()
+ {
+ hashBlock = uint256();
+ nIndex = -1;
+ fMerkleVerified = false;
+ }
+
+ ADD_SERIALIZE_METHODS;
+
+ template <typename Stream, typename Operation>
+ inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
+ READWRITE(*(CTransaction*)this);
+ nVersion = this->nVersion;
+ READWRITE(hashBlock);
+ READWRITE(vMerkleBranch);
+ READWRITE(nIndex);
+ }
+
+ int SetMerkleBranch(const CBlock& block);
+
+
+ /**
+ * Return depth of transaction in blockchain:
+ * -1 : not in blockchain, and not in memory pool (conflicted transaction)
+ * 0 : in memory pool, waiting to be included in a block
+ * >=1 : this many blocks deep in the main chain
+ */
+ int GetDepthInMainChain(const CBlockIndex* &pindexRet) const;
+ int GetDepthInMainChain() const { const CBlockIndex *pindexRet; return GetDepthInMainChain(pindexRet); }
+ bool IsInMainChain() const { const CBlockIndex *pindexRet; return GetDepthInMainChainINTERNAL(pindexRet) > 0; }
+ int GetBlocksToMaturity() const;
+ bool AcceptToMemoryPool(bool fLimitFree=true, bool fRejectAbsurdFee=true);
+};
+
+/**
+ * A transaction with a bunch of additional info that only the owner cares about.
+ * It includes any unrecorded transactions needed to link it back to the block chain.
+ */
+class CWalletTx : public CMerkleTx
+{
+private:
+ const CWallet* pwallet;
+
+public:
+ mapValue_t mapValue;
+ std::vector<std::pair<std::string, std::string> > vOrderForm;
+ unsigned int fTimeReceivedIsTxTime;
+ unsigned int nTimeReceived; //! time received by this node
+ unsigned int nTimeSmart;
+ char fFromMe;
+ std::string strFromAccount;
+ int64_t nOrderPos; //! position in ordered transaction list
+
+ // memory only
+ mutable bool fDebitCached;
+ mutable bool fCreditCached;
+ mutable bool fImmatureCreditCached;
+ mutable bool fAvailableCreditCached;
+ mutable bool fWatchDebitCached;
+ mutable bool fWatchCreditCached;
+ mutable bool fImmatureWatchCreditCached;
+ mutable bool fAvailableWatchCreditCached;
+ mutable bool fChangeCached;
+ mutable CAmount nDebitCached;
+ mutable CAmount nCreditCached;
+ mutable CAmount nImmatureCreditCached;
+ mutable CAmount nAvailableCreditCached;
+ mutable CAmount nWatchDebitCached;
+ mutable CAmount nWatchCreditCached;
+ mutable CAmount nImmatureWatchCreditCached;
+ mutable CAmount nAvailableWatchCreditCached;
+ mutable CAmount nChangeCached;
+
+ CWalletTx()
+ {
+ Init(NULL);
+ }
+
+ CWalletTx(const CWallet* pwalletIn)
+ {
+ Init(pwalletIn);
+ }
+
+ CWalletTx(const CWallet* pwalletIn, const CMerkleTx& txIn) : CMerkleTx(txIn)
+ {
+ Init(pwalletIn);
+ }
+
+ CWalletTx(const CWallet* pwalletIn, const CTransaction& txIn) : CMerkleTx(txIn)
+ {
+ Init(pwalletIn);
+ }
+
+ void Init(const CWallet* pwalletIn)
+ {
+ pwallet = pwalletIn;
+ mapValue.clear();
+ vOrderForm.clear();
+ fTimeReceivedIsTxTime = false;
+ nTimeReceived = 0;
+ nTimeSmart = 0;
+ fFromMe = false;
+ strFromAccount.clear();
+ fDebitCached = false;
+ fCreditCached = false;
+ fImmatureCreditCached = false;
+ fAvailableCreditCached = false;
+ fWatchDebitCached = false;
+ fWatchCreditCached = false;
+ fImmatureWatchCreditCached = false;
+ fAvailableWatchCreditCached = false;
+ fChangeCached = false;
+ nDebitCached = 0;
+ nCreditCached = 0;
+ nImmatureCreditCached = 0;
+ nAvailableCreditCached = 0;
+ nWatchDebitCached = 0;
+ nWatchCreditCached = 0;
+ nAvailableWatchCreditCached = 0;
+ nImmatureWatchCreditCached = 0;
+ nChangeCached = 0;
+ nOrderPos = -1;
+ }
+
+ ADD_SERIALIZE_METHODS;
+
+ template <typename Stream, typename Operation>
+ inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
+ if (ser_action.ForRead())
+ Init(NULL);
+ char fSpent = false;
+
+ if (!ser_action.ForRead())
+ {
+ mapValue["fromaccount"] = strFromAccount;
+
+ WriteOrderPos(nOrderPos, mapValue);
+
+ if (nTimeSmart)
+ mapValue["timesmart"] = strprintf("%u", nTimeSmart);
+ }
+
+ READWRITE(*(CMerkleTx*)this);
+ std::vector<CMerkleTx> vUnused; //! Used to be vtxPrev
+ READWRITE(vUnused);
+ READWRITE(mapValue);
+ READWRITE(vOrderForm);
+ READWRITE(fTimeReceivedIsTxTime);
+ READWRITE(nTimeReceived);
+ READWRITE(fFromMe);
+ READWRITE(fSpent);
+
+ if (ser_action.ForRead())
+ {
+ strFromAccount = mapValue["fromaccount"];
+
+ ReadOrderPos(nOrderPos, mapValue);
+
+ nTimeSmart = mapValue.count("timesmart") ? (unsigned int)atoi64(mapValue["timesmart"]) : 0;
+ }
+
+ mapValue.erase("fromaccount");
+ mapValue.erase("version");
+ mapValue.erase("spent");
+ mapValue.erase("n");
+ mapValue.erase("timesmart");
+ }
+
+ //! make sure balances are recalculated
+ void MarkDirty()
+ {
+ fCreditCached = false;
+ fAvailableCreditCached = false;
+ fWatchDebitCached = false;
+ fWatchCreditCached = false;
+ fAvailableWatchCreditCached = false;
+ fImmatureWatchCreditCached = false;
+ fDebitCached = false;
+ fChangeCached = false;
+ }
+
+ void BindWallet(CWallet *pwalletIn)
+ {
+ pwallet = pwalletIn;
+ MarkDirty();
+ }
+
+ //! filter decides which addresses will count towards the debit
+ CAmount GetDebit(const isminefilter& filter) const;
+ CAmount GetCredit(const isminefilter& filter) const;
+ CAmount GetImmatureCredit(bool fUseCache=true) const;
+ CAmount GetAvailableCredit(bool fUseCache=true) const;
+ CAmount GetImmatureWatchOnlyCredit(const bool& fUseCache=true) const;
+ CAmount GetAvailableWatchOnlyCredit(const bool& fUseCache=true) const;
+ CAmount GetChange() const;
+
+ void GetAmounts(std::list<COutputEntry>& listReceived,
+ std::list<COutputEntry>& listSent, CAmount& nFee, std::string& strSentAccount, const isminefilter& filter) const;
+
+ void GetAccountAmounts(const std::string& strAccount, CAmount& nReceived,
+ CAmount& nSent, CAmount& nFee, const isminefilter& filter) const;
+
+ bool IsFromMe(const isminefilter& filter) const
+ {
+ return (GetDebit(filter) > 0);
+ }
+
+ bool IsTrusted() const;
+
+ bool WriteToDisk(CWalletDB *pwalletdb);
+
+ int64_t GetTxTime() const;
+ int GetRequestCount() const;
+
+ void RelayWalletTransaction();
+
+ std::set<uint256> GetConflicts() const;
+};
+
+
+
+
+class COutput
+{
+public:
+ const CWalletTx *tx;
+ int i;
+ int nDepth;
+ bool fSpendable;
+
+ COutput(const CWalletTx *txIn, int iIn, int nDepthIn, bool fSpendableIn)
+ {
+ tx = txIn; i = iIn; nDepth = nDepthIn; fSpendable = fSpendableIn;
+ }
+
+ std::string ToString() const;
+};
+
+
+
+
+/** Private key that includes an expiration date in case it never gets used. */
+class CWalletKey
+{
+public:
+ CPrivKey vchPrivKey;
+ int64_t nTimeCreated;
+ int64_t nTimeExpires;
+ std::string strComment;
+ //! todo: add something to note what created it (user, getnewaddress, change)
+ //! maybe should have a map<string, string> property map
+
+ CWalletKey(int64_t nExpires=0);
+
+ ADD_SERIALIZE_METHODS;
+
+ template <typename Stream, typename Operation>
+ inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
+ if (!(nType & SER_GETHASH))
+ READWRITE(nVersion);
+ READWRITE(vchPrivKey);
+ READWRITE(nTimeCreated);
+ READWRITE(nTimeExpires);
+ READWRITE(LIMITED_STRING(strComment, 65536));
+ }
+};
+
+
+
/**
* A CWallet is an extension of a keystore, which also maintains a set of transactions and balances,
* and provides the ability to create new transactions.
@@ -275,7 +598,7 @@ public:
TxItems OrderedTxItems(std::list<CAccountingEntry>& acentries, std::string strAccount = "");
void MarkDirty();
- bool AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet=false);
+ bool AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet, CWalletDB* pwalletdb);
void SyncTransaction(const CTransaction& tx, const CBlock* pblock);
bool AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate);
void EraseFromWallet(const uint256 &hash);
@@ -320,14 +643,14 @@ public:
CAmount GetCredit(const CTxOut& txout, const isminefilter& filter) const
{
if (!MoneyRange(txout.nValue))
- throw std::runtime_error("CWallet::GetCredit() : value out of range");
+ throw std::runtime_error("CWallet::GetCredit(): value out of range");
return ((IsMine(txout) & filter) ? txout.nValue : 0);
}
bool IsChange(const CTxOut& txout) const;
CAmount GetChange(const CTxOut& txout) const
{
if (!MoneyRange(txout.nValue))
- throw std::runtime_error("CWallet::GetChange() : value out of range");
+ throw std::runtime_error("CWallet::GetChange(): value out of range");
return (IsChange(txout) ? txout.nValue : 0);
}
bool IsMine(const CTransaction& tx) const
@@ -349,7 +672,7 @@ public:
{
nDebit += GetDebit(txin, filter);
if (!MoneyRange(nDebit))
- throw std::runtime_error("CWallet::GetDebit() : value out of range");
+ throw std::runtime_error("CWallet::GetDebit(): value out of range");
}
return nDebit;
}
@@ -360,7 +683,7 @@ public:
{
nCredit += GetCredit(txout, filter);
if (!MoneyRange(nCredit))
- throw std::runtime_error("CWallet::GetCredit() : value out of range");
+ throw std::runtime_error("CWallet::GetCredit(): value out of range");
}
return nCredit;
}
@@ -371,7 +694,7 @@ public:
{
nChange += GetChange(txout);
if (!MoneyRange(nChange))
- throw std::runtime_error("CWallet::GetChange() : value out of range");
+ throw std::runtime_error("CWallet::GetChange(): value out of range");
}
return nChange;
}
@@ -464,508 +787,6 @@ public:
};
-typedef std::map<std::string, std::string> mapValue_t;
-
-
-static void ReadOrderPos(int64_t& nOrderPos, mapValue_t& mapValue)
-{
- if (!mapValue.count("n"))
- {
- nOrderPos = -1; // TODO: calculate elsewhere
- return;
- }
- nOrderPos = atoi64(mapValue["n"].c_str());
-}
-
-
-static void WriteOrderPos(const int64_t& nOrderPos, mapValue_t& mapValue)
-{
- if (nOrderPos == -1)
- return;
- mapValue["n"] = i64tostr(nOrderPos);
-}
-
-struct COutputEntry
-{
- CTxDestination destination;
- CAmount amount;
- int vout;
-};
-
-/** A transaction with a merkle branch linking it to the block chain. */
-class CMerkleTx : public CTransaction
-{
-private:
- int GetDepthInMainChainINTERNAL(const CBlockIndex* &pindexRet) const;
-
-public:
- uint256 hashBlock;
- std::vector<uint256> vMerkleBranch;
- int nIndex;
-
- // memory only
- mutable bool fMerkleVerified;
-
-
- CMerkleTx()
- {
- Init();
- }
-
- CMerkleTx(const CTransaction& txIn) : CTransaction(txIn)
- {
- Init();
- }
-
- void Init()
- {
- hashBlock = uint256();
- nIndex = -1;
- fMerkleVerified = false;
- }
-
- ADD_SERIALIZE_METHODS;
-
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
- READWRITE(*(CTransaction*)this);
- nVersion = this->nVersion;
- READWRITE(hashBlock);
- READWRITE(vMerkleBranch);
- READWRITE(nIndex);
- }
-
- int SetMerkleBranch(const CBlock& block);
-
-
- /**
- * Return depth of transaction in blockchain:
- * -1 : not in blockchain, and not in memory pool (conflicted transaction)
- * 0 : in memory pool, waiting to be included in a block
- * >=1 : this many blocks deep in the main chain
- */
- int GetDepthInMainChain(const CBlockIndex* &pindexRet) const;
- int GetDepthInMainChain() const { const CBlockIndex *pindexRet; return GetDepthInMainChain(pindexRet); }
- bool IsInMainChain() const { const CBlockIndex *pindexRet; return GetDepthInMainChainINTERNAL(pindexRet) > 0; }
- int GetBlocksToMaturity() const;
- bool AcceptToMemoryPool(bool fLimitFree=true, bool fRejectInsaneFee=true);
-};
-
-/**
- * A transaction with a bunch of additional info that only the owner cares about.
- * It includes any unrecorded transactions needed to link it back to the block chain.
- */
-class CWalletTx : public CMerkleTx
-{
-private:
- const CWallet* pwallet;
-
-public:
- mapValue_t mapValue;
- std::vector<std::pair<std::string, std::string> > vOrderForm;
- unsigned int fTimeReceivedIsTxTime;
- unsigned int nTimeReceived; //! time received by this node
- unsigned int nTimeSmart;
- char fFromMe;
- std::string strFromAccount;
- int64_t nOrderPos; //! position in ordered transaction list
-
- // memory only
- mutable bool fDebitCached;
- mutable bool fCreditCached;
- mutable bool fImmatureCreditCached;
- mutable bool fAvailableCreditCached;
- mutable bool fWatchDebitCached;
- mutable bool fWatchCreditCached;
- mutable bool fImmatureWatchCreditCached;
- mutable bool fAvailableWatchCreditCached;
- mutable bool fChangeCached;
- mutable CAmount nDebitCached;
- mutable CAmount nCreditCached;
- mutable CAmount nImmatureCreditCached;
- mutable CAmount nAvailableCreditCached;
- mutable CAmount nWatchDebitCached;
- mutable CAmount nWatchCreditCached;
- mutable CAmount nImmatureWatchCreditCached;
- mutable CAmount nAvailableWatchCreditCached;
- mutable CAmount nChangeCached;
-
- CWalletTx()
- {
- Init(NULL);
- }
-
- CWalletTx(const CWallet* pwalletIn)
- {
- Init(pwalletIn);
- }
-
- CWalletTx(const CWallet* pwalletIn, const CMerkleTx& txIn) : CMerkleTx(txIn)
- {
- Init(pwalletIn);
- }
-
- CWalletTx(const CWallet* pwalletIn, const CTransaction& txIn) : CMerkleTx(txIn)
- {
- Init(pwalletIn);
- }
-
- void Init(const CWallet* pwalletIn)
- {
- pwallet = pwalletIn;
- mapValue.clear();
- vOrderForm.clear();
- fTimeReceivedIsTxTime = false;
- nTimeReceived = 0;
- nTimeSmart = 0;
- fFromMe = false;
- strFromAccount.clear();
- fDebitCached = false;
- fCreditCached = false;
- fImmatureCreditCached = false;
- fAvailableCreditCached = false;
- fWatchDebitCached = false;
- fWatchCreditCached = false;
- fImmatureWatchCreditCached = false;
- fAvailableWatchCreditCached = false;
- fChangeCached = false;
- nDebitCached = 0;
- nCreditCached = 0;
- nImmatureCreditCached = 0;
- nAvailableCreditCached = 0;
- nWatchDebitCached = 0;
- nWatchCreditCached = 0;
- nAvailableWatchCreditCached = 0;
- nImmatureWatchCreditCached = 0;
- nChangeCached = 0;
- nOrderPos = -1;
- }
-
- ADD_SERIALIZE_METHODS;
-
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
- if (ser_action.ForRead())
- Init(NULL);
- char fSpent = false;
-
- if (!ser_action.ForRead())
- {
- mapValue["fromaccount"] = strFromAccount;
-
- WriteOrderPos(nOrderPos, mapValue);
-
- if (nTimeSmart)
- mapValue["timesmart"] = strprintf("%u", nTimeSmart);
- }
-
- READWRITE(*(CMerkleTx*)this);
- std::vector<CMerkleTx> vUnused; //! Used to be vtxPrev
- READWRITE(vUnused);
- READWRITE(mapValue);
- READWRITE(vOrderForm);
- READWRITE(fTimeReceivedIsTxTime);
- READWRITE(nTimeReceived);
- READWRITE(fFromMe);
- READWRITE(fSpent);
-
- if (ser_action.ForRead())
- {
- strFromAccount = mapValue["fromaccount"];
-
- ReadOrderPos(nOrderPos, mapValue);
-
- nTimeSmart = mapValue.count("timesmart") ? (unsigned int)atoi64(mapValue["timesmart"]) : 0;
- }
-
- mapValue.erase("fromaccount");
- mapValue.erase("version");
- mapValue.erase("spent");
- mapValue.erase("n");
- mapValue.erase("timesmart");
- }
-
- //! make sure balances are recalculated
- void MarkDirty()
- {
- fCreditCached = false;
- fAvailableCreditCached = false;
- fWatchDebitCached = false;
- fWatchCreditCached = false;
- fAvailableWatchCreditCached = false;
- fImmatureWatchCreditCached = false;
- fDebitCached = false;
- fChangeCached = false;
- }
-
- void BindWallet(CWallet *pwalletIn)
- {
- pwallet = pwalletIn;
- MarkDirty();
- }
-
- //! filter decides which addresses will count towards the debit
- CAmount GetDebit(const isminefilter& filter) const
- {
- if (vin.empty())
- return 0;
-
- CAmount debit = 0;
- if(filter & ISMINE_SPENDABLE)
- {
- if (fDebitCached)
- debit += nDebitCached;
- else
- {
- nDebitCached = pwallet->GetDebit(*this, ISMINE_SPENDABLE);
- fDebitCached = true;
- debit += nDebitCached;
- }
- }
- if(filter & ISMINE_WATCH_ONLY)
- {
- if(fWatchDebitCached)
- debit += nWatchDebitCached;
- else
- {
- nWatchDebitCached = pwallet->GetDebit(*this, ISMINE_WATCH_ONLY);
- fWatchDebitCached = true;
- debit += nWatchDebitCached;
- }
- }
- return debit;
- }
-
- CAmount GetCredit(const isminefilter& filter) const
- {
- // Must wait until coinbase is safely deep enough in the chain before valuing it
- if (IsCoinBase() && GetBlocksToMaturity() > 0)
- return 0;
-
- int64_t credit = 0;
- if (filter & ISMINE_SPENDABLE)
- {
- // GetBalance can assume transactions in mapWallet won't change
- if (fCreditCached)
- credit += nCreditCached;
- else
- {
- nCreditCached = pwallet->GetCredit(*this, ISMINE_SPENDABLE);
- fCreditCached = true;
- credit += nCreditCached;
- }
- }
- if (filter & ISMINE_WATCH_ONLY)
- {
- if (fWatchCreditCached)
- credit += nWatchCreditCached;
- else
- {
- nWatchCreditCached = pwallet->GetCredit(*this, ISMINE_WATCH_ONLY);
- fWatchCreditCached = true;
- credit += nWatchCreditCached;
- }
- }
- return credit;
- }
-
- CAmount GetImmatureCredit(bool fUseCache=true) const
- {
- if (IsCoinBase() && GetBlocksToMaturity() > 0 && IsInMainChain())
- {
- if (fUseCache && fImmatureCreditCached)
- return nImmatureCreditCached;
- nImmatureCreditCached = pwallet->GetCredit(*this, ISMINE_SPENDABLE);
- fImmatureCreditCached = true;
- return nImmatureCreditCached;
- }
-
- return 0;
- }
-
- CAmount GetAvailableCredit(bool fUseCache=true) const
- {
- if (pwallet == 0)
- return 0;
-
- // Must wait until coinbase is safely deep enough in the chain before valuing it
- if (IsCoinBase() && GetBlocksToMaturity() > 0)
- return 0;
-
- if (fUseCache && fAvailableCreditCached)
- return nAvailableCreditCached;
-
- CAmount nCredit = 0;
- uint256 hashTx = GetHash();
- for (unsigned int i = 0; i < vout.size(); i++)
- {
- if (!pwallet->IsSpent(hashTx, i))
- {
- const CTxOut &txout = vout[i];
- nCredit += pwallet->GetCredit(txout, ISMINE_SPENDABLE);
- if (!MoneyRange(nCredit))
- throw std::runtime_error("CWalletTx::GetAvailableCredit() : value out of range");
- }
- }
-
- nAvailableCreditCached = nCredit;
- fAvailableCreditCached = true;
- return nCredit;
- }
-
- CAmount GetImmatureWatchOnlyCredit(const bool& fUseCache=true) const
- {
- if (IsCoinBase() && GetBlocksToMaturity() > 0 && IsInMainChain())
- {
- if (fUseCache && fImmatureWatchCreditCached)
- return nImmatureWatchCreditCached;
- nImmatureWatchCreditCached = pwallet->GetCredit(*this, ISMINE_WATCH_ONLY);
- fImmatureWatchCreditCached = true;
- return nImmatureWatchCreditCached;
- }
-
- return 0;
- }
-
- CAmount GetAvailableWatchOnlyCredit(const bool& fUseCache=true) const
- {
- if (pwallet == 0)
- return 0;
-
- // Must wait until coinbase is safely deep enough in the chain before valuing it
- if (IsCoinBase() && GetBlocksToMaturity() > 0)
- return 0;
-
- if (fUseCache && fAvailableWatchCreditCached)
- return nAvailableWatchCreditCached;
-
- CAmount nCredit = 0;
- for (unsigned int i = 0; i < vout.size(); i++)
- {
- if (!pwallet->IsSpent(GetHash(), i))
- {
- const CTxOut &txout = vout[i];
- nCredit += pwallet->GetCredit(txout, ISMINE_WATCH_ONLY);
- if (!MoneyRange(nCredit))
- throw std::runtime_error("CWalletTx::GetAvailableCredit() : value out of range");
- }
- }
-
- nAvailableWatchCreditCached = nCredit;
- fAvailableWatchCreditCached = true;
- return nCredit;
- }
-
- CAmount GetChange() const
- {
- if (fChangeCached)
- return nChangeCached;
- nChangeCached = pwallet->GetChange(*this);
- fChangeCached = true;
- return nChangeCached;
- }
-
- void GetAmounts(std::list<COutputEntry>& listReceived,
- std::list<COutputEntry>& listSent, CAmount& nFee, std::string& strSentAccount, const isminefilter& filter) const;
-
- void GetAccountAmounts(const std::string& strAccount, CAmount& nReceived,
- CAmount& nSent, CAmount& nFee, const isminefilter& filter) const;
-
- bool IsFromMe(const isminefilter& filter) const
- {
- return (GetDebit(filter) > 0);
- }
-
- bool IsTrusted() const
- {
- // Quick answer in most cases
- if (!IsFinalTx(*this))
- return false;
- int nDepth = GetDepthInMainChain();
- if (nDepth >= 1)
- return true;
- if (nDepth < 0)
- return false;
- if (!bSpendZeroConfChange || !IsFromMe(ISMINE_ALL)) // using wtx's cached debit
- return false;
-
- // Trusted if all inputs are from us and are in the mempool:
- BOOST_FOREACH(const CTxIn& txin, vin)
- {
- // Transactions not sent by us: not trusted
- const CWalletTx* parent = pwallet->GetWalletTx(txin.prevout.hash);
- if (parent == NULL)
- return false;
- const CTxOut& parentOut = parent->vout[txin.prevout.n];
- if (pwallet->IsMine(parentOut) != ISMINE_SPENDABLE)
- return false;
- }
- return true;
- }
-
- bool WriteToDisk();
-
- int64_t GetTxTime() const;
- int GetRequestCount() const;
-
- void RelayWalletTransaction();
-
- std::set<uint256> GetConflicts() const;
-};
-
-
-
-
-class COutput
-{
-public:
- const CWalletTx *tx;
- int i;
- int nDepth;
- bool fSpendable;
-
- COutput(const CWalletTx *txIn, int iIn, int nDepthIn, bool fSpendableIn)
- {
- tx = txIn; i = iIn; nDepth = nDepthIn; fSpendable = fSpendableIn;
- }
-
- std::string ToString() const;
-};
-
-
-
-
-/** Private key that includes an expiration date in case it never gets used. */
-class CWalletKey
-{
-public:
- CPrivKey vchPrivKey;
- int64_t nTimeCreated;
- int64_t nTimeExpires;
- std::string strComment;
- //! todo: add something to note what created it (user, getnewaddress, change)
- //! maybe should have a map<string, string> property map
-
- CWalletKey(int64_t nExpires=0);
-
- ADD_SERIALIZE_METHODS;
-
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
- if (!(nType & SER_GETHASH))
- READWRITE(nVersion);
- READWRITE(vchPrivKey);
- READWRITE(nTimeCreated);
- READWRITE(nTimeExpires);
- READWRITE(LIMITED_STRING(strComment, 65536));
- }
-};
-
-
-
-
-
-
/**
* Account information.
* Stored in wallet with key "acc"+string account name.
diff --git a/src/walletdb.cpp b/src/walletdb.cpp
index 054473e7cc..b2daf036ff 100644
--- a/src/walletdb.cpp
+++ b/src/walletdb.cpp
@@ -210,7 +210,7 @@ void CWalletDB::ListAccountCreditDebit(const string& strAccount, list<CAccountin
Dbc* pcursor = GetCursor();
if (!pcursor)
- throw runtime_error("CWalletDB::ListAccountCreditDebit() : cannot create DB cursor");
+ throw runtime_error("CWalletDB::ListAccountCreditDebit(): cannot create DB cursor");
unsigned int fFlags = DB_SET_RANGE;
while (true)
{
@@ -226,7 +226,7 @@ void CWalletDB::ListAccountCreditDebit(const string& strAccount, list<CAccountin
else if (ret != 0)
{
pcursor->close();
- throw runtime_error("CWalletDB::ListAccountCreditDebit() : error scanning DB");
+ throw runtime_error("CWalletDB::ListAccountCreditDebit(): error scanning DB");
}
// Unserialize
@@ -395,7 +395,7 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
if (wtx.nOrderPos == -1)
wss.fAnyUnordered = true;
- pwallet->AddToWallet(wtx, true);
+ pwallet->AddToWallet(wtx, true, NULL);
}
else if (strType == "acentry")
{
diff --git a/src/walletdb.h b/src/walletdb.h
index 45c00328a4..2627ef71a6 100644
--- a/src/walletdb.h
+++ b/src/walletdb.h
@@ -76,7 +76,7 @@ public:
class CWalletDB : public CDB
{
public:
- CWalletDB(const std::string& strFilename, const char* pszMode = "r+") : CDB(strFilename, pszMode)
+ CWalletDB(const std::string& strFilename, const char* pszMode = "r+", bool fFlushOnClose = true) : CDB(strFilename, pszMode, fFlushOnClose)
{
}