diff options
90 files changed, 1483 insertions, 1222 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/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/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/macdeploy/DS_Store b/contrib/macdeploy/DS_Store Binary files differindex 7527dc671f..099960712a 100644 --- a/contrib/macdeploy/DS_Store +++ b/contrib/macdeploy/DS_Store diff --git a/contrib/macdeploy/background.png b/contrib/macdeploy/background.png Binary files differindex fce12e3807..f88a2ae74b 100644 --- a/contrib/macdeploy/background.png +++ b/contrib/macdeploy/background.png diff --git a/contrib/macdeploy/background.psd b/contrib/macdeploy/background.psd Binary files differindex 5889676f8e..fdc4f4ca4a 100644 --- a/contrib/macdeploy/background.psd +++ b/contrib/macdeploy/background.psd diff --git a/contrib/macdeploy/background.tiff b/contrib/macdeploy/background.tiff Binary files differnew file mode 100644 index 0000000000..4b44ac672e --- /dev/null +++ b/contrib/macdeploy/background.tiff diff --git a/contrib/macdeploy/background@2x.png b/contrib/macdeploy/background@2x.png Binary files differnew file mode 100644 index 0000000000..4858183f75 --- /dev/null +++ b/contrib/macdeploy/background@2x.png 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/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/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/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/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/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/src/Makefile.am b/src/Makefile.am index 1f9a1621a7..e2ba191e3a 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 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/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..7b51707f60 100644 --- a/src/db.cpp +++ b/src/db.cpp @@ -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; @@ -297,7 +298,8 @@ void CDB::Close() activeTxn = NULL; pdb = NULL; - Flush(); + if (fFlushOnClose) + Flush(); { LOCK(bitdb.cs_db); @@ -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/init.cpp b/src/init.cpp index d6f1e1cb9f..aaa5f06c75 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -380,6 +380,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"; @@ -1210,6 +1211,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(); @@ -1225,7 +1228,7 @@ bool AppInit2(boost::thread_group& threadGroup) copyTo->fFromMe = copyFrom->fFromMe; copyTo->strFromAccount = copyFrom->strFromAccount; copyTo->nOrderPos = copyFrom->nOrderPos; - copyTo->WriteToDisk(); + copyTo->WriteToDisk(&walletdb); } } } @@ -1251,6 +1254,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/main.h b/src/main.h index 2b260a665b..a7360d2f70 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 **/ @@ -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..5cc4a92791 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" @@ -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; } } @@ -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..bba80535e5 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); @@ -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/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/bitcoingui.cpp b/src/qt/bitcoingui.cpp index 3d41dc89f1..09f784387e 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -164,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(); 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..37008f047e 100644 --- a/src/qt/forms/helpmessagedialog.ui +++ b/src/qt/forms/helpmessagedialog.ui @@ -6,33 +6,15 @@ <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"> <item> - <widget class="QLabel" name="graphic"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Ignored"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="pixmap"> - <pixmap resource="../bitcoin.qrc">:/images/about</pixmap> - </property> - </widget> - </item> - <item> <layout class="QVBoxLayout" name="verticalLayout"> <item> <widget class="QTextEdit" name="helpMessage"> @@ -50,14 +32,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"> diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp index c675235cc2..8ad9b30624 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 } 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..39171c89eb 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> @@ -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); diff --git a/src/qt/paymentserver.cpp b/src/qt/paymentserver.cpp index 0187e4c229..46ffd055a5 100644 --- a/src/qt/paymentserver.cpp +++ b/src/qt/paymentserver.cpp @@ -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(); diff --git a/src/qt/res/icons/add.png b/src/qt/res/icons/add.png Binary files differindex 7e46672f2d..1442b4e85e 100644 --- a/src/qt/res/icons/add.png +++ b/src/qt/res/icons/add.png diff --git a/src/qt/res/icons/filesave.png b/src/qt/res/icons/filesave.png Binary files differindex f4e6f58d05..779cca1d52 100644 --- a/src/qt/res/icons/filesave.png +++ b/src/qt/res/icons/filesave.png diff --git a/src/qt/res/images/about.png b/src/qt/res/images/about.png Binary files differdeleted file mode 100644 index fdede66172..0000000000 --- a/src/qt/res/images/about.png +++ /dev/null diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp index ce4a62d1b0..9e8743d805 100644 --- a/src/qt/sendcoinsdialog.cpp +++ b/src/qt/sendcoinsdialog.cpp @@ -661,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 @@ -691,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/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..4ef42b927e 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)")); diff --git a/src/rpcmining.cpp b/src/rpcmining.cpp index 603e2935dd..5df5de66d9 100644 --- a/src/rpcmining.cpp +++ b/src/rpcmining.cpp @@ -201,24 +201,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 +219,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" @@ -260,7 +241,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; } diff --git a/src/rpcmisc.cpp b/src/rpcmisc.cpp index 184aacf5a8..3d647a0d2d 100644 --- a/src/rpcmisc.cpp +++ b/src/rpcmisc.cpp @@ -165,7 +165,7 @@ 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\"") diff --git a/src/rpcrawtransaction.cpp b/src/rpcrawtransaction.cpp index 9bd8233992..2b108bf588 100644 --- a/src/rpcrawtransaction.cpp +++ b/src/rpcrawtransaction.cpp @@ -216,7 +216,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" diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp index a070ab5bbe..e4f23d56d2 100644 --- a/src/rpcserver.cpp +++ b/src/rpcserver.cpp @@ -281,7 +281,6 @@ static const CRPCCommand vRPCCommands[] = #ifdef ENABLE_WALLET /* Coin generation */ { "generating", "getgenerate", &getgenerate, true, false, false }, - { "generating", "gethashespersec", &gethashespersec, true, false, false }, { "generating", "setgenerate", &setgenerate, true, true, false }, #endif @@ -953,7 +952,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 diff --git a/src/rpcserver.h b/src/rpcserver.h index fb561ab939..1b94b758f2 100644 --- a/src/rpcserver.h +++ b/src/rpcserver.h @@ -154,7 +154,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..6ad3ee54d5 100644 --- a/src/rpcwallet.cpp +++ b/src/rpcwallet.cpp @@ -79,17 +79,15 @@ 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", "") ); // Parse the account first so we don't generate a key if there's an error @@ -154,7 +152,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" @@ -212,7 +210,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" @@ -254,7 +252,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" @@ -281,7 +279,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" @@ -400,7 +398,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" @@ -542,7 +540,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" @@ -627,26 +625,22 @@ 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") ); if (params.size() == 0) @@ -710,7 +704,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" @@ -775,7 +769,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" @@ -836,7 +830,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,11 +843,11 @@ 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\"") ); string strAccount = AccountFromValue(params[0]); @@ -918,7 +912,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 +921,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" @@ -1103,7 +1097,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" @@ -1124,7 +1118,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" @@ -1251,15 +1245,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,12 +1286,10 @@ 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") ); string strAccount = "*"; @@ -1361,7 +1352,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" @@ -1444,7 +1435,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" @@ -1538,7 +1529,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" diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp index d0f75ab672..8a06f3d118 100644 --- a/src/script/interpreter.cpp +++ b/src/script/interpreter.cpp @@ -189,6 +189,11 @@ bool static IsDefinedHashtypeSignature(const valtype &vchSig) { } bool static CheckSignatureEncoding(const valtype &vchSig, unsigned int flags, ScriptError* serror) { + // 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 && !IsDERSignature(vchSig)) { return set_error(serror, SCRIPT_ERR_SIG_DER); } else if ((flags & SCRIPT_VERIFY_LOW_S) != 0 && !IsLowDERSignature(vchSig, serror)) { 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/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/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..9a8fe1ee88 100644 --- a/src/test/data/script_invalid.json +++ b/src/test/data/script_invalid.json @@ -504,7 +504,7 @@ "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." diff --git a/src/test/data/script_valid.json b/src/test/data/script_valid.json index 5253d5e39e..a187401cd4 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"], diff --git a/src/test/multisig_tests.cpp b/src/test/multisig_tests.cpp index 69d8522188..9501169943 100644 --- a/src/test/multisig_tests.cpp +++ b/src/test/multisig_tests.cpp @@ -116,10 +116,6 @@ BOOST_AUTO_TEST_CASE(multisig_verify) } } 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_MESSAGE(err == SCRIPT_ERR_SIG_DER, ScriptErrorString(err)); diff --git a/src/wallet.cpp b/src/wallet.cpp index 6c5af3bdc7..1fe0552109 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -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()) @@ -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); } /** @@ -1581,14 +1587,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; diff --git a/src/wallet.h b/src/wallet.h index 1d0dc97c6c..f9cbd3a849 100644 --- a/src/wallet.h +++ b/src/wallet.h @@ -275,7 +275,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); @@ -903,7 +903,7 @@ public: return true; } - bool WriteToDisk(); + bool WriteToDisk(CWalletDB *pwalletdb); int64_t GetTxTime() const; int GetRequestCount() const; diff --git a/src/walletdb.cpp b/src/walletdb.cpp index 054473e7cc..d4d2e16740 100644 --- a/src/walletdb.cpp +++ b/src/walletdb.cpp @@ -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) { } |