diff options
196 files changed, 4533 insertions, 1177 deletions
diff --git a/.gitignore b/.gitignore index 892b2a3e08..b9db7cbd39 100644 --- a/.gitignore +++ b/.gitignore @@ -103,10 +103,7 @@ linux-build win32-build qa/pull-tester/run-bitcoind-for-test.sh qa/pull-tester/tests_config.py -qa/pull-tester/test.*/* -qa/tmp qa/cache/* -share/BitcoindComparisonTool.jar !src/leveldb*/Makefile diff --git a/.travis.yml b/.travis.yml index 0b38fd45fe..d201cea732 100644 --- a/.travis.yml +++ b/.travis.yml @@ -34,7 +34,7 @@ env: # No wallet - HOST=x86_64-unknown-linux-gnu PACKAGES="python3" DEP_OPTS="NO_WALLET=1" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-glibc-back-compat --enable-reduce-exports" # Cross-Mac - - HOST=x86_64-apple-darwin11 PACKAGES="cmake imagemagick libcap-dev librsvg2-bin libz-dev libbz2-dev libtiff-tools python-dev" BITCOIN_CONFIG="--enable-reduce-exports" OSX_SDK=10.11 GOAL="deploy" + - HOST=x86_64-apple-darwin11 PACKAGES="cmake imagemagick libcap-dev librsvg2-bin libz-dev libbz2-dev libtiff-tools python-dev" BITCOIN_CONFIG="--enable-gui --enable-reduce-exports" OSX_SDK=10.11 GOAL="deploy" before_install: - export PATH=$(echo $PATH | tr ':' "\n" | sed '/\/opt\/python/d' | tr "\n" ":" | sed "s|::|:|g") diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 62ebc7917a..fd1a912c4f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -87,6 +87,15 @@ before it will be merged. The basic squashing workflow is shown below. # save and quit git push -f # (force push to GitHub) +If you have problems with squashing (or other workflows with `git`), you can +alternatively enable "Allow edits from maintainers" in the right GitHub +sidebar and ask for help in the pull request. + +Please refrain from creating several pull requests for the same change. +Use the pull request that is already open (or was created earlier) to amend +changes. This preserves the discussion and review that happened earlier for +the respective change set. + The length of time required for peer review is unpredictable and will vary from pull request to pull request. @@ -198,3 +207,11 @@ Release Policy -------------- The project leader is the release manager for each Bitcoin Core release. + +Copyright +--------- + +By contributing to this repository, you agree to license your work under the +MIT license unless specified otherwise in `contrib/debian/copyright` or at +the top of the file itself. Any work contributed where you are not the original +author must contain its license header with the original author(s) and source. diff --git a/Makefile.am b/Makefile.am index 37c1e98eca..44fdf9c9fb 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,5 +1,12 @@ +# Copyright (c) 2013-2016 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + ACLOCAL_AMFLAGS = -I build-aux/m4 SUBDIRS = src +if ENABLE_MAN +SUBDIRS += doc/man +endif .PHONY: deploy FORCE GZIP_ENV="-9n" @@ -213,6 +220,8 @@ DISTCLEANFILES = qa/pull-tester/tests_config.pyc .INTERMEDIATE: $(COVERAGE_INFO) +DISTCHECK_CONFIGURE_FLAGS = --enable-man + clean-local: rm -rf coverage_percent.txt test_bitcoin.coverage/ total.coverage/ qa/tmp/ cache/ $(OSX_APP) rm -rf qa/pull-tester/__pycache__ diff --git a/autogen.sh b/autogen.sh index 46e36ff5b2..27417daf76 100755 --- a/autogen.sh +++ b/autogen.sh @@ -1,4 +1,8 @@ #!/bin/sh +# Copyright (c) 2013-2016 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + set -e srcdir="$(dirname $0)" cd "$srcdir" diff --git a/build-aux/m4/bitcoin_find_bdb48.m4 b/build-aux/m4/bitcoin_find_bdb48.m4 index 2aa493a6af..0c3d49c2bc 100644 --- a/build-aux/m4/bitcoin_find_bdb48.m4 +++ b/build-aux/m4/bitcoin_find_bdb48.m4 @@ -1,3 +1,7 @@ +dnl Copyright (c) 2013-2015 The Bitcoin Core developers +dnl Distributed under the MIT software license, see the accompanying +dnl file COPYING or http://www.opensource.org/licenses/mit-license.php. + AC_DEFUN([BITCOIN_FIND_BDB48],[ AC_MSG_CHECKING([for Berkeley DB C++ headers]) BDB_CPPFLAGS= diff --git a/build-aux/m4/bitcoin_qt.m4 b/build-aux/m4/bitcoin_qt.m4 index d26136cbe9..509283a0b9 100644 --- a/build-aux/m4/bitcoin_qt.m4 +++ b/build-aux/m4/bitcoin_qt.m4 @@ -1,3 +1,7 @@ +dnl Copyright (c) 2013-2016 The Bitcoin Core developers +dnl Distributed under the MIT software license, see the accompanying +dnl file COPYING or http://www.opensource.org/licenses/mit-license.php. + dnl Helper for cases where a qt dependency is not met. dnl Output: If qt version is auto, set bitcoin_enable_qt to false. Else, exit. AC_DEFUN([BITCOIN_QT_FAIL],[ diff --git a/build-aux/m4/bitcoin_subdir_to_include.m4 b/build-aux/m4/bitcoin_subdir_to_include.m4 index 66f106c7d4..7841042ac8 100644 --- a/build-aux/m4/bitcoin_subdir_to_include.m4 +++ b/build-aux/m4/bitcoin_subdir_to_include.m4 @@ -1,3 +1,7 @@ +dnl Copyright (c) 2013-2014 The Bitcoin Core developers +dnl Distributed under the MIT software license, see the accompanying +dnl file COPYING or http://www.opensource.org/licenses/mit-license.php. + dnl BITCOIN_SUBDIR_TO_INCLUDE([CPPFLAGS-VARIABLE-NAME],[SUBDIRECTORY-NAME],[HEADER-FILE]) dnl SUBDIRECTORY-NAME must end with a path separator AC_DEFUN([BITCOIN_SUBDIR_TO_INCLUDE],[ diff --git a/build-aux/m4/l_atomic.m4 b/build-aux/m4/l_atomic.m4 index 906724b640..75c43f9a92 100644 --- a/build-aux/m4/l_atomic.m4 +++ b/build-aux/m4/l_atomic.m4 @@ -1,3 +1,9 @@ +dnl Copyright (c) 2015 Tim Kosse <tim.kosse@filezilla-project.org> +dnl Copying and distribution of this file, with or without modification, are +dnl permitted in any medium without royalty provided the copyright notice +dnl and this notice are preserved. This file is offered as-is, without any +dnl warranty. + # Some versions of gcc/libstdc++ require linking with -latomic if # using the C++ atomic library. # @@ -32,7 +38,7 @@ AC_DEFUN([CHECK_ATOMIC], [ AC_MSG_RESULT([yes]) ],[ AC_MSG_RESULT([no]) - AC_MSG_FAILURE([cannot figure our how to use std::atomic]) + AC_MSG_FAILURE([cannot figure out how to use std::atomic]) ]) ]) diff --git a/configure.ac b/configure.ac index 607adec4f4..97f44f269b 100644 --- a/configure.ac +++ b/configure.ac @@ -171,6 +171,12 @@ AC_ARG_ENABLE([zmq], AC_ARG_WITH([protoc-bindir],[AS_HELP_STRING([--with-protoc-bindir=BIN_DIR],[specify protoc bin path])], [protoc_bin_path=$withval], []) +AC_ARG_ENABLE(man, + [AS_HELP_STRING([--disable-man], + [do not install man pages (default is to install)])],, + enable_man=yes) +AM_CONDITIONAL(ENABLE_MAN, test "$enable_man" != no) + # Enable debug AC_ARG_ENABLE([debug], [AS_HELP_STRING([--enable-debug], @@ -476,6 +482,7 @@ if test x$use_hardening != xno; then AX_CHECK_LINK_FLAG([[-Wl,--dynamicbase]], [HARDENED_LDFLAGS="$HARDENED_LDFLAGS -Wl,--dynamicbase"]) AX_CHECK_LINK_FLAG([[-Wl,--nxcompat]], [HARDENED_LDFLAGS="$HARDENED_LDFLAGS -Wl,--nxcompat"]) + AX_CHECK_LINK_FLAG([[-Wl,--high-entropy-va]], [HARDENED_LDFLAGS="$HARDENED_LDFLAGS -Wl,--high-entropy-va"]) AX_CHECK_LINK_FLAG([[-Wl,-z,relro]], [HARDENED_LDFLAGS="$HARDENED_LDFLAGS -Wl,-z,relro"]) AX_CHECK_LINK_FLAG([[-Wl,-z,now]], [HARDENED_LDFLAGS="$HARDENED_LDFLAGS -Wl,-z,now"]) @@ -1057,7 +1064,7 @@ AC_SUBST(EVENT_PTHREADS_LIBS) AC_SUBST(ZMQ_LIBS) AC_SUBST(PROTOBUF_LIBS) AC_SUBST(QR_LIBS) -AC_CONFIG_FILES([Makefile src/Makefile share/setup.nsi share/qt/Info.plist src/test/buildenv.py]) +AC_CONFIG_FILES([Makefile src/Makefile doc/man/Makefile share/setup.nsi share/qt/Info.plist src/test/buildenv.py]) AC_CONFIG_FILES([qa/pull-tester/run-bitcoind-for-test.sh],[chmod +x qa/pull-tester/run-bitcoind-for-test.sh]) AC_CONFIG_FILES([qa/pull-tester/tests_config.py],[chmod +x qa/pull-tester/tests_config.py]) AC_CONFIG_FILES([contrib/devtools/split-debug.sh],[chmod +x contrib/devtools/split-debug.sh]) diff --git a/contrib/README.md b/contrib/README.md index 3e3c83da5f..ab5f57587e 100644 --- a/contrib/README.md +++ b/contrib/README.md @@ -1,11 +1,3 @@ -Wallet Tools ---------------------- - -### [SpendFrom](/contrib/spendfrom) ### - -Use the raw transactions API to send coins received on a particular -address (or addresses). - Repository Tools --------------------- diff --git a/contrib/debian/bitcoin-qt.manpages b/contrib/debian/bitcoin-qt.manpages new file mode 100644 index 0000000000..9a3cc31c09 --- /dev/null +++ b/contrib/debian/bitcoin-qt.manpages @@ -0,0 +1 @@ +doc/man/bitcoin-qt.1 diff --git a/contrib/debian/bitcoin-tx.manpages b/contrib/debian/bitcoin-tx.manpages new file mode 100644 index 0000000000..861d49d070 --- /dev/null +++ b/contrib/debian/bitcoin-tx.manpages @@ -0,0 +1 @@ +doc/man/bitcoin-tx.1 diff --git a/contrib/debian/bitcoind.manpages b/contrib/debian/bitcoind.manpages index 6d3e683855..bab644ece1 100644 --- a/contrib/debian/bitcoind.manpages +++ b/contrib/debian/bitcoind.manpages @@ -1,3 +1,2 @@ -debian/manpages/bitcoind.1 -debian/manpages/bitcoin.conf.5 -debian/manpages/bitcoin-cli.1 +doc/man/bitcoind.1 +doc/man/bitcoin-cli.1 diff --git a/contrib/debian/copyright b/contrib/debian/copyright index cc4606ca88..5cac6e533c 100644 --- a/contrib/debian/copyright +++ b/contrib/debian/copyright @@ -15,10 +15,6 @@ Copyright: 2010-2011, Jonas Smedegaard <dr@jones.dk> 2011, Matt Corallo <matt@bluematt.me> License: GPL-2+ -Files: debian/manpages/* -Copyright: Micah Anderson <micah@debian.org> -License: GPL-3+ - Files: src/qt/res/icons/add.png src/qt/res/icons/address-book.png src/qt/res/icons/chevron.png diff --git a/contrib/debian/manpages/bitcoin-cli.1 b/contrib/debian/manpages/bitcoin-cli.1 deleted file mode 100644 index 16c338dd3e..0000000000 --- a/contrib/debian/manpages/bitcoin-cli.1 +++ /dev/null @@ -1,21 +0,0 @@ -.TH BITCOIN-CLI "1" "February 2016" "bitcoin-cli 0.12" -.SH NAME -bitcoin-cli \- a remote procedure call client for Bitcoin Core. -.SH SYNOPSIS -bitcoin-cli [options] <command> [params] \- Send command to Bitcoin Core. -.TP -bitcoin-cli [options] help \- Asks Bitcoin Core for a list of supported commands. -.SH DESCRIPTION -This manual page documents the bitcoin-cli program. bitcoin-cli is an RPC client used to send commands to Bitcoin Core. - -.SH OPTIONS -.TP -\fB\-?\fR -Show possible options. - -.SH "SEE ALSO" -\fBbitcoind\fP, \fBbitcoin.conf\fP -.SH AUTHOR -This manual page was written by Ciemon Dunville <ciemon@gmail.com>. Permission is granted to copy, distribute and/or modify this document under the terms of the MIT License. - -The complete text of the MIT License can be found on the web at \fIhttp://opensource.org/licenses/MIT\fP. diff --git a/contrib/debian/manpages/bitcoin-qt.1 b/contrib/debian/manpages/bitcoin-qt.1 deleted file mode 100644 index 685a282080..0000000000 --- a/contrib/debian/manpages/bitcoin-qt.1 +++ /dev/null @@ -1,13 +0,0 @@ -.TH BITCOIN-QT "1" "February 2016" "bitcoin-qt 0.12" -.SH NAME -bitcoin-qt \- peer-to-peer network based digital currency -.SH DESCRIPTION -.SS "Usage:" -.IP -bitcoin\-qt [command\-line options] -.SH OPTIONS -.TP -\-? -List options. -.SH "SEE ALSO" -bitcoind(1) diff --git a/contrib/debian/manpages/bitcoin.conf.5 b/contrib/debian/manpages/bitcoin.conf.5 deleted file mode 100644 index 839dc26c1a..0000000000 --- a/contrib/debian/manpages/bitcoin.conf.5 +++ /dev/null @@ -1,19 +0,0 @@ -.TH BITCOIN.CONF "5" "February 2016" "bitcoin.conf 0.12" -.SH NAME -bitcoin.conf \- bitcoin configuration file -.SH SYNOPSIS -All command-line options (except for '\-conf') may be specified in a configuration file, and all configuration file options may also be specified on the command line. Command-line options override values set in the configuration file. -.TP -The configuration file is a list of 'setting=value' pairs, one per line, with optional comments starting with the '#' character. Please refer to bitcoind(1) for a up to date list of valid options. -.TP -The configuration file is not automatically created; you can create it using your favorite plain-text editor. By default, bitcoind(1) will look for a file named bitcoin.conf(5) in the bitcoin data directory, but both the data directory and the configuration file path may be changed using the '\-datadir' and '\-conf' command-line arguments. -.SH LOCATION -bitcoin.conf should be located in $HOME/.bitcoin - -.SH "SEE ALSO" -bitcoind(1) -.SH AUTHOR -This manual page was written by Micah Anderson <micah@debian.org> for the Debian system (but may be used by others). Permission is granted to copy, distribute and/or modify this document under the terms of the GNU General Public License, Version 3 or any later version published by the Free Software Foundation. - -On Debian systems, the complete text of the GNU General Public License can be found in /usr/share/common-licenses/GPL. - diff --git a/contrib/debian/manpages/bitcoind.1 b/contrib/debian/manpages/bitcoind.1 deleted file mode 100644 index 5c3e52f441..0000000000 --- a/contrib/debian/manpages/bitcoind.1 +++ /dev/null @@ -1,30 +0,0 @@ -.TH BITCOIND "1" "February 2016" "bitcoind 0.12" -.SH NAME -bitcoind \- peer-to-peer network based digital currency -.SH SYNOPSIS -bitcoin [options] <command> [params] -.TP -bitcoin [options] help <command> \- Get help for a command -.SH DESCRIPTION -This manual page documents the bitcoind program. Bitcoin is an experimental new digital currency that enables instant payments to anyone, anywhere in the world. Bitcoin uses peer-to-peer technology to operate with no central authority: managing transactions and issuing money are carried out collectively by the network. Bitcoin Core is the name of open source software which enables the use of this currency. - -.SH OPTIONS -.TP -\-? -List of possible options. -.SH COMMANDS -.TP -\fBhelp\fR -List commands. - -.TP -\fBhelp 'command'\fR -Get help for a command. - -.SH "SEE ALSO" -bitcoin.conf(5) -.SH AUTHOR -This manual page was written by Micah Anderson <micah@debian.org> for the Debian system (but may be used by others). Permission is granted to copy, distribute and/or modify this document under the terms of the GNU General Public License, Version 3 or any later version published by the Free Software Foundation. - -On Debian systems, the complete text of the GNU General Public License can be found in /usr/share/common-licenses/GPL. - diff --git a/contrib/debian/rules b/contrib/debian/rules index 52b357cf01..3896d2caa3 100755 --- a/contrib/debian/rules +++ b/contrib/debian/rules @@ -5,9 +5,6 @@ #build/bitcoind:: # $(if $(filter nocheck,$(DEB_BUILD_OPTIONS)),,src/test_bitcoin) -DEB_INSTALL_EXAMPLES_bitcoind += debian/examples/* -DEB_INSTALL_MANPAGES_bitcoind += debian/manpages/* - %: dh --with bash-completion $@ diff --git a/contrib/devtools/README.md b/contrib/devtools/README.md index af5c000b03..60fe69e7e3 100644 --- a/contrib/devtools/README.md +++ b/contrib/devtools/README.md @@ -40,6 +40,12 @@ would be changed to: ```// Copyright (c) 2009-2015 The Bitcoin Core developers``` +gen-manpages.sh +=============== + +A small script to automatically create manpages in ../../doc/man by running the release binaries with the -help option. +This requires help2man which can be found at: https://www.gnu.org/software/help2man/ + git-subtree-check.sh ==================== diff --git a/contrib/devtools/gen-manpages.sh b/contrib/devtools/gen-manpages.sh new file mode 100755 index 0000000000..967717e1e0 --- /dev/null +++ b/contrib/devtools/gen-manpages.sh @@ -0,0 +1,29 @@ +#!/bin/sh + +TOPDIR=${TOPDIR:-$(git rev-parse --show-toplevel)} +SRCDIR=${SRCDIR:-$TOPDIR/src} +MANDIR=${MANDIR:-$TOPDIR/doc/man} + +BITCOIND=${BITCOIND:-$SRCDIR/bitcoind} +BITCOINCLI=${BITCOINCLI:-$SRCDIR/bitcoin-cli} +BITCOINTX=${BITCOINTX:-$SRCDIR/bitcoin-tx} +BITCOINQT=${BITCOINQT:-$SRCDIR/qt/bitcoin-qt} + +[ ! -x $BITCOIND ] && echo "$BITCOIND not found or not executable." && exit 1 + +# The autodetected version git tag can screw up manpage output a little bit +BTCVER=($($BITCOINCLI --version | head -n1 | awk -F'[ -]' '{ print $6, $7 }')) + +# Create a footer file with copyright content. +# This gets autodetected fine for bitcoind if --version-string is not set, +# but has different outcomes for bitcoin-qt and bitcoin-cli. +echo "[COPYRIGHT]" > footer.h2m +$BITCOIND --version | sed -n '1!p' >> footer.h2m + +for cmd in $BITCOIND $BITCOINCLI $BITCOINTX $BITCOINQT; do + cmdname="${cmd##*/}" + help2man -N --version-string=${BTCVER[0]} --include=footer.h2m -o ${MANDIR}/${cmdname}.1 ${cmd} + sed -i "s/\\\-${BTCVER[1]}//g" ${MANDIR}/${cmdname}.1 +done + +rm -f footer.h2m diff --git a/contrib/devtools/git-subtree-check.sh b/contrib/devtools/git-subtree-check.sh index 1cb82fe682..2384d66cad 100755 --- a/contrib/devtools/git-subtree-check.sh +++ b/contrib/devtools/git-subtree-check.sh @@ -1,4 +1,7 @@ #!/bin/sh +# Copyright (c) 2015 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. DIR="$1" COMMIT="$2" diff --git a/contrib/devtools/optimize-pngs.py b/contrib/devtools/optimize-pngs.py index 799e0cc7d0..b7b8dc0082 100755 --- a/contrib/devtools/optimize-pngs.py +++ b/contrib/devtools/optimize-pngs.py @@ -1,4 +1,7 @@ #!/usr/bin/env python +# Copyright (c) 2014-2015 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. ''' Run this script every time you change one of the png files. Using pngcrush, it will optimize the png files, remove various color profiles, remove ancillary chunks (alla) and text chunks (text). #pngcrush -brute -ow -rem gAMA -rem cHRM -rem iCCP -rem sRGB -rem alla -rem text diff --git a/contrib/devtools/security-check.py b/contrib/devtools/security-check.py index c61d652641..c90541e271 100755 --- a/contrib/devtools/security-check.py +++ b/contrib/devtools/security-check.py @@ -1,4 +1,7 @@ #!/usr/bin/env python +# Copyright (c) 2015-2016 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. ''' Perform basic ELF security checks on a series of executables. Exit status will be 0 if successful, and the program will be silent. @@ -12,6 +15,7 @@ import os READELF_CMD = os.getenv('READELF', '/usr/bin/readelf') OBJDUMP_CMD = os.getenv('OBJDUMP', '/usr/bin/objdump') +NONFATAL = {'HIGH_ENTROPY_VA'} # checks which are non-fatal for now but only generate a warning def check_ELF_PIE(executable): ''' @@ -114,26 +118,50 @@ def check_ELF_Canary(executable): def get_PE_dll_characteristics(executable): ''' - Get PE DllCharacteristics bits + Get PE DllCharacteristics bits. + Returns a tuple (arch,bits) where arch is 'i386:x86-64' or 'i386' + and bits is the DllCharacteristics value. ''' p = subprocess.Popen([OBJDUMP_CMD, '-x', executable], stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE) (stdout, stderr) = p.communicate() if p.returncode: raise IOError('Error opening file') + arch = '' + bits = 0 for line in stdout.split('\n'): tokens = line.split() + if len(tokens)>=2 and tokens[0] == 'architecture:': + arch = tokens[1].rstrip(',') if len(tokens)>=2 and tokens[0] == 'DllCharacteristics': - return int(tokens[1],16) - return 0 + bits = int(tokens[1],16) + return (arch,bits) +IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA = 0x0020 +IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE = 0x0040 +IMAGE_DLL_CHARACTERISTICS_NX_COMPAT = 0x0100 -def check_PE_PIE(executable): +def check_PE_DYNAMIC_BASE(executable): '''PIE: DllCharacteristics bit 0x40 signifies dynamicbase (ASLR)''' - return bool(get_PE_dll_characteristics(executable) & 0x40) + (arch,bits) = get_PE_dll_characteristics(executable) + reqbits = IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE + return (bits & reqbits) == reqbits + +# On 64 bit, must support high-entropy 64-bit address space layout randomization in addition to DYNAMIC_BASE +# to have secure ASLR. +def check_PE_HIGH_ENTROPY_VA(executable): + '''PIE: DllCharacteristics bit 0x20 signifies high-entropy ASLR''' + (arch,bits) = get_PE_dll_characteristics(executable) + if arch == 'i386:x86-64': + reqbits = IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA + else: # Unnecessary on 32-bit + assert(arch == 'i386') + reqbits = 0 + return (bits & reqbits) == reqbits def check_PE_NX(executable): '''NX: DllCharacteristics bit 0x100 signifies nxcompat (DEP)''' - return bool(get_PE_dll_characteristics(executable) & 0x100) + (arch,bits) = get_PE_dll_characteristics(executable) + return (bits & IMAGE_DLL_CHARACTERISTICS_NX_COMPAT) == IMAGE_DLL_CHARACTERISTICS_NX_COMPAT CHECKS = { 'ELF': [ @@ -143,7 +171,8 @@ CHECKS = { ('Canary', check_ELF_Canary) ], 'PE': [ - ('PIE', check_PE_PIE), + ('DYNAMIC_BASE', check_PE_DYNAMIC_BASE), + ('HIGH_ENTROPY_VA', check_PE_HIGH_ENTROPY_VA), ('NX', check_PE_NX) ] } @@ -168,12 +197,18 @@ if __name__ == '__main__': continue failed = [] + warning = [] for (name, func) in CHECKS[etype]: if not func(filename): - failed.append(name) + if name in NONFATAL: + warning.append(name) + else: + failed.append(name) if failed: print('%s: failed %s' % (filename, ' '.join(failed))) retval = 1 + if warning: + print('%s: warning %s' % (filename, ' '.join(warning))) except IOError: print('%s: cannot open' % filename) retval = 1 diff --git a/contrib/devtools/test-security-check.py b/contrib/devtools/test-security-check.py index 324b7bcd85..c0f120392e 100755 --- a/contrib/devtools/test-security-check.py +++ b/contrib/devtools/test-security-check.py @@ -1,4 +1,7 @@ #!/usr/bin/env python2 +# Copyright (c) 2015-2016 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. ''' Test script for security-check.py ''' diff --git a/contrib/gitian-build.sh b/contrib/gitian-build.sh index ee47d138f3..53c24e3a87 100755 --- a/contrib/gitian-build.sh +++ b/contrib/gitian-build.sh @@ -1,3 +1,7 @@ +# Copyright (c) 2016 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + # What to do sign=false verify=false diff --git a/contrib/gitian-keys/btcdrak-key.pgp b/contrib/gitian-keys/btcdrak-key.pgp Binary files differindex 60d76c0ec7..f00dc729d5 100644 --- a/contrib/gitian-keys/btcdrak-key.pgp +++ b/contrib/gitian-keys/btcdrak-key.pgp diff --git a/contrib/macdeploy/detached-sig-apply.sh b/contrib/macdeploy/detached-sig-apply.sh index 781fe315ed..91674a92e6 100755 --- a/contrib/macdeploy/detached-sig-apply.sh +++ b/contrib/macdeploy/detached-sig-apply.sh @@ -1,4 +1,8 @@ #!/bin/sh +# Copyright (c) 2014-2015 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + set -e UNSIGNED="$1" diff --git a/contrib/macdeploy/detached-sig-create.sh b/contrib/macdeploy/detached-sig-create.sh index 89a2da32f7..5022ea88bc 100755 --- a/contrib/macdeploy/detached-sig-create.sh +++ b/contrib/macdeploy/detached-sig-create.sh @@ -1,4 +1,8 @@ #!/bin/sh +# Copyright (c) 2014-2015 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + set -e ROOTDIR=dist diff --git a/contrib/macdeploy/extract-osx-sdk.sh b/contrib/macdeploy/extract-osx-sdk.sh index 46d2d825d4..ff9fbd58df 100755 --- a/contrib/macdeploy/extract-osx-sdk.sh +++ b/contrib/macdeploy/extract-osx-sdk.sh @@ -1,4 +1,8 @@ #!/bin/bash +# Copyright (c) 2016 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + set -e INPUTFILE="Xcode_7.3.1.dmg" diff --git a/contrib/qos/tc.sh b/contrib/qos/tc.sh index f620604212..aaf5e1fa11 100644 --- a/contrib/qos/tc.sh +++ b/contrib/qos/tc.sh @@ -1,3 +1,7 @@ +# Copyright (c) 2013 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + #network interface on which to limit traffic IF="eth0" #limit of the network interface in question diff --git a/contrib/qt_translations.py b/contrib/qt_translations.py deleted file mode 100755 index fd8a8b7129..0000000000 --- a/contrib/qt_translations.py +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env python - -# Helpful little script that spits out a comma-separated list of -# language codes for Qt icons that should be included -# in binary bitcoin distributions - -import glob -import os -import re -import sys - -if len(sys.argv) != 3: - sys.exit("Usage: %s $QTDIR/translations $BITCOINDIR/src/qt/locale"%sys.argv[0]) - -d1 = sys.argv[1] -d2 = sys.argv[2] - -l1 = set([ re.search(r'qt_(.*).qm', f).group(1) for f in glob.glob(os.path.join(d1, 'qt_*.qm')) ]) -l2 = set([ re.search(r'bitcoin_(.*).qm', f).group(1) for f in glob.glob(os.path.join(d2, 'bitcoin_*.qm')) ]) - -print ",".join(sorted(l1.intersection(l2))) - diff --git a/contrib/rpm/bitcoin.spec b/contrib/rpm/bitcoin.spec index 38ae038180..516f42334e 100644 --- a/contrib/rpm/bitcoin.spec +++ b/contrib/rpm/bitcoin.spec @@ -27,10 +27,9 @@ Source1: http://download.oracle.com/berkeley-db/db-%{bdbv}.NC.tar.gz Source10: https://raw.githubusercontent.com/bitcoin/bitcoin/v%{version}/contrib/debian/examples/bitcoin.conf #man pages -Source20: https://raw.githubusercontent.com/bitcoin/bitcoin/v%{version}/contrib/debian/manpages/bitcoind.1 -Source21: https://raw.githubusercontent.com/bitcoin/bitcoin/v%{version}/contrib/debian/manpages/bitcoin-cli.1 -Source22: https://raw.githubusercontent.com/bitcoin/bitcoin/v%{version}/contrib/debian/manpages/bitcoin-qt.1 -Source23: https://raw.githubusercontent.com/bitcoin/bitcoin/v%{version}/contrib/debian/manpages/bitcoin.conf.5 +Source20: https://raw.githubusercontent.com/bitcoin/bitcoin/v%{version}/doc/man/bitcoind.1 +Source21: https://raw.githubusercontent.com/bitcoin/bitcoin/v%{version}/doc/man/bitcoin-cli.1 +Source22: https://raw.githubusercontent.com/bitcoin/bitcoin/v%{version}/doc/man/bitcoin-qt.1 #selinux Source30: https://raw.githubusercontent.com/bitcoin/bitcoin/v%{version}/contrib/rpm/bitcoin.te @@ -306,7 +305,6 @@ install -p %{SOURCE21} %{buildroot}%{_mandir}/man1/bitcoin-cli.1 %if %{_buildqt} install -p %{SOURCE22} %{buildroot}%{_mandir}/man1/bitcoin-qt.1 %endif -install -D -p %{SOURCE23} %{buildroot}%{_mandir}/man5/bitcoin.conf.5 # nuke these, we do extensive testing of binaries in %%check before packaging rm -f %{buildroot}%{_bindir}/test_* @@ -415,7 +413,6 @@ rm -rf %{buildroot} %config(noreplace) %attr(0600,root,root) %{_sysconfdir}/sysconfig/bitcoin %attr(0644,root,root) %{_datadir}/selinux/*/*.pp %attr(0644,root,root) %{_mandir}/man1/bitcoind.1* -%attr(0644,root,root) %{_mandir}/man5/bitcoin.conf.5* %files utils %defattr(-,root,root,-) @@ -425,7 +422,6 @@ rm -rf %{buildroot} %attr(0755,root,root) %{_bindir}/bitcoin-tx %attr(0755,root,root) %{_bindir}/bench_bitcoin %attr(0644,root,root) %{_mandir}/man1/bitcoin-cli.1* -%attr(0644,root,root) %{_mandir}/man5/bitcoin.conf.5* diff --git a/contrib/seeds/makeseeds.py b/contrib/seeds/makeseeds.py index 4072405ef5..041f224f40 100755 --- a/contrib/seeds/makeseeds.py +++ b/contrib/seeds/makeseeds.py @@ -1,4 +1,7 @@ #!/usr/bin/env python +# Copyright (c) 2013-2015 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. # # Generate seeds.txt from Pieter's DNS seeder # diff --git a/contrib/spendfrom/README.md b/contrib/spendfrom/README.md deleted file mode 100644 index c0a9c9ccf9..0000000000 --- a/contrib/spendfrom/README.md +++ /dev/null @@ -1,35 +0,0 @@ -### SpendFrom ### - -Use the raw transactions API to send coins received on a particular -address (or addresses). - -### Usage: ### -Depends on [jsonrpc](http://json-rpc.org/). - - spendfrom.py --from=FROMADDRESS1[,FROMADDRESS2] --to=TOADDRESS --amount=amount \ - --fee=fee --datadir=/path/to/.bitcoin --testnet --dry_run - -With no arguments, outputs a list of amounts associated with addresses. - -With arguments, sends coins received by the `FROMADDRESS` addresses to the `TOADDRESS`. - -### Notes ### - -- You may explicitly specify how much fee to pay (a fee more than 1% of the amount -will fail, though, to prevent bitcoin-losing accidents). Spendfrom may fail if -it thinks the transaction would never be confirmed (if the amount being sent is -too small, or if the transaction is too many bytes for the fee). - -- If a change output needs to be created, the change will be sent to the last -`FROMADDRESS` (if you specify just one `FROMADDRESS`, change will go back to it). - -- If `--datadir` is not specified, the default datadir is used. - -- The `--dry_run` option will just create and sign the transaction and print -the transaction data (as hexadecimal), instead of broadcasting it. - -- If the transaction is created and broadcast successfully, a transaction id -is printed. - -- If this was a tool for end-users and not programmers, it would have much friendlier -error-handling. diff --git a/contrib/spendfrom/setup.py b/contrib/spendfrom/setup.py deleted file mode 100644 index 01b9768a5b..0000000000 --- a/contrib/spendfrom/setup.py +++ /dev/null @@ -1,9 +0,0 @@ -from distutils.core import setup -setup(name='btcspendfrom', - version='1.0', - description='Command-line utility for bitcoin "coin control"', - author='Gavin Andresen', - author_email='gavin@bitcoinfoundation.org', - requires=['jsonrpc'], - scripts=['spendfrom.py'], - ) diff --git a/contrib/spendfrom/spendfrom.py b/contrib/spendfrom/spendfrom.py deleted file mode 100755 index 72ee0425eb..0000000000 --- a/contrib/spendfrom/spendfrom.py +++ /dev/null @@ -1,267 +0,0 @@ -#!/usr/bin/env python -# -# Use the raw transactions API to spend bitcoins received on particular addresses, -# and send any change back to that same address. -# -# Example usage: -# spendfrom.py # Lists available funds -# spendfrom.py --from=ADDRESS --to=ADDRESS --amount=11.00 -# -# Assumes it will talk to a bitcoind or Bitcoin-Qt running -# on localhost. -# -# Depends on jsonrpc -# - -from decimal import * -import getpass -import math -import os -import os.path -import platform -import sys -import time -from jsonrpc import ServiceProxy, json - -BASE_FEE=Decimal("0.001") - -def check_json_precision(): - """Make sure json library being used does not lose precision converting BTC values""" - n = Decimal("20000000.00000003") - satoshis = int(json.loads(json.dumps(float(n)))*1.0e8) - if satoshis != 2000000000000003: - raise RuntimeError("JSON encode/decode loses precision") - -def determine_db_dir(): - """Return the default location of the bitcoin data directory""" - if platform.system() == "Darwin": - return os.path.expanduser("~/Library/Application Support/Bitcoin/") - elif platform.system() == "Windows": - return os.path.join(os.environ['APPDATA'], "Bitcoin") - return os.path.expanduser("~/.bitcoin") - -def read_bitcoin_config(dbdir): - """Read the bitcoin.conf file from dbdir, returns dictionary of settings""" - from ConfigParser import SafeConfigParser - - class FakeSecHead(object): - def __init__(self, fp): - self.fp = fp - self.sechead = '[all]\n' - def readline(self): - if self.sechead: - try: return self.sechead - finally: self.sechead = None - else: - s = self.fp.readline() - if s.find('#') != -1: - s = s[0:s.find('#')].strip() +"\n" - return s - - config_parser = SafeConfigParser() - config_parser.readfp(FakeSecHead(open(os.path.join(dbdir, "bitcoin.conf")))) - return dict(config_parser.items("all")) - -def connect_JSON(config): - """Connect to a bitcoin JSON-RPC server""" - testnet = config.get('testnet', '0') - testnet = (int(testnet) > 0) # 0/1 in config file, convert to True/False - if not 'rpcport' in config: - config['rpcport'] = 18332 if testnet else 8332 - connect = "http://%s:%s@127.0.0.1:%s"%(config['rpcuser'], config['rpcpassword'], config['rpcport']) - try: - result = ServiceProxy(connect) - # ServiceProxy is lazy-connect, so send an RPC command mostly to catch connection errors, - # but also make sure the bitcoind we're talking to is/isn't testnet: - if result.getmininginfo()['testnet'] != testnet: - sys.stderr.write("RPC server at "+connect+" testnet setting mismatch\n") - sys.exit(1) - return result - except: - sys.stderr.write("Error connecting to RPC server at "+connect+"\n") - sys.exit(1) - -def unlock_wallet(bitcoind): - info = bitcoind.getinfo() - if 'unlocked_until' not in info: - return True # wallet is not encrypted - t = int(info['unlocked_until']) - if t <= time.time(): - try: - passphrase = getpass.getpass("Wallet is locked; enter passphrase: ") - bitcoind.walletpassphrase(passphrase, 5) - except: - sys.stderr.write("Wrong passphrase\n") - - info = bitcoind.getinfo() - return int(info['unlocked_until']) > time.time() - -def list_available(bitcoind): - address_summary = dict() - - address_to_account = dict() - for info in bitcoind.listreceivedbyaddress(0): - address_to_account[info["address"]] = info["account"] - - unspent = bitcoind.listunspent(0) - for output in unspent: - # listunspent doesn't give addresses, so: - rawtx = bitcoind.getrawtransaction(output['txid'], 1) - vout = rawtx["vout"][output['vout']] - pk = vout["scriptPubKey"] - - # This code only deals with ordinary pay-to-bitcoin-address - # or pay-to-script-hash outputs right now; anything exotic is ignored. - if pk["type"] != "pubkeyhash" and pk["type"] != "scripthash": - continue - - address = pk["addresses"][0] - if address in address_summary: - address_summary[address]["total"] += vout["value"] - address_summary[address]["outputs"].append(output) - else: - address_summary[address] = { - "total" : vout["value"], - "outputs" : [output], - "account" : address_to_account.get(address, "") - } - - return address_summary - -def select_coins(needed, inputs): - # Feel free to improve this, this is good enough for my simple needs: - outputs = [] - have = Decimal("0.0") - n = 0 - while have < needed and n < len(inputs): - outputs.append({ "txid":inputs[n]["txid"], "vout":inputs[n]["vout"]}) - have += inputs[n]["amount"] - n += 1 - return (outputs, have-needed) - -def create_tx(bitcoind, fromaddresses, toaddress, amount, fee): - all_coins = list_available(bitcoind) - - total_available = Decimal("0.0") - needed = amount+fee - potential_inputs = [] - for addr in fromaddresses: - if addr not in all_coins: - continue - potential_inputs.extend(all_coins[addr]["outputs"]) - total_available += all_coins[addr]["total"] - - if total_available < needed: - sys.stderr.write("Error, only %f BTC available, need %f\n"%(total_available, needed)); - sys.exit(1) - - # - # Note: - # Python's json/jsonrpc modules have inconsistent support for Decimal numbers. - # Instead of wrestling with getting json.dumps() (used by jsonrpc) to encode - # Decimals, I'm casting amounts to float before sending them to bitcoind. - # - outputs = { toaddress : float(amount) } - (inputs, change_amount) = select_coins(needed, potential_inputs) - if change_amount > BASE_FEE: # don't bother with zero or tiny change - change_address = fromaddresses[-1] - if change_address in outputs: - outputs[change_address] += float(change_amount) - else: - outputs[change_address] = float(change_amount) - - rawtx = bitcoind.createrawtransaction(inputs, outputs) - signed_rawtx = bitcoind.signrawtransaction(rawtx) - if not signed_rawtx["complete"]: - sys.stderr.write("signrawtransaction failed\n") - sys.exit(1) - txdata = signed_rawtx["hex"] - - return txdata - -def compute_amount_in(bitcoind, txinfo): - result = Decimal("0.0") - for vin in txinfo['vin']: - in_info = bitcoind.getrawtransaction(vin['txid'], 1) - vout = in_info['vout'][vin['vout']] - result = result + vout['value'] - return result - -def compute_amount_out(txinfo): - result = Decimal("0.0") - for vout in txinfo['vout']: - result = result + vout['value'] - return result - -def sanity_test_fee(bitcoind, txdata_hex, max_fee): - class FeeError(RuntimeError): - pass - try: - txinfo = bitcoind.decoderawtransaction(txdata_hex) - total_in = compute_amount_in(bitcoind, txinfo) - total_out = compute_amount_out(txinfo) - if total_in-total_out > max_fee: - raise FeeError("Rejecting transaction, unreasonable fee of "+str(total_in-total_out)) - - tx_size = len(txdata_hex)/2 - kb = tx_size/1000 # integer division rounds down - if kb > 1 and fee < BASE_FEE: - raise FeeError("Rejecting no-fee transaction, larger than 1000 bytes") - if total_in < 0.01 and fee < BASE_FEE: - raise FeeError("Rejecting no-fee, tiny-amount transaction") - # Exercise for the reader: compute transaction priority, and - # warn if this is a very-low-priority transaction - - except FeeError as err: - sys.stderr.write((str(err)+"\n")) - sys.exit(1) - -def main(): - import optparse - - parser = optparse.OptionParser(usage="%prog [options]") - parser.add_option("--from", dest="fromaddresses", default=None, - help="addresses to get bitcoins from") - parser.add_option("--to", dest="to", default=None, - help="address to get send bitcoins to") - parser.add_option("--amount", dest="amount", default=None, - help="amount to send") - parser.add_option("--fee", dest="fee", default="0.0", - help="fee to include") - parser.add_option("--datadir", dest="datadir", default=determine_db_dir(), - help="location of bitcoin.conf file with RPC username/password (default: %default)") - parser.add_option("--testnet", dest="testnet", default=False, action="store_true", - help="Use the test network") - parser.add_option("--dry_run", dest="dry_run", default=False, action="store_true", - help="Don't broadcast the transaction, just create and print the transaction data") - - (options, args) = parser.parse_args() - - check_json_precision() - config = read_bitcoin_config(options.datadir) - if options.testnet: config['testnet'] = True - bitcoind = connect_JSON(config) - - if options.amount is None: - address_summary = list_available(bitcoind) - for address,info in address_summary.iteritems(): - n_transactions = len(info['outputs']) - if n_transactions > 1: - print("%s %.8f %s (%d transactions)"%(address, info['total'], info['account'], n_transactions)) - else: - print("%s %.8f %s"%(address, info['total'], info['account'])) - else: - fee = Decimal(options.fee) - amount = Decimal(options.amount) - while unlock_wallet(bitcoind) == False: - pass # Keep asking for passphrase until they get it right - txdata = create_tx(bitcoind, options.fromaddresses.split(","), options.to, amount, fee) - sanity_test_fee(bitcoind, txdata, amount*Decimal("0.01")) - if options.dry_run: - print(txdata) - else: - txid = bitcoind.sendrawtransaction(txdata) - print(txid) - -if __name__ == '__main__': - main() diff --git a/contrib/testgen/base58.py b/contrib/testgen/base58.py index b716495145..72b288b2dc 100644 --- a/contrib/testgen/base58.py +++ b/contrib/testgen/base58.py @@ -1,3 +1,6 @@ +# Copyright (c) 2012 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. ''' Bitcoin base58 encoding and decoding. diff --git a/contrib/testgen/gen_base58_test_vectors.py b/contrib/testgen/gen_base58_test_vectors.py index 1813436953..8518774db3 100755 --- a/contrib/testgen/gen_base58_test_vectors.py +++ b/contrib/testgen/gen_base58_test_vectors.py @@ -1,4 +1,7 @@ #!/usr/bin/env python +# Copyright (c) 2012 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. ''' Generate valid and invalid base58 address and private key test vectors. diff --git a/contrib/tidy_datadir.sh b/contrib/tidy_datadir.sh index 5d6d826444..8960f8811d 100755 --- a/contrib/tidy_datadir.sh +++ b/contrib/tidy_datadir.sh @@ -1,4 +1,7 @@ #!/bin/bash +# Copyright (c) 2013 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. if [ -d "$1" ]; then cd "$1" diff --git a/contrib/verify-commits/gpg.sh b/contrib/verify-commits/gpg.sh index 375d711725..09ff237544 100755 --- a/contrib/verify-commits/gpg.sh +++ b/contrib/verify-commits/gpg.sh @@ -1,4 +1,8 @@ #!/bin/sh +# Copyright (c) 2014-2016 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + INPUT=$(cat /dev/stdin) VALID=false REVSIG=false diff --git a/contrib/verify-commits/pre-push-hook.sh b/contrib/verify-commits/pre-push-hook.sh index c57222818a..c21febb9e9 100755 --- a/contrib/verify-commits/pre-push-hook.sh +++ b/contrib/verify-commits/pre-push-hook.sh @@ -1,4 +1,8 @@ #!/bin/bash +# Copyright (c) 2014-2015 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + if ! [[ "$2" =~ ^(git@)?(www.)?github.com(:|/)bitcoin/bitcoin(.git)?$ ]]; then exit 0 fi diff --git a/contrib/verify-commits/verify-commits.sh b/contrib/verify-commits/verify-commits.sh index 5219331e2e..cfe4f11a0b 100755 --- a/contrib/verify-commits/verify-commits.sh +++ b/contrib/verify-commits/verify-commits.sh @@ -1,4 +1,8 @@ #!/bin/sh +# Copyright (c) 2014-2016 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + # Not technically POSIX-compliant due to use of "local", but almost every # shell anyone uses today supports it, so its probably fine diff --git a/contrib/verifybinaries/verify.sh b/contrib/verifybinaries/verify.sh index e22b911743..e20770c96a 100755 --- a/contrib/verifybinaries/verify.sh +++ b/contrib/verifybinaries/verify.sh @@ -1,4 +1,7 @@ #!/bin/bash +# Copyright (c) 2016 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. ### This script attempts to download the signature file SHA256SUMS.asc from bitcoin.org ### It first checks if the signature passes, and then downloads the files specified in diff --git a/contrib/zmq/zmq_sub.py b/contrib/zmq/zmq_sub.py index 6268123dd8..3dea5e3c14 100755 --- a/contrib/zmq/zmq_sub.py +++ b/contrib/zmq/zmq_sub.py @@ -1,4 +1,7 @@ #!/usr/bin/env python2 +# Copyright (c) 2014-2016 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. import array import binascii diff --git a/depends/packages/expat.mk b/depends/packages/expat.mk index bd29275638..81a660e83a 100644 --- a/depends/packages/expat.mk +++ b/depends/packages/expat.mk @@ -1,8 +1,8 @@ package=expat -$(package)_version=2.1.1 +$(package)_version=2.2.0 $(package)_download_path=https://downloads.sourceforge.net/project/expat/expat/$($(package)_version) $(package)_file_name=$(package)-$($(package)_version).tar.bz2 -$(package)_sha256_hash=aff584e5a2f759dcfc6d48671e9529f6afe1e30b0cd6a4cec200cbe3f793de67 +$(package)_sha256_hash=d9e50ff2d19b3538bd2127902a89987474e1a4db8e43a66a4d1a712ab9a504ff define $(package)_set_vars $(package)_config_opts=--disable-static diff --git a/depends/packages/fontconfig.mk b/depends/packages/fontconfig.mk index 2cf553ed96..fb97e0b9ec 100644 --- a/depends/packages/fontconfig.mk +++ b/depends/packages/fontconfig.mk @@ -1,8 +1,8 @@ package=fontconfig -$(package)_version=2.11.1 +$(package)_version=2.12.1 $(package)_download_path=http://www.freedesktop.org/software/fontconfig/release/ $(package)_file_name=$(package)-$($(package)_version).tar.bz2 -$(package)_sha256_hash=dc62447533bca844463a3c3fd4083b57c90f18a70506e7a9f4936b5a1e516a99 +$(package)_sha256_hash=b449a3e10c47e1d1c7a6ec6e2016cca73d3bd68fbbd4f0ae5cc6b573f7d6c7f3 $(package)_dependencies=freetype expat define $(package)_set_vars diff --git a/depends/packages/libevent.mk b/depends/packages/libevent.mk index 2e9be1e98c..4b02b2eff9 100644 --- a/depends/packages/libevent.mk +++ b/depends/packages/libevent.mk @@ -3,10 +3,11 @@ $(package)_version=2.0.22 $(package)_download_path=https://github.com/libevent/libevent/releases/download/release-2.0.22-stable $(package)_file_name=$(package)-$($(package)_version)-stable.tar.gz $(package)_sha256_hash=71c2c49f0adadacfdbe6332a372c38cf9c8b7895bb73dabeaa53cdcc1d4e1fa3 -$(package)_patches=reuseaddr.patch +$(package)_patches=reuseaddr.patch libevent-2-fixes.patch define $(package)_preprocess_cmds - patch -p1 < $($(package)_patch_dir)/reuseaddr.patch + patch -p1 < $($(package)_patch_dir)/reuseaddr.patch && \ + patch -p1 < $($(package)_patch_dir)/libevent-2-fixes.patch endef define $(package)_set_vars diff --git a/depends/packages/native_ccache.mk b/depends/packages/native_ccache.mk index 9216e17598..a3a58604e5 100644 --- a/depends/packages/native_ccache.mk +++ b/depends/packages/native_ccache.mk @@ -1,8 +1,8 @@ package=native_ccache -$(package)_version=3.2.5 -$(package)_download_path=http://samba.org/ftp/ccache +$(package)_version=3.3.1 +$(package)_download_path=https://samba.org/ftp/ccache $(package)_file_name=ccache-$($(package)_version).tar.bz2 -$(package)_sha256_hash=7a553809e90faf9de3a23ee9c5b5f786cfd4836bf502744bedb824a24bee1097 +$(package)_sha256_hash=cb6e4bafbb19ba0a2ec43386b123a5f92a20e1e3384c071d5d13e0cb3c84bf73 define $(package)_set_vars $(package)_config_opts= diff --git a/depends/packages/qt.mk b/depends/packages/qt.mk index d41d0b9ea5..bdde15aa17 100644 --- a/depends/packages/qt.mk +++ b/depends/packages/qt.mk @@ -8,7 +8,7 @@ $(package)_dependencies=openssl $(package)_linux_dependencies=freetype fontconfig libxcb libX11 xproto libXext $(package)_build_subdir=qtbase $(package)_qt_libs=corelib network widgets gui plugins testlib -$(package)_patches=mac-qmake.conf mingw-uuidof.patch pidlist_absolute.patch fix-xcb-include-order.patch fix_qt_pkgconfig.patch +$(package)_patches=mac-qmake.conf configure-xcoderun.patch mingw-uuidof.patch pidlist_absolute.patch fix-xcb-include-order.patch fix_qt_pkgconfig.patch $(package)_qttranslations_file_name=qttranslations-$($(package)_suffix) $(package)_qttranslations_sha256_hash=dcc1534d247babca1840cb6d0a000671801a341ea352d0535474f86adadaf028 @@ -134,6 +134,7 @@ define $(package)_preprocess_cmds cp -f qtbase/mkspecs/macx-clang/Info.plist.app qtbase/mkspecs/macx-clang-linux/ &&\ cp -f qtbase/mkspecs/macx-clang/qplatformdefs.h qtbase/mkspecs/macx-clang-linux/ &&\ cp -f $($(package)_patch_dir)/mac-qmake.conf qtbase/mkspecs/macx-clang-linux/qmake.conf && \ + patch -p1 < $($(package)_patch_dir)/configure-xcoderun.patch && \ patch -p1 < $($(package)_patch_dir)/mingw-uuidof.patch && \ patch -p1 < $($(package)_patch_dir)/pidlist_absolute.patch && \ patch -p1 < $($(package)_patch_dir)/fix-xcb-include-order.patch && \ diff --git a/depends/patches/libevent/libevent-2-fixes.patch b/depends/patches/libevent/libevent-2-fixes.patch new file mode 100644 index 0000000000..79fec8a488 --- /dev/null +++ b/depends/patches/libevent/libevent-2-fixes.patch @@ -0,0 +1,18 @@ +--- a/util-internal.h 2013-11-01 12:18:57.000000000 -0600 ++++ b/util-internal.h 2015-07-20 20:19:43.199560900 -0500 +@@ -299,8 +299,13 @@ HANDLE evutil_load_windows_system_librar + + #if defined(__STDC__) && defined(__STDC_VERSION__) + #if (__STDC_VERSION__ >= 199901L) +-#define EV_SIZE_FMT "%zu" +-#define EV_SSIZE_FMT "%zd" ++ #if defined(_MSC_VER) || defined(__MINGW32__) || defined(__MINGW64__) ++ #define EV_SIZE_FMT "%Iu" ++ #define EV_SSIZE_FMT "%Id" ++ #else ++ #define EV_SIZE_FMT "%zu" ++ #define EV_SSIZE_FMT "%zd" ++ #endif + #define EV_SIZE_ARG(x) (x) + #define EV_SSIZE_ARG(x) (x) + #endif diff --git a/depends/patches/qt/configure-xcoderun.patch b/depends/patches/qt/configure-xcoderun.patch new file mode 100644 index 0000000000..08286d8420 --- /dev/null +++ b/depends/patches/qt/configure-xcoderun.patch @@ -0,0 +1,25 @@ +--- old/qtbase/configure ++++ new/qtbase/configure +@@ -543,7 +543,7 @@ if [ "$BUILD_ON_MAC" = "yes" ]; then + exit 2 + fi + +- if ! /usr/bin/xcrun -find xcrun >/dev/null 2>&1; then ++ if ! /usr/bin/xcrun -find xcodebuild >/dev/null 2>&1; then + echo >&2 + echo " Xcode not set up properly. You may need to confirm the license" >&2 + echo " agreement by running /usr/bin/xcodebuild without arguments." >&2 +diff --git a/mkspecs/features/mac/default_pre.prf b/mkspecs/features/mac/default_pre.prf +index 0cc8cd6..5df99d1 100644 +--- old/qtbase/mkspecs/features/mac/default_pre.prf ++++ new/qtbase/mkspecs/features/mac/default_pre.prf +@@ -12,7 +12,7 @@ isEmpty(QMAKE_XCODE_DEVELOPER_PATH) { + error("Xcode is not installed in $${QMAKE_XCODE_DEVELOPER_PATH}. Please use xcode-select to choose Xcode installation path.") + + # Make sure Xcode is set up properly +- isEmpty($$list($$system("/usr/bin/xcrun -find xcrun 2>/dev/null"))): \ ++ isEmpty($$list($$system("/usr/bin/xcrun -find xcodebuild 2>/dev/null"))): \ + error("Xcode not set up properly. You may need to confirm the license agreement by running /usr/bin/xcodebuild.") + } + +-- diff --git a/doc/build-osx.md b/doc/build-osx.md index c9eb4225ab..bc90a30562 100644 --- a/doc/build-osx.md +++ b/doc/build-osx.md @@ -16,7 +16,7 @@ Then install [Homebrew](http://brew.sh). Dependencies ---------------------- - brew install automake berkeley-db4 libtool boost --c++11 miniupnpc openssl pkg-config protobuf --c++11 qt5 libevent + brew install automake berkeley-db4 libtool boost --c++11 miniupnpc openssl pkg-config homebrew/versions/protobuf260 --c++11 qt5 libevent NOTE: Building with Qt4 is still supported, however, could result in a broken UI. Building with Qt5 is recommended. diff --git a/doc/build-windows.md b/doc/build-windows.md index 129774491b..ec5f26c88b 100644 --- a/doc/build-windows.md +++ b/doc/build-windows.md @@ -27,6 +27,7 @@ To build executables for Windows 32-bit: cd depends make HOST=i686-w64-mingw32 -j4 cd .. + ./autogen.sh # not required when building from tarball ./configure --prefix=`pwd`/depends/i686-w64-mingw32 make @@ -35,6 +36,7 @@ To build executables for Windows 64-bit: cd depends make HOST=x86_64-w64-mingw32 -j4 cd .. + ./autogen.sh # not required when building from tarball ./configure --prefix=`pwd`/depends/x86_64-w64-mingw32 make diff --git a/doc/gitian-building.md b/doc/gitian-building.md index 938f92ff12..4914d90df4 100644 --- a/doc/gitian-building.md +++ b/doc/gitian-building.md @@ -95,14 +95,14 @@ After creating the VM, we need to configure it. - Click `Ok` twice to save. -Get the [Debian 8.x net installer](http://cdimage.debian.org/debian-cd/8.5.0/amd64/iso-cd/debian-8.5.0-amd64-netinst.iso) (a more recent minor version should also work, see also [Debian Network installation](https://www.debian.org/CD/netinst/)). -This DVD image can be validated using a SHA256 hashing tool, for example on +Get the [Debian 8.x net installer](http://cdimage.debian.org/mirror/cdimage/archive/8.5.0/amd64/iso-cd/debian-8.5.0-amd64-netinst.iso) (a more recent minor version should also work, see also [Debian Network installation](https://www.debian.org/CD/netinst/)). +This DVD image can be [validated](https://www.debian.org/CD/verify) using a SHA256 hashing tool, for example on Unixy OSes by entering the following in a terminal: echo "ad4e8c27c561ad8248d5ebc1d36eb172f884057bfeb2c22ead823f59fa8c3dff debian-8.5.0-amd64-netinst.iso" | sha256sum -c # (must return OK) -Then start the VM. On the first launch you will be asked for a CD or DVD image. Choose the downloaded iso. +Then start the VM. On the first launch you will be asked for a CD or DVD image. Choose the downloaded ISO. ![](gitian-building/select_startup_disk.png) @@ -336,8 +336,8 @@ There will be a lot of warnings printed during the build of the image. These can Getting and building the inputs -------------------------------- -Follow the instructions in [doc/release-process.md](release-process.md#fetch-and-build-inputs-first-time-or-when-dependency-versions-change) -in the bitcoin repository under 'Fetch and build inputs' to install sources which require +Follow the instructions in [doc/release-process.md](release-process.md#fetch-and-create-inputs-first-time-or-when-dependency-versions-change) +in the bitcoin repository under 'Fetch and create inputs' to install sources which require manual intervention. Also optionally follow the next step: 'Seed the Gitian sources cache and offline git repositories' which will fetch the remaining files required for building offline. diff --git a/doc/man/Makefile.am b/doc/man/Makefile.am new file mode 100644 index 0000000000..5252ef4a19 --- /dev/null +++ b/doc/man/Makefile.am @@ -0,0 +1 @@ +dist_man1_MANS=bitcoind.1 bitcoin-qt.1 bitcoin-cli.1 bitcoin-tx.1 diff --git a/doc/man/bitcoin-cli.1 b/doc/man/bitcoin-cli.1 new file mode 100644 index 0000000000..11b690cf85 --- /dev/null +++ b/doc/man/bitcoin-cli.1 @@ -0,0 +1,84 @@ +.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.46.5. +.TH BITCOIN-CLI "1" "September 2016" "bitcoin-cli v0.13.0.0" "User Commands" +.SH NAME +bitcoin-cli \- manual page for bitcoin-cli v0.13.0.0 +.SH DESCRIPTION +Bitcoin Core RPC client version v0.13.0.0 +.SS "Usage:" +.TP +bitcoin\-cli [options] <command> [params] +Send command to Bitcoin Core +.TP +bitcoin\-cli [options] help +List commands +.TP +bitcoin\-cli [options] help <command> +Get help for a command +.SH OPTIONS +.HP +\-? +.IP +This help message +.HP +\fB\-conf=\fR<file> +.IP +Specify configuration file (default: bitcoin.conf) +.HP +\fB\-datadir=\fR<dir> +.IP +Specify data directory +.PP +Chain selection options: +.HP +\fB\-testnet\fR +.IP +Use the test chain +.HP +\fB\-regtest\fR +.IP +Enter regression test mode, which uses a special chain in which blocks +can be solved instantly. This is intended for regression testing +tools and app development. +.HP +\fB\-rpcconnect=\fR<ip> +.IP +Send commands to node running on <ip> (default: 127.0.0.1) +.HP +\fB\-rpcport=\fR<port> +.IP +Connect to JSON\-RPC on <port> (default: 8332 or testnet: 18332) +.HP +\fB\-rpcwait\fR +.IP +Wait for RPC server to start +.HP +\fB\-rpcuser=\fR<user> +.IP +Username for JSON\-RPC connections +.HP +\fB\-rpcpassword=\fR<pw> +.IP +Password for JSON\-RPC connections +.HP +\fB\-rpcclienttimeout=\fR<n> +.IP +Timeout during HTTP requests (default: 900) +.HP +\fB\-stdin\fR +.IP +Read extra arguments from standard input, one per line until EOF/Ctrl\-D +(recommended for sensitive information such as passphrases) +.SH COPYRIGHT +Copyright (C) 2009-2016 The Bitcoin Core developers + +Please contribute if you find Bitcoin Core useful. Visit +<https://bitcoincore.org> for further information about the software. +The source code is available from <https://github.com/bitcoin/bitcoin>. + +This is experimental software. +Distributed under the MIT software license, see the accompanying file COPYING +or <http://www.opensource.org/licenses/mit-license.php>. + +This product includes software developed by the OpenSSL Project for use in the +OpenSSL Toolkit <https://www.openssl.org/> and cryptographic software written +by Eric Young and UPnP software written by Thomas Bernard. diff --git a/doc/man/bitcoin-qt.1 b/doc/man/bitcoin-qt.1 new file mode 100644 index 0000000000..24b529dac1 --- /dev/null +++ b/doc/man/bitcoin-qt.1 @@ -0,0 +1,513 @@ +.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.46.5. +.TH BITCOIN-QT "1" "September 2016" "bitcoin-qt v0.13.0.0" "User Commands" +.SH NAME +bitcoin-qt \- manual page for bitcoin-qt v0.13.0.0 +.SH DESCRIPTION +Bitcoin Core version v0.13.0.0 (64\-bit) +Usage: +.IP +bitcoin\-qt [command\-line options] +.SH OPTIONS +.HP +\-? +.IP +Print this help message and exit +.HP +\fB\-version\fR +.IP +Print version and exit +.HP +\fB\-alertnotify=\fR<cmd> +.IP +Execute command when a relevant alert is received or we see a really +long fork (%s in cmd is replaced by message) +.HP +\fB\-blocknotify=\fR<cmd> +.IP +Execute command when the best block changes (%s in cmd is replaced by +block hash) +.HP +\fB\-checkblocks=\fR<n> +.IP +How many blocks to check at startup (default: 288, 0 = all) +.HP +\fB\-checklevel=\fR<n> +.IP +How thorough the block verification of \fB\-checkblocks\fR is (0\-4, default: 3) +.HP +\fB\-conf=\fR<file> +.IP +Specify configuration file (default: bitcoin.conf) +.HP +\fB\-datadir=\fR<dir> +.IP +Specify data directory +.HP +\fB\-dbcache=\fR<n> +.IP +Set database cache size in megabytes (4 to 16384, default: 300) +.HP +\fB\-loadblock=\fR<file> +.IP +Imports blocks from external blk000??.dat file on startup +.HP +\fB\-maxorphantx=\fR<n> +.IP +Keep at most <n> unconnectable transactions in memory (default: 100) +.HP +\fB\-maxmempool=\fR<n> +.IP +Keep the transaction memory pool below <n> megabytes (default: 300) +.HP +\fB\-mempoolexpiry=\fR<n> +.IP +Do not keep transactions in the mempool longer than <n> hours (default: +72) +.HP +\fB\-par=\fR<n> +.IP +Set the number of script verification threads (\fB\-4\fR to 16, 0 = auto, <0 = +leave that many cores free, default: 0) +.HP +\fB\-pid=\fR<file> +.IP +Specify pid file (default: bitcoind.pid) +.HP +\fB\-prune=\fR<n> +.IP +Reduce storage requirements by pruning (deleting) old blocks. This mode +is incompatible with \fB\-txindex\fR and \fB\-rescan\fR. Warning: Reverting +this setting requires re\-downloading the entire blockchain. +(default: 0 = disable pruning blocks, >550 = target size in MiB +to use for block files) +.HP +\fB\-reindex\-chainstate\fR +.IP +Rebuild chain state from the currently indexed blocks +.HP +\fB\-reindex\fR +.IP +Rebuild chain state and block index from the blk*.dat files on disk +.HP +\fB\-sysperms\fR +.IP +Create new files with system default permissions, instead of umask 077 +(only effective with disabled wallet functionality) +.HP +\fB\-txindex\fR +.IP +Maintain a full transaction index, used by the getrawtransaction rpc +call (default: 0) +.PP +Connection options: +.HP +\fB\-addnode=\fR<ip> +.IP +Add a node to connect to and attempt to keep the connection open +.HP +\fB\-banscore=\fR<n> +.IP +Threshold for disconnecting misbehaving peers (default: 100) +.HP +\fB\-bantime=\fR<n> +.IP +Number of seconds to keep misbehaving peers from reconnecting (default: +86400) +.HP +\fB\-bind=\fR<addr> +.IP +Bind to given address and always listen on it. Use [host]:port notation +for IPv6 +.HP +\fB\-connect=\fR<ip> +.IP +Connect only to the specified node(s) +.HP +\fB\-discover\fR +.IP +Discover own IP addresses (default: 1 when listening and no \fB\-externalip\fR +or \fB\-proxy\fR) +.HP +\fB\-dns\fR +.IP +Allow DNS lookups for \fB\-addnode\fR, \fB\-seednode\fR and \fB\-connect\fR (default: 1) +.HP +\fB\-dnsseed\fR +.IP +Query for peer addresses via DNS lookup, if low on addresses (default: 1 +unless \fB\-connect\fR) +.HP +\fB\-externalip=\fR<ip> +.IP +Specify your own public address +.HP +\fB\-forcednsseed\fR +.IP +Always query for peer addresses via DNS lookup (default: 0) +.HP +\fB\-listen\fR +.IP +Accept connections from outside (default: 1 if no \fB\-proxy\fR or \fB\-connect\fR) +.HP +\fB\-listenonion\fR +.IP +Automatically create Tor hidden service (default: 1) +.HP +\fB\-maxconnections=\fR<n> +.IP +Maintain at most <n> connections to peers (default: 125) +.HP +\fB\-maxreceivebuffer=\fR<n> +.IP +Maximum per\-connection receive buffer, <n>*1000 bytes (default: 5000) +.HP +\fB\-maxsendbuffer=\fR<n> +.IP +Maximum per\-connection send buffer, <n>*1000 bytes (default: 1000) +.HP +\fB\-maxtimeadjustment\fR +.IP +Maximum allowed median peer time offset adjustment. Local perspective of +time may be influenced by peers forward or backward by this +amount. (default: 4200 seconds) +.HP +\fB\-onion=\fR<ip:port> +.IP +Use separate SOCKS5 proxy to reach peers via Tor hidden services +(default: \fB\-proxy\fR) +.HP +\fB\-onlynet=\fR<net> +.IP +Only connect to nodes in network <net> (ipv4, ipv6 or onion) +.HP +\fB\-permitbaremultisig\fR +.IP +Relay non\-P2SH multisig (default: 1) +.HP +\fB\-peerbloomfilters\fR +.IP +Support filtering of blocks and transaction with bloom filters (default: +1) +.HP +\fB\-port=\fR<port> +.IP +Listen for connections on <port> (default: 8333 or testnet: 18333) +.HP +\fB\-proxy=\fR<ip:port> +.IP +Connect through SOCKS5 proxy +.HP +\fB\-proxyrandomize\fR +.IP +Randomize credentials for every proxy connection. This enables Tor +stream isolation (default: 1) +.HP +\fB\-seednode=\fR<ip> +.IP +Connect to a node to retrieve peer addresses, and disconnect +.HP +\fB\-timeout=\fR<n> +.IP +Specify connection timeout in milliseconds (minimum: 1, default: 5000) +.HP +\fB\-torcontrol=\fR<ip>:<port> +.IP +Tor control port to use if onion listening enabled (default: +127.0.0.1:9051) +.HP +\fB\-torpassword=\fR<pass> +.IP +Tor control port password (default: empty) +.HP +\fB\-whitebind=\fR<addr> +.IP +Bind to given address and whitelist peers connecting to it. Use +[host]:port notation for IPv6 +.HP +\fB\-whitelist=\fR<netmask> +.IP +Whitelist peers connecting from the given netmask or IP address. Can be +specified multiple times. Whitelisted peers cannot be DoS banned +and their transactions are always relayed, even if they are +already in the mempool, useful e.g. for a gateway +.HP +\fB\-whitelistrelay\fR +.IP +Accept relayed transactions received from whitelisted peers even when +not relaying transactions (default: 1) +.HP +\fB\-whitelistforcerelay\fR +.IP +Force relay of transactions from whitelisted peers even they violate +local relay policy (default: 1) +.HP +\fB\-maxuploadtarget=\fR<n> +.IP +Tries to keep outbound traffic under the given target (in MiB per 24h), +0 = no limit (default: 0) +.PP +Wallet options: +.HP +\fB\-disablewallet\fR +.IP +Do not load the wallet and disable wallet RPC calls +.HP +\fB\-keypool=\fR<n> +.IP +Set key pool size to <n> (default: 100) +.HP +\fB\-fallbackfee=\fR<amt> +.IP +A fee rate (in BTC/kB) that will be used when fee estimation has +insufficient data (default: 0.0002) +.HP +\fB\-mintxfee=\fR<amt> +.IP +Fees (in BTC/kB) smaller than this are considered zero fee for +transaction creation (default: 0.00001) +.HP +\fB\-paytxfee=\fR<amt> +.IP +Fee (in BTC/kB) to add to transactions you send (default: 0.00) +.HP +\fB\-rescan\fR +.IP +Rescan the block chain for missing wallet transactions on startup +.HP +\fB\-salvagewallet\fR +.IP +Attempt to recover private keys from a corrupt wallet on startup +.HP +\fB\-spendzeroconfchange\fR +.IP +Spend unconfirmed change when sending transactions (default: 1) +.HP +\fB\-txconfirmtarget=\fR<n> +.IP +If paytxfee is not set, include enough fee so transactions begin +confirmation on average within n blocks (default: 2) +.HP +\fB\-usehd\fR +.IP +Use hierarchical deterministic key generation (HD) after BIP32. Only has +effect during wallet creation/first start (default: 1) +.HP +\fB\-upgradewallet\fR +.IP +Upgrade wallet to latest format on startup +.HP +\fB\-wallet=\fR<file> +.IP +Specify wallet file (within data directory) (default: wallet.dat) +.HP +\fB\-walletbroadcast\fR +.IP +Make the wallet broadcast transactions (default: 1) +.HP +\fB\-walletnotify=\fR<cmd> +.IP +Execute command when a wallet transaction changes (%s in cmd is replaced +by TxID) +.HP +\fB\-zapwallettxes=\fR<mode> +.IP +Delete all wallet transactions and only recover those parts of the +blockchain through \fB\-rescan\fR on startup (1 = keep tx meta data e.g. +account owner and payment request information, 2 = drop tx meta +data) +.PP +ZeroMQ notification options: +.HP +\fB\-zmqpubhashblock=\fR<address> +.IP +Enable publish hash block in <address> +.HP +\fB\-zmqpubhashtx=\fR<address> +.IP +Enable publish hash transaction in <address> +.HP +\fB\-zmqpubrawblock=\fR<address> +.IP +Enable publish raw block in <address> +.HP +\fB\-zmqpubrawtx=\fR<address> +.IP +Enable publish raw transaction in <address> +.PP +Debugging/Testing options: +.HP +\fB\-uacomment=\fR<cmt> +.IP +Append comment to the user agent string +.HP +\fB\-debug=\fR<category> +.IP +Output debugging information (default: 0, supplying <category> is +optional). If <category> is not supplied or if <category> = 1, +output all debugging information.<category> can be: addrman, +alert, bench, coindb, db, http, libevent, lock, mempool, +mempoolrej, net, proxy, prune, rand, reindex, rpc, selectcoins, +tor, zmq, qt. +.HP +\fB\-help\-debug\fR +.IP +Show all debugging options (usage: \fB\-\-help\fR \fB\-help\-debug\fR) +.HP +\fB\-logips\fR +.IP +Include IP addresses in debug output (default: 0) +.HP +\fB\-logtimestamps\fR +.IP +Prepend debug output with timestamp (default: 1) +.HP +\fB\-minrelaytxfee=\fR<amt> +.IP +Fees (in BTC/kB) smaller than this are considered zero fee for relaying, +mining and transaction creation (default: 0.00001) +.HP +\fB\-maxtxfee=\fR<amt> +.IP +Maximum total fees (in BTC) to use in a single wallet transaction or raw +transaction; setting this too low may abort large transactions +(default: 0.10) +.HP +\fB\-printtoconsole\fR +.IP +Send trace/debug info to console instead of debug.log file +.HP +\fB\-shrinkdebugfile\fR +.IP +Shrink debug.log file on client startup (default: 1 when no \fB\-debug\fR) +.PP +Chain selection options: +.HP +\fB\-testnet\fR +.IP +Use the test chain +.PP +Node relay options: +.HP +\fB\-bytespersigop\fR +.IP +Equivalent bytes per sigop in transactions for relay and mining +(default: 20) +.HP +\fB\-datacarrier\fR +.IP +Relay and mine data carrier transactions (default: 1) +.HP +\fB\-datacarriersize\fR +.IP +Maximum size of data in data carrier transactions we relay and mine +(default: 83) +.HP +\fB\-mempoolreplacement\fR +.IP +Enable transaction replacement in the memory pool (default: 1) +.PP +Block creation options: +.HP +\fB\-blockmaxweight=\fR<n> +.IP +Set maximum BIP141 block weight (default: 3000000) +.HP +\fB\-blockmaxsize=\fR<n> +.IP +Set maximum block size in bytes (default: 750000) +.HP +\fB\-blockprioritysize=\fR<n> +.IP +Set maximum size of high\-priority/low\-fee transactions in bytes +(default: 0) +.PP +RPC server options: +.HP +\fB\-server\fR +.IP +Accept command line and JSON\-RPC commands +.HP +\fB\-rest\fR +.IP +Accept public REST requests (default: 0) +.HP +\fB\-rpcbind=\fR<addr> +.IP +Bind to given address to listen for JSON\-RPC connections. Use +[host]:port notation for IPv6. This option can be specified +multiple times (default: bind to all interfaces) +.HP +\fB\-rpccookiefile=\fR<loc> +.IP +Location of the auth cookie (default: data dir) +.HP +\fB\-rpcuser=\fR<user> +.IP +Username for JSON\-RPC connections +.HP +\fB\-rpcpassword=\fR<pw> +.IP +Password for JSON\-RPC connections +.HP +\fB\-rpcauth=\fR<userpw> +.IP +Username and hashed password for JSON\-RPC connections. The field +<userpw> comes in the format: <USERNAME>:<SALT>$<HASH>. A +canonical python script is included in share/rpcuser. This option +can be specified multiple times +.HP +\fB\-rpcport=\fR<port> +.IP +Listen for JSON\-RPC connections on <port> (default: 8332 or testnet: +18332) +.HP +\fB\-rpcallowip=\fR<ip> +.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 +.HP +\fB\-rpcthreads=\fR<n> +.IP +Set the number of threads to service RPC calls (default: 4) +.PP +UI Options: +.HP +\fB\-choosedatadir\fR +.IP +Choose data directory on startup (default: 0) +.HP +\fB\-lang=\fR<lang> +.IP +Set language, for example "de_DE" (default: system locale) +.HP +\fB\-min\fR +.IP +Start minimized +.HP +\fB\-rootcertificates=\fR<file> +.IP +Set SSL root certificates for payment request (default: \fB\-system\-\fR) +.HP +\fB\-splash\fR +.IP +Show splash screen on startup (default: 1) +.HP +\fB\-resetguisettings\fR +.IP +Reset all settings changed in the GUI +.SH COPYRIGHT +Copyright (C) 2009-2016 The Bitcoin Core developers + +Please contribute if you find Bitcoin Core useful. Visit +<https://bitcoincore.org> for further information about the software. +The source code is available from <https://github.com/bitcoin/bitcoin>. + +This is experimental software. +Distributed under the MIT software license, see the accompanying file COPYING +or <http://www.opensource.org/licenses/mit-license.php>. + +This product includes software developed by the OpenSSL Project for use in the +OpenSSL Toolkit <https://www.openssl.org/> and cryptographic software written +by Eric Young and UPnP software written by Thomas Bernard. diff --git a/doc/man/bitcoin-tx.1 b/doc/man/bitcoin-tx.1 new file mode 100644 index 0000000000..5c4e31e7f7 --- /dev/null +++ b/doc/man/bitcoin-tx.1 @@ -0,0 +1,107 @@ +.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.46.5. +.TH BITCOIN-TX "1" "September 2016" "bitcoin-tx v0.13.0.0" "User Commands" +.SH NAME +bitcoin-tx \- manual page for bitcoin-tx v0.13.0.0 +.SH DESCRIPTION +Bitcoin Core bitcoin\-tx utility version v0.13.0.0 +.SS "Usage:" +.TP +bitcoin\-tx [options] <hex\-tx> [commands] +Update hex\-encoded bitcoin transaction +.TP +bitcoin\-tx [options] \fB\-create\fR [commands] +Create hex\-encoded bitcoin transaction +.SH OPTIONS +.HP +\-? +.IP +This help message +.HP +\fB\-create\fR +.IP +Create new, empty TX. +.HP +\fB\-json\fR +.IP +Select JSON output +.HP +\fB\-txid\fR +.IP +Output only the hex\-encoded transaction id of the resultant transaction. +.PP +Chain selection options: +.HP +\fB\-testnet\fR +.IP +Use the test chain +.HP +\fB\-regtest\fR +.IP +Enter regression test mode, which uses a special chain in which blocks +can be solved instantly. This is intended for regression testing +tools and app development. +.PP +Commands: +.IP +delin=N +.IP +Delete input N from TX +.IP +delout=N +.IP +Delete output N from TX +.IP +in=TXID:VOUT(:SEQUENCE_NUMBER) +.IP +Add input to TX +.IP +locktime=N +.IP +Set TX lock time to N +.IP +nversion=N +.IP +Set TX version to N +.IP +outaddr=VALUE:ADDRESS +.IP +Add address\-based output to TX +.IP +outdata=[VALUE:]DATA +.IP +Add data\-based output to TX +.IP +outscript=VALUE:SCRIPT +.IP +Add raw script output to TX +.IP +sign=SIGHASH\-FLAGS +.IP +Add zero or more signatures to transaction. This command requires JSON +registers:prevtxs=JSON object, privatekeys=JSON object. See +signrawtransaction docs for format of sighash flags, JSON +objects. +.PP +Register Commands: +.IP +load=NAME:FILENAME +.IP +Load JSON file FILENAME into register NAME +.IP +set=NAME:JSON\-STRING +.IP +Set register NAME to given JSON\-STRING +.SH COPYRIGHT +Copyright (C) 2009-2016 The Bitcoin Core developers + +Please contribute if you find Bitcoin Core useful. Visit +<https://bitcoincore.org> for further information about the software. +The source code is available from <https://github.com/bitcoin/bitcoin>. + +This is experimental software. +Distributed under the MIT software license, see the accompanying file COPYING +or <http://www.opensource.org/licenses/mit-license.php>. + +This product includes software developed by the OpenSSL Project for use in the +OpenSSL Toolkit <https://www.openssl.org/> and cryptographic software written +by Eric Young and UPnP software written by Thomas Bernard. diff --git a/doc/man/bitcoind.1 b/doc/man/bitcoind.1 new file mode 100644 index 0000000000..b99657a5fa --- /dev/null +++ b/doc/man/bitcoind.1 @@ -0,0 +1,492 @@ +.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.46.5. +.TH BITCOIND "1" "September 2016" "bitcoind v0.13.0.0" "User Commands" +.SH NAME +bitcoind \- manual page for bitcoind v0.13.0.0 +.SH DESCRIPTION +Bitcoin Core Daemon version v0.13.0.0 +.SS "Usage:" +.TP +bitcoind [options] +Start Bitcoin Core Daemon +.SH OPTIONS +.HP +\-? +.IP +Print this help message and exit +.HP +\fB\-version\fR +.IP +Print version and exit +.HP +\fB\-alertnotify=\fR<cmd> +.IP +Execute command when a relevant alert is received or we see a really +long fork (%s in cmd is replaced by message) +.HP +\fB\-blocknotify=\fR<cmd> +.IP +Execute command when the best block changes (%s in cmd is replaced by +block hash) +.HP +\fB\-checkblocks=\fR<n> +.IP +How many blocks to check at startup (default: 288, 0 = all) +.HP +\fB\-checklevel=\fR<n> +.IP +How thorough the block verification of \fB\-checkblocks\fR is (0\-4, default: 3) +.HP +\fB\-conf=\fR<file> +.IP +Specify configuration file (default: bitcoin.conf) +.HP +\fB\-daemon\fR +.IP +Run in the background as a daemon and accept commands +.HP +\fB\-datadir=\fR<dir> +.IP +Specify data directory +.HP +\fB\-dbcache=\fR<n> +.IP +Set database cache size in megabytes (4 to 16384, default: 300) +.HP +\fB\-loadblock=\fR<file> +.IP +Imports blocks from external blk000??.dat file on startup +.HP +\fB\-maxorphantx=\fR<n> +.IP +Keep at most <n> unconnectable transactions in memory (default: 100) +.HP +\fB\-maxmempool=\fR<n> +.IP +Keep the transaction memory pool below <n> megabytes (default: 300) +.HP +\fB\-mempoolexpiry=\fR<n> +.IP +Do not keep transactions in the mempool longer than <n> hours (default: +72) +.HP +\fB\-par=\fR<n> +.IP +Set the number of script verification threads (\fB\-4\fR to 16, 0 = auto, <0 = +leave that many cores free, default: 0) +.HP +\fB\-pid=\fR<file> +.IP +Specify pid file (default: bitcoind.pid) +.HP +\fB\-prune=\fR<n> +.IP +Reduce storage requirements by pruning (deleting) old blocks. This mode +is incompatible with \fB\-txindex\fR and \fB\-rescan\fR. Warning: Reverting +this setting requires re\-downloading the entire blockchain. +(default: 0 = disable pruning blocks, >550 = target size in MiB +to use for block files) +.HP +\fB\-reindex\-chainstate\fR +.IP +Rebuild chain state from the currently indexed blocks +.HP +\fB\-reindex\fR +.IP +Rebuild chain state and block index from the blk*.dat files on disk +.HP +\fB\-sysperms\fR +.IP +Create new files with system default permissions, instead of umask 077 +(only effective with disabled wallet functionality) +.HP +\fB\-txindex\fR +.IP +Maintain a full transaction index, used by the getrawtransaction rpc +call (default: 0) +.PP +Connection options: +.HP +\fB\-addnode=\fR<ip> +.IP +Add a node to connect to and attempt to keep the connection open +.HP +\fB\-banscore=\fR<n> +.IP +Threshold for disconnecting misbehaving peers (default: 100) +.HP +\fB\-bantime=\fR<n> +.IP +Number of seconds to keep misbehaving peers from reconnecting (default: +86400) +.HP +\fB\-bind=\fR<addr> +.IP +Bind to given address and always listen on it. Use [host]:port notation +for IPv6 +.HP +\fB\-connect=\fR<ip> +.IP +Connect only to the specified node(s) +.HP +\fB\-discover\fR +.IP +Discover own IP addresses (default: 1 when listening and no \fB\-externalip\fR +or \fB\-proxy\fR) +.HP +\fB\-dns\fR +.IP +Allow DNS lookups for \fB\-addnode\fR, \fB\-seednode\fR and \fB\-connect\fR (default: 1) +.HP +\fB\-dnsseed\fR +.IP +Query for peer addresses via DNS lookup, if low on addresses (default: 1 +unless \fB\-connect\fR) +.HP +\fB\-externalip=\fR<ip> +.IP +Specify your own public address +.HP +\fB\-forcednsseed\fR +.IP +Always query for peer addresses via DNS lookup (default: 0) +.HP +\fB\-listen\fR +.IP +Accept connections from outside (default: 1 if no \fB\-proxy\fR or \fB\-connect\fR) +.HP +\fB\-listenonion\fR +.IP +Automatically create Tor hidden service (default: 1) +.HP +\fB\-maxconnections=\fR<n> +.IP +Maintain at most <n> connections to peers (default: 125) +.HP +\fB\-maxreceivebuffer=\fR<n> +.IP +Maximum per\-connection receive buffer, <n>*1000 bytes (default: 5000) +.HP +\fB\-maxsendbuffer=\fR<n> +.IP +Maximum per\-connection send buffer, <n>*1000 bytes (default: 1000) +.HP +\fB\-maxtimeadjustment\fR +.IP +Maximum allowed median peer time offset adjustment. Local perspective of +time may be influenced by peers forward or backward by this +amount. (default: 4200 seconds) +.HP +\fB\-onion=\fR<ip:port> +.IP +Use separate SOCKS5 proxy to reach peers via Tor hidden services +(default: \fB\-proxy\fR) +.HP +\fB\-onlynet=\fR<net> +.IP +Only connect to nodes in network <net> (ipv4, ipv6 or onion) +.HP +\fB\-permitbaremultisig\fR +.IP +Relay non\-P2SH multisig (default: 1) +.HP +\fB\-peerbloomfilters\fR +.IP +Support filtering of blocks and transaction with bloom filters (default: +1) +.HP +\fB\-port=\fR<port> +.IP +Listen for connections on <port> (default: 8333 or testnet: 18333) +.HP +\fB\-proxy=\fR<ip:port> +.IP +Connect through SOCKS5 proxy +.HP +\fB\-proxyrandomize\fR +.IP +Randomize credentials for every proxy connection. This enables Tor +stream isolation (default: 1) +.HP +\fB\-seednode=\fR<ip> +.IP +Connect to a node to retrieve peer addresses, and disconnect +.HP +\fB\-timeout=\fR<n> +.IP +Specify connection timeout in milliseconds (minimum: 1, default: 5000) +.HP +\fB\-torcontrol=\fR<ip>:<port> +.IP +Tor control port to use if onion listening enabled (default: +127.0.0.1:9051) +.HP +\fB\-torpassword=\fR<pass> +.IP +Tor control port password (default: empty) +.HP +\fB\-whitebind=\fR<addr> +.IP +Bind to given address and whitelist peers connecting to it. Use +[host]:port notation for IPv6 +.HP +\fB\-whitelist=\fR<netmask> +.IP +Whitelist peers connecting from the given netmask or IP address. Can be +specified multiple times. Whitelisted peers cannot be DoS banned +and their transactions are always relayed, even if they are +already in the mempool, useful e.g. for a gateway +.HP +\fB\-whitelistrelay\fR +.IP +Accept relayed transactions received from whitelisted peers even when +not relaying transactions (default: 1) +.HP +\fB\-whitelistforcerelay\fR +.IP +Force relay of transactions from whitelisted peers even they violate +local relay policy (default: 1) +.HP +\fB\-maxuploadtarget=\fR<n> +.IP +Tries to keep outbound traffic under the given target (in MiB per 24h), +0 = no limit (default: 0) +.PP +Wallet options: +.HP +\fB\-disablewallet\fR +.IP +Do not load the wallet and disable wallet RPC calls +.HP +\fB\-keypool=\fR<n> +.IP +Set key pool size to <n> (default: 100) +.HP +\fB\-fallbackfee=\fR<amt> +.IP +A fee rate (in BTC/kB) that will be used when fee estimation has +insufficient data (default: 0.0002) +.HP +\fB\-mintxfee=\fR<amt> +.IP +Fees (in BTC/kB) smaller than this are considered zero fee for +transaction creation (default: 0.00001) +.HP +\fB\-paytxfee=\fR<amt> +.IP +Fee (in BTC/kB) to add to transactions you send (default: 0.00) +.HP +\fB\-rescan\fR +.IP +Rescan the block chain for missing wallet transactions on startup +.HP +\fB\-salvagewallet\fR +.IP +Attempt to recover private keys from a corrupt wallet on startup +.HP +\fB\-spendzeroconfchange\fR +.IP +Spend unconfirmed change when sending transactions (default: 1) +.HP +\fB\-txconfirmtarget=\fR<n> +.IP +If paytxfee is not set, include enough fee so transactions begin +confirmation on average within n blocks (default: 2) +.HP +\fB\-usehd\fR +.IP +Use hierarchical deterministic key generation (HD) after BIP32. Only has +effect during wallet creation/first start (default: 1) +.HP +\fB\-upgradewallet\fR +.IP +Upgrade wallet to latest format on startup +.HP +\fB\-wallet=\fR<file> +.IP +Specify wallet file (within data directory) (default: wallet.dat) +.HP +\fB\-walletbroadcast\fR +.IP +Make the wallet broadcast transactions (default: 1) +.HP +\fB\-walletnotify=\fR<cmd> +.IP +Execute command when a wallet transaction changes (%s in cmd is replaced +by TxID) +.HP +\fB\-zapwallettxes=\fR<mode> +.IP +Delete all wallet transactions and only recover those parts of the +blockchain through \fB\-rescan\fR on startup (1 = keep tx meta data e.g. +account owner and payment request information, 2 = drop tx meta +data) +.PP +ZeroMQ notification options: +.HP +\fB\-zmqpubhashblock=\fR<address> +.IP +Enable publish hash block in <address> +.HP +\fB\-zmqpubhashtx=\fR<address> +.IP +Enable publish hash transaction in <address> +.HP +\fB\-zmqpubrawblock=\fR<address> +.IP +Enable publish raw block in <address> +.HP +\fB\-zmqpubrawtx=\fR<address> +.IP +Enable publish raw transaction in <address> +.PP +Debugging/Testing options: +.HP +\fB\-uacomment=\fR<cmt> +.IP +Append comment to the user agent string +.HP +\fB\-debug=\fR<category> +.IP +Output debugging information (default: 0, supplying <category> is +optional). If <category> is not supplied or if <category> = 1, +output all debugging information.<category> can be: addrman, +alert, bench, coindb, db, http, libevent, lock, mempool, +mempoolrej, net, proxy, prune, rand, reindex, rpc, selectcoins, +tor, zmq. +.HP +\fB\-help\-debug\fR +.IP +Show all debugging options (usage: \fB\-\-help\fR \fB\-help\-debug\fR) +.HP +\fB\-logips\fR +.IP +Include IP addresses in debug output (default: 0) +.HP +\fB\-logtimestamps\fR +.IP +Prepend debug output with timestamp (default: 1) +.HP +\fB\-minrelaytxfee=\fR<amt> +.IP +Fees (in BTC/kB) smaller than this are considered zero fee for relaying, +mining and transaction creation (default: 0.00001) +.HP +\fB\-maxtxfee=\fR<amt> +.IP +Maximum total fees (in BTC) to use in a single wallet transaction or raw +transaction; setting this too low may abort large transactions +(default: 0.10) +.HP +\fB\-printtoconsole\fR +.IP +Send trace/debug info to console instead of debug.log file +.HP +\fB\-shrinkdebugfile\fR +.IP +Shrink debug.log file on client startup (default: 1 when no \fB\-debug\fR) +.PP +Chain selection options: +.HP +\fB\-testnet\fR +.IP +Use the test chain +.PP +Node relay options: +.HP +\fB\-bytespersigop\fR +.IP +Equivalent bytes per sigop in transactions for relay and mining +(default: 20) +.HP +\fB\-datacarrier\fR +.IP +Relay and mine data carrier transactions (default: 1) +.HP +\fB\-datacarriersize\fR +.IP +Maximum size of data in data carrier transactions we relay and mine +(default: 83) +.HP +\fB\-mempoolreplacement\fR +.IP +Enable transaction replacement in the memory pool (default: 1) +.PP +Block creation options: +.HP +\fB\-blockmaxweight=\fR<n> +.IP +Set maximum BIP141 block weight (default: 3000000) +.HP +\fB\-blockmaxsize=\fR<n> +.IP +Set maximum block size in bytes (default: 750000) +.HP +\fB\-blockprioritysize=\fR<n> +.IP +Set maximum size of high\-priority/low\-fee transactions in bytes +(default: 0) +.PP +RPC server options: +.HP +\fB\-server\fR +.IP +Accept command line and JSON\-RPC commands +.HP +\fB\-rest\fR +.IP +Accept public REST requests (default: 0) +.HP +\fB\-rpcbind=\fR<addr> +.IP +Bind to given address to listen for JSON\-RPC connections. Use +[host]:port notation for IPv6. This option can be specified +multiple times (default: bind to all interfaces) +.HP +\fB\-rpccookiefile=\fR<loc> +.IP +Location of the auth cookie (default: data dir) +.HP +\fB\-rpcuser=\fR<user> +.IP +Username for JSON\-RPC connections +.HP +\fB\-rpcpassword=\fR<pw> +.IP +Password for JSON\-RPC connections +.HP +\fB\-rpcauth=\fR<userpw> +.IP +Username and hashed password for JSON\-RPC connections. The field +<userpw> comes in the format: <USERNAME>:<SALT>$<HASH>. A +canonical python script is included in share/rpcuser. This option +can be specified multiple times +.HP +\fB\-rpcport=\fR<port> +.IP +Listen for JSON\-RPC connections on <port> (default: 8332 or testnet: +18332) +.HP +\fB\-rpcallowip=\fR<ip> +.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 +.HP +\fB\-rpcthreads=\fR<n> +.IP +Set the number of threads to service RPC calls (default: 4) +.SH COPYRIGHT +Copyright (C) 2009-2016 The Bitcoin Core developers + +Please contribute if you find Bitcoin Core useful. Visit +<https://bitcoincore.org> for further information about the software. +The source code is available from <https://github.com/bitcoin/bitcoin>. + +This is experimental software. +Distributed under the MIT software license, see the accompanying file COPYING +or <http://www.opensource.org/licenses/mit-license.php>. + +This product includes software developed by the OpenSSL Project for use in the +OpenSSL Toolkit <https://www.openssl.org/> and cryptographic software written +by Eric Young and UPnP software written by Thomas Bernard. diff --git a/doc/reduce-traffic.md b/doc/reduce-traffic.md index 2d86588eb2..697099beab 100644 --- a/doc/reduce-traffic.md +++ b/doc/reduce-traffic.md @@ -19,8 +19,7 @@ This is *not* a hard limit; only a threshold to minimize the outbound traffic. When the limit is about to be reached, the uploaded data is cut by no longer serving historic blocks (blocks older than one week). Keep in mind that new nodes require other nodes that are willing to serve -historic blocks. **The recommended minimum is 144 blocks per day (max. 144MB -per day)** +historic blocks. Whitelisted peers will never be disconnected, although their traffic counts for calculating the target. diff --git a/doc/release-process.md b/doc/release-process.md index 394b159b31..04d9473c20 100644 --- a/doc/release-process.md +++ b/doc/release-process.md @@ -5,6 +5,8 @@ Before every release candidate: * Update translations (ping wumpus on IRC) see [translation_process.md](https://github.com/bitcoin/bitcoin/blob/master/doc/translation_process.md#synchronising-translations). +* Update manpages, see [gen-manpages.sh](https://github.com/bitcoin/bitcoin/blob/master/contrib/devtools/README.md#gen-manpagessh). + Before every minor and major release: * Update [bips.md](bips.md) to account for changes since the last release. diff --git a/doc/tor.md b/doc/tor.md index 79f1563021..2f376af4c7 100644 --- a/doc/tor.md +++ b/doc/tor.md @@ -113,4 +113,13 @@ the user running bitcoind to the same group and setting permissions appropriatel Debian-based systems the user running bitcoind can be added to the debian-tor group, which has the appropriate permissions. An alternative authentication method is the use of the `-torpassword` flag and a `hash-password` which can be enabled and specified in -Tor configuration.
\ No newline at end of file +Tor configuration. + +4. Privacy recommendations +--------------------------- + +- Do not add anything but bitcoin ports to the hidden service created in section 2. + If you run a web service too, create a new hidden service for that. + Otherwise it is trivial to link them, which may reduce privacy. Hidden + services created automatically (as in section 3) always have only one port + open. diff --git a/doc/translation_process.md b/doc/translation_process.md index a443a16fe2..9e9ced2457 100644 --- a/doc/translation_process.md +++ b/doc/translation_process.md @@ -6,7 +6,7 @@ The Bitcoin-Core project has been designed to support multiple localisations. Th ### Helping to translate (using Transifex) Transifex is setup to monitor the Github repo for updates, and when code containing new translations is found, Transifex will process any changes. It may take several hours after a pull-request has been merged, to appear in the Transifex web interface. -Multiple language support is critical in assisting Bitcoin’s global adoption, and growth. One of Bitcoin’s greatest strengths is cross-boarder money transfers, any help making that easier is greatly appreciated. +Multiple language support is critical in assisting Bitcoin’s global adoption, and growth. One of Bitcoin’s greatest strengths is cross-border money transfers, any help making that easier is greatly appreciated. See the [Transifex Bitcoin project](https://www.transifex.com/projects/p/bitcoin/) to assist in translations. You should also join the translation mailing list for announcements - see details below. diff --git a/qa/pull-tester/rpc-tests.py b/qa/pull-tester/rpc-tests.py index 771f6c7a0f..4a953385e0 100755 --- a/qa/pull-tester/rpc-tests.py +++ b/qa/pull-tester/rpc-tests.py @@ -143,6 +143,7 @@ testScripts = [ 'importprunedfunds.py', 'signmessages.py', 'p2p-compactblocks.py', + 'nulldummy.py', ] if ENABLE_ZMQ: testScripts.append('zmq_test.py') @@ -215,8 +216,8 @@ def runtests(): time_sum += duration print('\n' + BOLD[1] + name + BOLD[0] + ":") - print(stdout) - print('stderr:\n' if not stderr == '' else '', stderr) + print('' if passed else stdout + '\n', end='') + print('' if stderr == '' else 'stderr:\n' + stderr + '\n', end='') results += "%s | %s | %s s\n" % (name.ljust(max_len_name), str(passed).ljust(6), duration) print("Pass: %s%s%s, Duration: %s s\n" % (BOLD[1], passed, BOLD[0], duration)) results += BOLD[1] + "\n%s | %s | %s s (accumulated)" % ("ALL".ljust(max_len_name), str(all_passed).ljust(6), time_sum) + BOLD[0] @@ -251,21 +252,27 @@ class RPCTestHandler: self.num_running += 1 t = self.test_list.pop(0) port_seed = ["--portseed=%s" % len(self.test_list)] + log_stdout = tempfile.SpooledTemporaryFile(max_size=2**16) + log_stderr = tempfile.SpooledTemporaryFile(max_size=2**16) self.jobs.append((t, time.time(), subprocess.Popen((RPC_TESTS_DIR + t).split() + self.flags + port_seed, universal_newlines=True, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE))) + stdout=log_stdout, + stderr=log_stderr), + log_stdout, + log_stderr)) if not self.jobs: raise IndexError('pop from empty list') while True: # Return first proc that finishes time.sleep(.5) for j in self.jobs: - (name, time0, proc) = j + (name, time0, proc, log_out, log_err) = j if proc.poll() is not None: - (stdout, stderr) = proc.communicate(timeout=3) + log_out.seek(0), log_err.seek(0) + [stdout, stderr] = [l.read().decode('utf-8') for l in (log_out, log_err)] + log_out.close(), log_err.close() passed = stderr == "" and proc.returncode == 0 self.num_running -= 1 self.jobs.remove(j) diff --git a/qa/rpc-tests/create_cache.py b/qa/rpc-tests/create_cache.py index b6161e0917..1ace6310d0 100755 --- a/qa/rpc-tests/create_cache.py +++ b/qa/rpc-tests/create_cache.py @@ -12,9 +12,15 @@ from test_framework.test_framework import BitcoinTestFramework class CreateCache(BitcoinTestFramework): + def __init__(self): + super().__init__() + + # Test network and test nodes are not required: + self.num_nodes = 0 + self.nodes = [] + def setup_network(self): - # Don't setup any test nodes - self.options.noshutdown = True + pass def run_test(self): pass diff --git a/qa/rpc-tests/nulldummy.py b/qa/rpc-tests/nulldummy.py new file mode 100755 index 0000000000..eaed7a8c78 --- /dev/null +++ b/qa/rpc-tests/nulldummy.py @@ -0,0 +1,148 @@ +#!/usr/bin/env python3 +# Copyright (c) 2016 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +from test_framework.test_framework import ComparisonTestFramework +from test_framework.util import * +from test_framework.mininode import CTransaction, NetworkThread +from test_framework.blocktools import create_coinbase, create_block, add_witness_commitment +from test_framework.comptool import TestManager +from test_framework.script import CScript +from io import BytesIO +import time + +NULLDUMMY_ERROR = "64: non-mandatory-script-verify-flag (Dummy CHECKMULTISIG argument must be zero)" + +def trueDummy(tx): + scriptSig = CScript(tx.vin[0].scriptSig) + newscript = [] + for i in scriptSig: + if (len(newscript) == 0): + assert(len(i) == 0) + newscript.append(b'\x51') + else: + newscript.append(i) + tx.vin[0].scriptSig = CScript(newscript) + tx.rehash() + +''' +This test is meant to exercise NULLDUMMY softfork. +Connect to a single node. +Generate 2 blocks (save the coinbases for later). +Generate 427 more blocks. +[Policy/Consensus] Check that NULLDUMMY compliant transactions are accepted in the 430th block. +[Policy] Check that non-NULLDUMMY transactions are rejected before activation. +[Consensus] Check that the new NULLDUMMY rules are not enforced on the 431st block. +[Policy/Consensus] Check that the new NULLDUMMY rules are enforced on the 432nd block. +''' + +class NULLDUMMYTest(ComparisonTestFramework): + + def __init__(self): + super().__init__() + self.num_nodes = 1 + + def setup_network(self): + # Must set the blockversion for this test + self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, + extra_args=[['-debug', '-whitelist=127.0.0.1', '-walletprematurewitness']]) + + def run_test(self): + self.address = self.nodes[0].getnewaddress() + self.ms_address = self.nodes[0].addmultisigaddress(1,[self.address]) + self.wit_address = self.nodes[0].addwitnessaddress(self.address) + self.wit_ms_address = self.nodes[0].addwitnessaddress(self.ms_address) + + test = TestManager(self, self.options.tmpdir) + test.add_all_connections(self.nodes) + NetworkThread().start() # Start up network handling in another thread + self.coinbase_blocks = self.nodes[0].generate(2) # Block 2 + coinbase_txid = [] + for i in self.coinbase_blocks: + coinbase_txid.append(self.nodes[0].getblock(i)['tx'][0]) + self.nodes[0].generate(427) # Block 429 + self.lastblockhash = self.nodes[0].getbestblockhash() + self.tip = int("0x" + self.lastblockhash, 0) + self.lastblockheight = 429 + self.lastblocktime = int(time.time()) + 429 + + print ("Test 1: NULLDUMMY compliant base transactions should be accepted to mempool and mined before activation [430]") + test1txs = [self.create_transaction(self.nodes[0], coinbase_txid[0], self.ms_address, 49)] + txid1 = self.tx_submit(self.nodes[0], test1txs[0]) + test1txs.append(self.create_transaction(self.nodes[0], txid1, self.ms_address, 48)) + txid2 = self.tx_submit(self.nodes[0], test1txs[1]) + test1txs.append(self.create_transaction(self.nodes[0], coinbase_txid[1], self.wit_ms_address, 49)) + txid3 = self.tx_submit(self.nodes[0], test1txs[2]) + self.block_submit(self.nodes[0], test1txs, False, True) + + print ("Test 2: Non-NULLDUMMY base multisig transaction should not be accepted to mempool before activation") + test2tx = self.create_transaction(self.nodes[0], txid2, self.ms_address, 48) + trueDummy(test2tx) + txid4 = self.tx_submit(self.nodes[0], test2tx, NULLDUMMY_ERROR) + + print ("Test 3: Non-NULLDUMMY base transactions should be accepted in a block before activation [431]") + self.block_submit(self.nodes[0], [test2tx], False, True) + + print ("Test 4: Non-NULLDUMMY base multisig transaction is invalid after activation") + test4tx = self.create_transaction(self.nodes[0], txid4, self.address, 47) + test6txs=[CTransaction(test4tx)] + trueDummy(test4tx) + self.tx_submit(self.nodes[0], test4tx, NULLDUMMY_ERROR) + self.block_submit(self.nodes[0], [test4tx]) + + print ("Test 5: Non-NULLDUMMY P2WSH multisig transaction invalid after activation") + test5tx = self.create_transaction(self.nodes[0], txid3, self.wit_address, 48) + test6txs.append(CTransaction(test5tx)) + test5tx.wit.vtxinwit[0].scriptWitness.stack[0] = b'\x01' + self.tx_submit(self.nodes[0], test5tx, NULLDUMMY_ERROR) + self.block_submit(self.nodes[0], [test5tx], True) + + print ("Test 6: NULLDUMMY compliant base/witness transactions should be accepted to mempool and in block after activation [432]") + for i in test6txs: + self.tx_submit(self.nodes[0], i) + self.block_submit(self.nodes[0], test6txs, True, True) + + + def create_transaction(self, node, txid, to_address, amount): + inputs = [{ "txid" : txid, "vout" : 0}] + outputs = { to_address : amount } + rawtx = node.createrawtransaction(inputs, outputs) + signresult = node.signrawtransaction(rawtx) + tx = CTransaction() + f = BytesIO(hex_str_to_bytes(signresult['hex'])) + tx.deserialize(f) + return tx + + + def tx_submit(self, node, tx, msg = ""): + tx.rehash() + try: + node.sendrawtransaction(bytes_to_hex_str(tx.serialize_with_witness()), True) + except JSONRPCException as exp: + assert_equal(exp.error["message"], msg) + return tx.hash + + + def block_submit(self, node, txs, witness = False, accept = False): + block = create_block(self.tip, create_coinbase(self.lastblockheight + 1), self.lastblocktime + 1) + block.nVersion = 4 + for tx in txs: + tx.rehash() + block.vtx.append(tx) + block.hashMerkleRoot = block.calc_merkle_root() + witness and add_witness_commitment(block) + block.rehash() + block.solve() + node.submitblock(bytes_to_hex_str(block.serialize(True))) + if (accept): + assert_equal(node.getbestblockhash(), block.hash) + self.tip = block.sha256 + self.lastblockhash = block.hash + self.lastblocktime += 1 + self.lastblockheight += 1 + else: + assert_equal(node.getbestblockhash(), self.lastblockhash) + +if __name__ == '__main__': + NULLDUMMYTest().main()
\ No newline at end of file diff --git a/qa/rpc-tests/p2p-compactblocks.py b/qa/rpc-tests/p2p-compactblocks.py index 7fe7ecc16c..bf4fb43add 100755 --- a/qa/rpc-tests/p2p-compactblocks.py +++ b/qa/rpc-tests/p2p-compactblocks.py @@ -78,6 +78,13 @@ class TestNode(SingleNodeConnCB): headers_message.headers = [CBlockHeader(b) for b in new_blocks] self.send_message(headers_message) + def request_headers_and_sync(self, locator, hashstop=0): + self.clear_block_announcement() + self.get_headers(locator, hashstop) + assert(wait_until(self.received_block_announcement, timeout=30)) + assert(self.received_block_announcement()) + self.clear_block_announcement() + class CompactBlocksTest(BitcoinTestFramework): def __init__(self): @@ -130,7 +137,7 @@ class CompactBlocksTest(BitcoinTestFramework): # Test "sendcmpct": # - No compact block announcements or getdata(MSG_CMPCT_BLOCK) unless # sendcmpct is sent. - # - If sendcmpct is sent with version > 0, the message is ignored. + # - If sendcmpct is sent with version > 1, the message is ignored. # - If sendcmpct is sent with boolean 0, then block announcements are not # made with compact blocks. # - If sendcmpct is then sent with boolean 1, then new block announcements @@ -142,57 +149,66 @@ class CompactBlocksTest(BitcoinTestFramework): def received_sendcmpct(): return (self.test_node.last_sendcmpct is not None) got_message = wait_until(received_sendcmpct, timeout=30) + assert(received_sendcmpct()) assert(got_message) assert_equal(self.test_node.last_sendcmpct.version, 1) tip = int(self.nodes[0].getbestblockhash(), 16) def check_announcement_of_new_block(node, peer, predicate): - self.test_node.clear_block_announcement() + peer.clear_block_announcement() node.generate(1) - got_message = wait_until(peer.received_block_announcement, timeout=30) + got_message = wait_until(lambda: peer.block_announced, timeout=30) + assert(peer.block_announced) assert(got_message) with mininode_lock: - assert(predicate) + assert(predicate(peer)) # We shouldn't get any block announcements via cmpctblock yet. - check_announcement_of_new_block(self.nodes[0], self.test_node, lambda: self.test_node.last_cmpctblock is None) + check_announcement_of_new_block(self.nodes[0], self.test_node, lambda p: p.last_cmpctblock is None) # Try one more time, this time after requesting headers. - self.test_node.clear_block_announcement() - self.test_node.get_headers(locator=[tip], hashstop=0) - wait_until(self.test_node.received_block_announcement, timeout=30) - self.test_node.clear_block_announcement() + self.test_node.request_headers_and_sync(locator=[tip]) + check_announcement_of_new_block(self.nodes[0], self.test_node, lambda p: p.last_cmpctblock is None and p.last_inv is not None) - check_announcement_of_new_block(self.nodes[0], self.test_node, lambda: self.test_node.last_cmpctblock is None and self.test_node.last_inv is not None) + # Test a few ways of using sendcmpct that should NOT + # result in compact block announcements. + # Before each test, sync the headers chain. + self.test_node.request_headers_and_sync(locator=[tip]) # Now try a SENDCMPCT message with too-high version sendcmpct = msg_sendcmpct() sendcmpct.version = 2 - self.test_node.send_message(sendcmpct) + self.test_node.send_and_ping(sendcmpct) + check_announcement_of_new_block(self.nodes[0], self.test_node, lambda p: p.last_cmpctblock is None) - check_announcement_of_new_block(self.nodes[0], self.test_node, lambda: self.test_node.last_cmpctblock is None) + # Headers sync before next test. + self.test_node.request_headers_and_sync(locator=[tip]) # Now try a SENDCMPCT message with valid version, but announce=False - self.test_node.send_message(msg_sendcmpct()) - check_announcement_of_new_block(self.nodes[0], self.test_node, lambda: self.test_node.last_cmpctblock is None) + self.test_node.send_and_ping(msg_sendcmpct()) + check_announcement_of_new_block(self.nodes[0], self.test_node, lambda p: p.last_cmpctblock is None) + + # Headers sync before next test. + self.test_node.request_headers_and_sync(locator=[tip]) # Finally, try a SENDCMPCT message with announce=True sendcmpct.version = 1 sendcmpct.announce = True - self.test_node.send_message(sendcmpct) - check_announcement_of_new_block(self.nodes[0], self.test_node, lambda: self.test_node.last_cmpctblock is not None) + self.test_node.send_and_ping(sendcmpct) + check_announcement_of_new_block(self.nodes[0], self.test_node, lambda p: p.last_cmpctblock is not None) - # Try one more time - check_announcement_of_new_block(self.nodes[0], self.test_node, lambda: self.test_node.last_cmpctblock is not None) + # Try one more time (no headers sync should be needed!) + check_announcement_of_new_block(self.nodes[0], self.test_node, lambda p: p.last_cmpctblock is not None) # Try one more time, after turning on sendheaders - self.test_node.send_message(msg_sendheaders()) - check_announcement_of_new_block(self.nodes[0], self.test_node, lambda: self.test_node.last_cmpctblock is not None) + self.test_node.send_and_ping(msg_sendheaders()) + check_announcement_of_new_block(self.nodes[0], self.test_node, lambda p: p.last_cmpctblock is not None) # Now turn off announcements sendcmpct.announce = False - check_announcement_of_new_block(self.nodes[0], self.test_node, lambda: self.test_node.last_cmpctblock is None and self.test_node.last_headers is not None) + self.test_node.send_and_ping(sendcmpct) + check_announcement_of_new_block(self.nodes[0], self.test_node, lambda p: p.last_cmpctblock is None and p.last_headers is not None) # This test actually causes bitcoind to (reasonably!) disconnect us, so do this last. def test_invalid_cmpctblock_message(self): diff --git a/qa/rpc-tests/p2p-segwit.py b/qa/rpc-tests/p2p-segwit.py index ca784644d8..5c1eb21b1f 100755 --- a/qa/rpc-tests/p2p-segwit.py +++ b/qa/rpc-tests/p2p-segwit.py @@ -305,13 +305,18 @@ class SegWitTest(BitcoinTestFramework): sync_blocks(self.nodes) # We'll add an unnecessary witness to this transaction that would cause - # it to be too large according to IsStandard. + # it to be non-standard, to test that violating policy with a witness before + # segwit activation doesn't blind a node to a transaction. Transactions + # rejected for having a witness before segwit activation shouldn't be added + # to the rejection cache. tx3 = CTransaction() tx3.vin.append(CTxIn(COutPoint(tx2.sha256, 0), CScript([p2sh_program]))) tx3.vout.append(CTxOut(tx2.vout[0].nValue-1000, scriptPubKey)) tx3.wit.vtxinwit.append(CTxInWitness()) tx3.wit.vtxinwit[0].scriptWitness.stack = [b'a'*400000] tx3.rehash() + # Note that this should be rejected for the premature witness reason, + # rather than a policy check, since segwit hasn't activated yet. self.std_node.test_transaction_acceptance(tx3, True, False, b'no-witness-yet') # If we send without witness, it should be accepted. @@ -949,8 +954,7 @@ class SegWitTest(BitcoinTestFramework): self.test_node.test_transaction_acceptance(tx, with_witness=True, accepted=False) # Verify that removing the witness succeeds. - # Re-announcing won't result in a getdata for ~2.5 minutes, so just - # deliver the modified transaction. + self.test_node.announce_tx_and_wait_for_getdata(tx) self.test_node.test_transaction_acceptance(tx, with_witness=False, accepted=True) # Now try to add extra witness data to a valid witness tx. @@ -1388,6 +1392,9 @@ class SegWitTest(BitcoinTestFramework): block = self.build_next_block() used_sighash_single_out_of_bounds = False for i in range(NUM_TESTS): + # Ping regularly to keep the connection alive + if (not i % 100): + self.test_node.sync_with_ping() # Choose random number of inputs to use. num_inputs = random.randint(1, 10) # Create a slight bias for producing more utxos diff --git a/qa/rpc-tests/p2p-versionbits-warning.py b/qa/rpc-tests/p2p-versionbits-warning.py index 962cafef0b..00dbbc02cf 100755 --- a/qa/rpc-tests/p2p-versionbits-warning.py +++ b/qa/rpc-tests/p2p-versionbits-warning.py @@ -6,6 +6,7 @@ from test_framework.mininode import * from test_framework.test_framework import BitcoinTestFramework from test_framework.util import * +import re import time from test_framework.blocktools import create_block, create_coinbase @@ -21,6 +22,10 @@ VB_THRESHOLD = 108 # versionbits activation threshold for regtest VB_TOP_BITS = 0x20000000 VB_UNKNOWN_BIT = 27 # Choose a bit unassigned to any deployment +WARN_UNKNOWN_RULES_MINED = "Unknown block versions being mined! It's possible unknown rules are in effect" +WARN_UNKNOWN_RULES_ACTIVE = "unknown new rules activated (versionbit {})".format(VB_UNKNOWN_BIT) +VB_PATTERN = re.compile("^Warning.*versionbit") + # TestNode: bare-bones "peer". Used mostly as a conduit for a test to sending # p2p messages to a node, generating the messages in the main testing logic. class TestNode(NodeConnCB): @@ -65,16 +70,12 @@ class VersionBitsWarningTest(BitcoinTestFramework): self.num_nodes = 1 def setup_network(self): - self.nodes = [] self.alert_filename = os.path.join(self.options.tmpdir, "alert.txt") # Open and close to create zero-length file - with open(self.alert_filename, 'w') as f: + with open(self.alert_filename, 'w') as _: pass - self.node_options = ["-debug", "-logtimemicros=1", "-alertnotify=echo %s >> \"" + self.alert_filename + "\""] - self.nodes.append(start_node(0, self.options.tmpdir, self.node_options)) - - import re - self.vb_pattern = re.compile("^Warning.*versionbit") + self.extra_args = [["-debug", "-logtimemicros=1", "-alertnotify=echo %s >> \"" + self.alert_filename + "\""]] + self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, self.extra_args) # Send numblocks blocks via peer with nVersionToUse set. def send_blocks_with_version(self, peer, numblocks, nVersionToUse): @@ -83,7 +84,7 @@ class VersionBitsWarningTest(BitcoinTestFramework): block_time = self.nodes[0].getblockheader(tip)["time"]+1 tip = int(tip, 16) - for i in range(numblocks): + for _ in range(numblocks): block = create_block(tip, create_coinbase(height+1), block_time) block.nVersion = nVersionToUse block.solve() @@ -96,7 +97,7 @@ class VersionBitsWarningTest(BitcoinTestFramework): def test_versionbits_in_alert_file(self): with open(self.alert_filename, 'r') as f: alert_text = f.read() - assert(self.vb_pattern.match(alert_text)) + assert(VB_PATTERN.match(alert_text)) def run_test(self): # Setup the p2p connection and start up the network thread. @@ -122,8 +123,10 @@ class VersionBitsWarningTest(BitcoinTestFramework): # Fill rest of period with regular version blocks self.nodes[0].generate(VB_PERIOD - VB_THRESHOLD + 1) # Check that we're not getting any versionbit-related errors in - # getinfo() - assert(not self.vb_pattern.match(self.nodes[0].getinfo()["errors"])) + # get*info() + assert(not VB_PATTERN.match(self.nodes[0].getinfo()["errors"])) + assert(not VB_PATTERN.match(self.nodes[0].getmininginfo()["errors"])) + assert(not VB_PATTERN.match(self.nodes[0].getnetworkinfo()["warnings"])) # 3. Now build one period of blocks with >= VB_THRESHOLD blocks signaling # some unknown bit @@ -132,8 +135,10 @@ class VersionBitsWarningTest(BitcoinTestFramework): # Might not get a versionbits-related alert yet, as we should # have gotten a different alert due to more than 51/100 blocks # being of unexpected version. - # Check that getinfo() shows some kind of error. - assert(len(self.nodes[0].getinfo()["errors"]) != 0) + # Check that get*info() shows some kind of error. + assert(WARN_UNKNOWN_RULES_MINED in self.nodes[0].getinfo()["errors"]) + assert(WARN_UNKNOWN_RULES_MINED in self.nodes[0].getmininginfo()["errors"]) + assert(WARN_UNKNOWN_RULES_MINED in self.nodes[0].getnetworkinfo()["warnings"]) # Mine a period worth of expected blocks so the generic block-version warning # is cleared, and restart the node. This should move the versionbit state @@ -142,20 +147,21 @@ class VersionBitsWarningTest(BitcoinTestFramework): stop_node(self.nodes[0], 0) wait_bitcoinds() # Empty out the alert file - with open(self.alert_filename, 'w') as f: + with open(self.alert_filename, 'w') as _: pass - self.nodes[0] = start_node(0, self.options.tmpdir, ["-debug", "-logtimemicros=1", "-alertnotify=echo %s >> \"" + self.alert_filename + "\""]) + self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, self.extra_args) # Connecting one block should be enough to generate an error. self.nodes[0].generate(1) - assert(len(self.nodes[0].getinfo()["errors"]) != 0) + assert(WARN_UNKNOWN_RULES_ACTIVE in self.nodes[0].getinfo()["errors"]) + assert(WARN_UNKNOWN_RULES_ACTIVE in self.nodes[0].getmininginfo()["errors"]) + assert(WARN_UNKNOWN_RULES_ACTIVE in self.nodes[0].getnetworkinfo()["warnings"]) stop_node(self.nodes[0], 0) wait_bitcoinds() self.test_versionbits_in_alert_file() # Test framework expects the node to still be running... - self.nodes[0] = start_node(0, self.options.tmpdir, ["-debug", "-logtimemicros=1", "-alertnotify=echo %s >> \"" + self.alert_filename + "\""]) - + self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, self.extra_args) if __name__ == '__main__': VersionBitsWarningTest().main() diff --git a/qa/rpc-tests/pruning.py b/qa/rpc-tests/pruning.py index 7cbe69c29b..287dbc776e 100755 --- a/qa/rpc-tests/pruning.py +++ b/qa/rpc-tests/pruning.py @@ -157,7 +157,10 @@ class PruneTest(BitcoinTestFramework): print("Usage possibly still high bc of stale blocks in block files:", calc_usage(self.prunedir)) print("Mine 220 more blocks so we have requisite history (some blocks will be big and cause pruning of previous chain)") - self.nodes[0].generate(220) #node 0 has many large tx's in its mempool from the disconnects + for i in range(22): + # This can be slow, so do this in multiple RPC calls to avoid + # RPC timeouts. + self.nodes[0].generate(10) #node 0 has many large tx's in its mempool from the disconnects sync_blocks(self.nodes[0:3], timeout=300) usage = calc_usage(self.prunedir) diff --git a/qa/rpc-tests/rpcbind_test.py b/qa/rpc-tests/rpcbind_test.py index 3ac32140ba..085024e268 100755 --- a/qa/rpc-tests/rpcbind_test.py +++ b/qa/rpc-tests/rpcbind_test.py @@ -44,7 +44,7 @@ class RPCBindTest(BitcoinTestFramework): def run_allowip_test(self, allow_ips, rpchost, rpcport): ''' - Start a node with rpcwallow IP, and request getinfo + Start a node with rpcallow IP, and request getnetworkinfo at a non-localhost IP. ''' base_args = ['-disablewallet', '-nolisten'] + ['-rpcallowip='+x for x in allow_ips] @@ -52,7 +52,7 @@ class RPCBindTest(BitcoinTestFramework): try: # connect to node through non-loopback interface node = get_rpc_proxy(rpc_url(0, "%s:%d" % (rpchost, rpcport)), 0) - node.getinfo() + node.getnetworkinfo() finally: node = None # make sure connection will be garbage collected and closed stop_nodes(self.nodes) diff --git a/qa/rpc-tests/test_framework/authproxy.py b/qa/rpc-tests/test_framework/authproxy.py index d095a56ce7..f5e0be20d1 100644 --- a/qa/rpc-tests/test_framework/authproxy.py +++ b/qa/rpc-tests/test_framework/authproxy.py @@ -55,7 +55,11 @@ log = logging.getLogger("BitcoinRPC") class JSONRPCException(Exception): def __init__(self, rpc_error): - Exception.__init__(self) + try: + errmsg = '%(message)s (%(code)i)' % rpc_error + except (KeyError, TypeError): + errmsg = '' + Exception.__init__(self, errmsg) self.error = rpc_error diff --git a/qa/rpc-tests/test_framework/blockstore.py b/qa/rpc-tests/test_framework/blockstore.py index 6120dd574b..1e2bbb277a 100644 --- a/qa/rpc-tests/test_framework/blockstore.py +++ b/qa/rpc-tests/test_framework/blockstore.py @@ -1,4 +1,7 @@ #!/usr/bin/env python3 +# Copyright (c) 2015-2016 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. # BlockStore: a helper class that keeps a map of blocks and implements # helper functions for responding to getheaders and getdata, # and for constructing a getheaders message diff --git a/qa/rpc-tests/test_framework/script.py b/qa/rpc-tests/test_framework/script.py index b46c643ccb..83bbf20479 100644 --- a/qa/rpc-tests/test_framework/script.py +++ b/qa/rpc-tests/test_framework/script.py @@ -882,7 +882,7 @@ def SignatureHash(script, txTo, inIdx, hashtype): tmp = txtmp.vout[outIdx] txtmp.vout = [] for i in range(outIdx): - txtmp.vout.append(CTxOut()) + txtmp.vout.append(CTxOut(-1)) txtmp.vout.append(tmp) for i in range(len(txtmp.vin)): diff --git a/qa/rpc-tests/test_framework/test_framework.py b/qa/rpc-tests/test_framework/test_framework.py index a1383729fa..186cf866cf 100755 --- a/qa/rpc-tests/test_framework/test_framework.py +++ b/qa/rpc-tests/test_framework/test_framework.py @@ -125,7 +125,8 @@ class BitcoinTestFramework(object): self.add_options(parser) (self.options, self.args) = parser.parse_args() - self.options.tmpdir += '/' + str(self.options.port_seed) + # backup dir variable for removal at cleanup + self.options.root, self.options.tmpdir = self.options.tmpdir, self.options.tmpdir + '/' + str(self.options.port_seed) if self.options.trace_rpc: logging.basicConfig(level=logging.DEBUG, stream=sys.stdout) @@ -176,6 +177,8 @@ class BitcoinTestFramework(object): if not self.options.nocleanup and not self.options.noshutdown and success: print("Cleaning up") shutil.rmtree(self.options.tmpdir) + if not os.listdir(self.options.root): + os.rmdir(self.options.root) else: print("Not cleaning up dir %s" % self.options.tmpdir) diff --git a/qa/rpc-tests/wallet-hd.py b/qa/rpc-tests/wallet-hd.py index c11da1e9a9..a49d91f6f4 100755 --- a/qa/rpc-tests/wallet-hd.py +++ b/qa/rpc-tests/wallet-hd.py @@ -39,8 +39,8 @@ class WalletHDTest(BitcoinTestFramework): self.nodes[1].importprivkey(self.nodes[0].dumpprivkey(non_hd_add)) # This should be enough to keep the master key and the non-HD key - self.nodes[1].backupwallet(tmpdir + "hd.bak") - #self.nodes[1].dumpwallet(tmpdir + "hd.dump") + self.nodes[1].backupwallet(tmpdir + "/hd.bak") + #self.nodes[1].dumpwallet(tmpdir + "/hd.dump") # Derive some HD addresses and remember the last # Also send funds to each add @@ -63,7 +63,7 @@ class WalletHDTest(BitcoinTestFramework): print("Restore backup ...") self.stop_node(1) os.remove(self.options.tmpdir + "/node1/regtest/wallet.dat") - shutil.copyfile(tmpdir + "hd.bak", tmpdir + "/node1/regtest/wallet.dat") + shutil.copyfile(tmpdir + "/hd.bak", tmpdir + "/node1/regtest/wallet.dat") self.nodes[1] = start_node(1, self.options.tmpdir, self.node_args[1]) #connect_nodes_bi(self.nodes, 0, 1) diff --git a/qa/rpc-tests/wallet.py b/qa/rpc-tests/wallet.py index 5d96e7a6e5..3420be1a2e 100755 --- a/qa/rpc-tests/wallet.py +++ b/qa/rpc-tests/wallet.py @@ -18,9 +18,10 @@ class WalletTest (BitcoinTestFramework): super().__init__() self.setup_clean_chain = True self.num_nodes = 4 + self.extra_args = [['-usehd={:d}'.format(i%2==0)] for i in range(4)] def setup_network(self, split=False): - self.nodes = start_nodes(3, self.options.tmpdir) + self.nodes = start_nodes(3, self.options.tmpdir, self.extra_args[:3]) connect_nodes_bi(self.nodes,0,1) connect_nodes_bi(self.nodes,1,2) connect_nodes_bi(self.nodes,0,2) @@ -154,7 +155,7 @@ class WalletTest (BitcoinTestFramework): txid2 = self.nodes[1].sendtoaddress(self.nodes[0].getnewaddress(), 1) sync_mempools(self.nodes) - self.nodes.append(start_node(3, self.options.tmpdir)) + self.nodes.append(start_node(3, self.options.tmpdir, self.extra_args[3])) connect_nodes_bi(self.nodes, 0, 3) sync_blocks(self.nodes) diff --git a/qa/rpc-tests/walletbackup.py b/qa/rpc-tests/walletbackup.py index b991d5c761..e12cb10a50 100755 --- a/qa/rpc-tests/walletbackup.py +++ b/qa/rpc-tests/walletbackup.py @@ -45,12 +45,12 @@ class WalletBackupTest(BitcoinTestFramework): super().__init__() self.setup_clean_chain = True self.num_nodes = 4 + # nodes 1, 2,3 are spenders, let's give them a keypool=100 + self.extra_args = [["-keypool=100"], ["-keypool=100"], ["-keypool=100"], []] # This mirrors how the network was setup in the bash test def setup_network(self, split=False): - # nodes 1, 2,3 are spenders, let's give them a keypool=100 - extra_args = [["-keypool=100"], ["-keypool=100"], ["-keypool=100"], []] - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, extra_args) + self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, self.extra_args) connect_nodes(self.nodes[0], 3) connect_nodes(self.nodes[1], 3) connect_nodes(self.nodes[2], 3) @@ -79,6 +79,7 @@ class WalletBackupTest(BitcoinTestFramework): # Must sync mempools before mining. sync_mempools(self.nodes) self.nodes[3].generate(1) + sync_blocks(self.nodes) # As above, this mirrors the original bash test. def start_three(self): diff --git a/share/genbuild.sh b/share/genbuild.sh index 1ef77d706f..eecac4bd00 100755 --- a/share/genbuild.sh +++ b/share/genbuild.sh @@ -1,4 +1,8 @@ #!/bin/sh +# Copyright (c) 2012-2016 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + if [ $# -gt 1 ]; then cd "$2" fi diff --git a/share/qt/extract_strings_qt.py b/share/qt/extract_strings_qt.py index 9624abf1fc..92e0df259e 100755 --- a/share/qt/extract_strings_qt.py +++ b/share/qt/extract_strings_qt.py @@ -1,4 +1,7 @@ #!/usr/bin/env python +# Copyright (c) 2012-2016 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. ''' Extract _("...") strings for translation and convert to Qt stringdefs so that they can be picked up by Qt linguist. diff --git a/share/qt/protobuf.pri b/share/qt/protobuf.pri deleted file mode 100644 index 865fe86555..0000000000 --- a/share/qt/protobuf.pri +++ /dev/null @@ -1,35 +0,0 @@ -# Based on: http://code.google.com/p/ostinato/source/browse/protobuf.pri -# -# Qt qmake integration with Google Protocol Buffers compiler protoc -# -# To compile protocol buffers with qt qmake, specify PROTOS variable and -# include this file -# -# Example: -# PROTOS = a.proto b.proto -# include(protobuf.pri) -# -# Set PROTO_PATH if you need to set the protoc --proto_path search path -# Set PROTOC to the path to the protoc compiler if it is not in your $PATH -# - -isEmpty(PROTO_DIR):PROTO_DIR = . -isEmpty(PROTOC):PROTOC = protoc - -PROTOPATHS = -for(p, PROTO_PATH):PROTOPATHS += --proto_path=$${p} - -protobuf_decl.name = protobuf header -protobuf_decl.input = PROTOS -protobuf_decl.output = $${PROTO_DIR}/${QMAKE_FILE_BASE}.pb.h -protobuf_decl.commands = $${PROTOC} --cpp_out="$${PROTO_DIR}" $${PROTOPATHS} --proto_path=${QMAKE_FILE_IN_PATH} ${QMAKE_FILE_NAME} -protobuf_decl.variable_out = GENERATED_FILES -QMAKE_EXTRA_COMPILERS += protobuf_decl - -protobuf_impl.name = protobuf implementation -protobuf_impl.input = PROTOS -protobuf_impl.output = $${PROTO_DIR}/${QMAKE_FILE_BASE}.pb.cc -protobuf_impl.depends = $${PROTO_DIR}/${QMAKE_FILE_BASE}.pb.h -protobuf_impl.commands = $$escape_expand(\\n) -protobuf_impl.variable_out = GENERATED_SOURCES -QMAKE_EXTRA_COMPILERS += protobuf_impl diff --git a/src/Makefile.am b/src/Makefile.am index ebdddc87f5..e7f1d82b8b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,3 +1,7 @@ +# Copyright (c) 2013-2016 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + DIST_SUBDIRS = secp256k1 univalue AM_LDFLAGS = $(PTHREAD_CFLAGS) $(LIBTOOL_LDFLAGS) $(HARDENED_LDFLAGS) diff --git a/src/Makefile.bench.include b/src/Makefile.bench.include index 4067ceb399..8c024a8c4a 100644 --- a/src/Makefile.bench.include +++ b/src/Makefile.bench.include @@ -1,3 +1,7 @@ +# Copyright (c) 2015-2016 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + bin_PROGRAMS += bench/bench_bitcoin BENCH_SRCDIR = bench BENCH_BINARY = bench/bench_bitcoin$(EXEEXT) diff --git a/src/Makefile.leveldb.include b/src/Makefile.leveldb.include index 4b3cd6364a..d7346aa181 100644 --- a/src/Makefile.leveldb.include +++ b/src/Makefile.leveldb.include @@ -1,3 +1,7 @@ +# Copyright (c) 2016 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + LIBLEVELDB_INT = leveldb/libleveldb.a LIBMEMENV_INT = leveldb/libmemenv.a diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include index 8947aeaca0..a2ed4f47d8 100644 --- a/src/Makefile.qt.include +++ b/src/Makefile.qt.include @@ -1,3 +1,7 @@ +# Copyright (c) 2013-2016 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + bin_PROGRAMS += qt/bitcoin-qt EXTRA_LIBRARIES += qt/libbitcoinqt.a @@ -96,6 +100,7 @@ QT_FORMS_UI = \ qt/forms/editaddressdialog.ui \ qt/forms/helpmessagedialog.ui \ qt/forms/intro.ui \ + qt/forms/modaloverlay.ui \ qt/forms/openuridialog.ui \ qt/forms/optionsdialog.ui \ qt/forms/overviewpage.ui \ @@ -125,6 +130,7 @@ QT_MOC_CPP = \ qt/moc_intro.cpp \ qt/moc_macdockiconhandler.cpp \ qt/moc_macnotificationhandler.cpp \ + qt/moc_modaloverlay.cpp \ qt/moc_notificator.cpp \ qt/moc_openuridialog.cpp \ qt/moc_optionsdialog.cpp \ @@ -192,6 +198,7 @@ BITCOIN_QT_H = \ qt/intro.h \ qt/macdockiconhandler.h \ qt/macnotificationhandler.h \ + qt/modaloverlay.h \ qt/networkstyle.h \ qt/notificator.h \ qt/openuridialog.h \ @@ -292,6 +299,7 @@ BITCOIN_QT_CPP = \ qt/csvmodelwriter.cpp \ qt/guiutil.cpp \ qt/intro.cpp \ + qt/modaloverlay.cpp \ qt/networkstyle.cpp \ qt/notificator.cpp \ qt/optionsdialog.cpp \ diff --git a/src/Makefile.qttest.include b/src/Makefile.qttest.include index 813a343ffa..cb310d5a1b 100644 --- a/src/Makefile.qttest.include +++ b/src/Makefile.qttest.include @@ -1,13 +1,20 @@ +# Copyright (c) 2013-2016 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + bin_PROGRAMS += qt/test/test_bitcoin-qt TESTS += qt/test/test_bitcoin-qt -TEST_QT_MOC_CPP = qt/test/moc_uritests.cpp +TEST_QT_MOC_CPP = \ + qt/test/moc_rpcnestedtests.cpp \ + qt/test/moc_uritests.cpp if ENABLE_WALLET TEST_QT_MOC_CPP += qt/test/moc_paymentservertests.cpp endif TEST_QT_H = \ + qt/test/rpcnestedtests.h \ qt/test/uritests.h \ qt/test/paymentrequestdata.h \ qt/test/paymentservertests.h @@ -16,6 +23,7 @@ qt_test_test_bitcoin_qt_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(BITCOIN_ $(QT_INCLUDES) $(QT_TEST_INCLUDES) $(PROTOBUF_CFLAGS) qt_test_test_bitcoin_qt_SOURCES = \ + qt/test/rpcnestedtests.cpp \ qt/test/test_main.cpp \ qt/test/uritests.cpp \ $(TEST_QT_H) diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 0748d1a39d..5ce1bbb896 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -1,3 +1,7 @@ +# Copyright (c) 2013-2016 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + TESTS += test/test_bitcoin bin_PROGRAMS += test/test_bitcoin TEST_SRCDIR = test diff --git a/src/addrman.cpp b/src/addrman.cpp index cebb1c8e5e..bfb8e94575 100644 --- a/src/addrman.cpp +++ b/src/addrman.cpp @@ -255,6 +255,11 @@ bool CAddrMan::Add_(const CAddress& addr, const CNetAddr& source, int64_t nTimeP int nId; CAddrInfo* pinfo = Find(addr, &nId); + // Do not set a penality for a source's self-announcement + if (addr == source) { + nTimePenalty = 0; + } + if (pinfo) { // periodically update nTime bool fCurrentlyOnline = (GetAdjustedTime() - addr.nTime < 24 * 60 * 60); diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp index a04101d3ed..68f5d90f51 100644 --- a/src/bitcoin-cli.cpp +++ b/src/bitcoin-cli.cpp @@ -116,17 +116,42 @@ static bool AppInitRPC(int argc, char* argv[]) /** Reply structure for request_done to fill in */ struct HTTPReply { + HTTPReply(): status(0), error(-1) {} + int status; + int error; std::string body; }; +const char *http_errorstring(int code) +{ + switch(code) { +#if LIBEVENT_VERSION_NUMBER >= 0x02010300 + case EVREQ_HTTP_TIMEOUT: + return "timeout reached"; + case EVREQ_HTTP_EOF: + return "EOF reached"; + case EVREQ_HTTP_INVALID_HEADER: + return "error while reading header, or invalid header"; + case EVREQ_HTTP_BUFFER_ERROR: + return "error encountered while reading or writing"; + case EVREQ_HTTP_REQUEST_CANCEL: + return "request was canceled"; + case EVREQ_HTTP_DATA_TOO_LONG: + return "response body is larger than allowed"; +#endif + default: + return "unknown"; + } +} + static void http_request_done(struct evhttp_request *req, void *ctx) { HTTPReply *reply = static_cast<HTTPReply*>(ctx); if (req == NULL) { - /* If req is NULL, it means an error occurred while connecting, but - * I'm not sure how to find out which one. We also don't really care. + /* If req is NULL, it means an error occurred while connecting: the + * error code will have been passed to http_error_cb. */ reply->status = 0; return; @@ -145,6 +170,14 @@ static void http_request_done(struct evhttp_request *req, void *ctx) } } +#if LIBEVENT_VERSION_NUMBER >= 0x02010300 +static void http_error_cb(enum evhttp_request_error err, void *ctx) +{ + HTTPReply *reply = static_cast<HTTPReply*>(ctx); + reply->error = err; +} +#endif + UniValue CallRPC(const string& strMethod, const UniValue& params) { std::string host = GetArg("-rpcconnect", DEFAULT_RPCCONNECT); @@ -165,6 +198,9 @@ UniValue CallRPC(const string& strMethod, const UniValue& params) struct evhttp_request *req = evhttp_request_new(http_request_done, (void*)&response); // TODO RAII if (req == NULL) throw runtime_error("create http request failed"); +#if LIBEVENT_VERSION_NUMBER >= 0x02010300 + evhttp_request_set_error_cb(req, http_error_cb); +#endif // Get credentials std::string strRPCUserColonPass; @@ -204,7 +240,7 @@ UniValue CallRPC(const string& strMethod, const UniValue& params) event_base_free(base); if (response.status == 0) - throw CConnectionFailed("couldn't connect to server"); + throw CConnectionFailed(strprintf("couldn't connect to server (%d %s)", response.error, http_errorstring(response.error))); else if (response.status == HTTP_UNAUTHORIZED) throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)"); else if (response.status >= 400 && response.status != HTTP_BAD_REQUEST && response.status != HTTP_NOT_FOUND && response.status != HTTP_INTERNAL_SERVER_ERROR) diff --git a/src/bloom.cpp b/src/bloom.cpp index fd328e8e96..2677652ada 100644 --- a/src/bloom.cpp +++ b/src/bloom.cpp @@ -280,8 +280,8 @@ void CRollingBloomFilter::insert(const std::vector<unsigned char>& vKey) void CRollingBloomFilter::insert(const uint256& hash) { - vector<unsigned char> data(hash.begin(), hash.end()); - insert(data); + vector<unsigned char> vData(hash.begin(), hash.end()); + insert(vData); } bool CRollingBloomFilter::contains(const std::vector<unsigned char>& vKey) const @@ -300,8 +300,8 @@ bool CRollingBloomFilter::contains(const std::vector<unsigned char>& vKey) const bool CRollingBloomFilter::contains(const uint256& hash) const { - vector<unsigned char> data(hash.begin(), hash.end()); - return contains(data); + vector<unsigned char> vData(hash.begin(), hash.end()); + return contains(vData); } void CRollingBloomFilter::reset() diff --git a/src/coins.cpp b/src/coins.cpp index 39db7dedfb..8ff652b474 100644 --- a/src/coins.cpp +++ b/src/coins.cpp @@ -275,7 +275,7 @@ double CCoinsViewCache::GetPriority(const CTransaction &tx, int nHeight, CAmount assert(coins); if (!coins->IsAvailable(txin.prevout.n)) continue; if (coins->nHeight <= nHeight) { - dResult += coins->vout[txin.prevout.n].nValue * (nHeight-coins->nHeight); + dResult += (double)(coins->vout[txin.prevout.n].nValue) * (nHeight-coins->nHeight); inChainInputValue += coins->vout[txin.prevout.n].nValue; } } diff --git a/src/init.cpp b/src/init.cpp index e9552da67d..cb8da06d64 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -200,7 +200,6 @@ void Shutdown() pwalletMain->Flush(false); #endif MapPort(false); - g_connman->Stop(); g_connman.reset(); StopTorControl(); @@ -760,10 +759,7 @@ void InitParameterInteraction() if (GetBoolArg("-blocksonly", DEFAULT_BLOCKSONLY)) { if (SoftSetBoolArg("-whitelistrelay", false)) LogPrintf("%s: parameter interaction: -blocksonly=1 -> setting -whitelistrelay=0\n", __func__); -#ifdef ENABLE_WALLET - if (SoftSetBoolArg("-walletbroadcast", false)) - LogPrintf("%s: parameter interaction: -blocksonly=1 -> setting -walletbroadcast=0\n", __func__); -#endif + // walletbroadcast is disabled in CWallet::ParameterInteraction() } // Forcing relay from whitelisted hosts implies we will accept relays from them in the first place. @@ -822,12 +818,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) return InitError("Initializing networking failed"); #ifndef WIN32 - if (GetBoolArg("-sysperms", false)) { -#ifdef ENABLE_WALLET - if (!GetBoolArg("-disablewallet", false)) - return InitError("-sysperms is not allowed in combination with enabled wallet functionality"); -#endif - } else { + if (!GetBoolArg("-sysperms", false)) { umask(077); } @@ -855,15 +846,10 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) // also see: InitParameterInteraction() - // if using block pruning, then disable txindex + // if using block pruning, then disallow txindex if (GetArg("-prune", 0)) { if (GetBoolArg("-txindex", DEFAULT_TXINDEX)) return InitError(_("Prune mode is incompatible with -txindex.")); -#ifdef ENABLE_WALLET - if (GetBoolArg("-rescan", false)) { - return InitError(_("Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again.")); - } -#endif } // Make sure enough file descriptors are available @@ -949,9 +935,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) RegisterAllCoreRPCCommands(tableRPC); #ifdef ENABLE_WALLET - bool fDisableWallet = GetBoolArg("-disablewallet", false); - if (!fDisableWallet) - RegisterWalletRPCCommands(tableRPC); + RegisterWalletRPCCommands(tableRPC); #endif nConnectTimeout = GetArg("-timeout", DEFAULT_CONNECT_TIMEOUT); @@ -967,10 +951,10 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) if (mapArgs.count("-minrelaytxfee")) { CAmount n = 0; - if (ParseMoney(mapArgs["-minrelaytxfee"], n) && n > 0) - ::minRelayTxFee = CFeeRate(n); - else + if (!ParseMoney(mapArgs["-minrelaytxfee"], n) || 0 == n) return InitError(AmountErrMsg("minrelaytxfee", mapArgs["-minrelaytxfee"])); + // High fee check is done afterward in CWallet::ParameterInteraction() + ::minRelayTxFee = CFeeRate(n); } fRequireStandard = !GetBoolArg("-acceptnonstdtxn", !Params().RequireStandard()); @@ -981,7 +965,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) #ifdef ENABLE_WALLET if (!CWallet::ParameterInteraction()) return false; -#endif // ENABLE_WALLET +#endif fIsBareMultisigStd = GetBoolArg("-permitbaremultisig", DEFAULT_PERMIT_BAREMULTISIG); fAcceptDatacarrier = GetBoolArg("-datacarrier", DEFAULT_ACCEPT_DATACARRIER); @@ -1109,15 +1093,13 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) // ********************************************************* Step 5: verify wallet database integrity #ifdef ENABLE_WALLET - if (!fDisableWallet) { - if (!CWallet::Verify()) - return false; - } // (!fDisableWallet) -#endif // ENABLE_WALLET + if (!CWallet::Verify()) + return false; +#endif // ********************************************************* Step 6: network initialization assert(!g_connman); - g_connman = std::unique_ptr<CConnman>(new CConnman()); + g_connman = std::unique_ptr<CConnman>(new CConnman(GetRand(std::numeric_limits<uint64_t>::max()), GetRand(std::numeric_limits<uint64_t>::max()))); CConnman& connman = *g_connman; RegisterNodeSignals(GetNodeSignals()); @@ -1250,8 +1232,11 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) RegisterValidationInterface(pzmqNotificationInterface); } #endif + uint64_t nMaxOutboundLimit = 0; //unlimited unless -maxuploadtarget is set + uint64_t nMaxOutboundTimeframe = MAX_UPLOAD_TIMEFRAME; + if (mapArgs.count("-maxuploadtarget")) { - connman.SetMaxOutboundTarget(GetArg("-maxuploadtarget", DEFAULT_MAX_UPLOAD_TARGET)*1024*1024); + nMaxOutboundLimit = GetArg("-maxuploadtarget", DEFAULT_MAX_UPLOAD_TARGET)*1024*1024; } // ********************************************************* Step 7: load block chain @@ -1438,17 +1423,11 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) // ********************************************************* Step 8: load wallet #ifdef ENABLE_WALLET - if (fDisableWallet) { - pwalletMain = NULL; - LogPrintf("Wallet disabled!\n"); - } else { - CWallet::InitLoadWallet(); - if (!pwalletMain) - return false; - } -#else // ENABLE_WALLET + if (!CWallet::InitLoadWallet()) + return false; +#else LogPrintf("No wallet support compiled in!\n"); -#endif // !ENABLE_WALLET +#endif // ********************************************************* Step 9: data directory maintenance @@ -1534,6 +1513,9 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) connOptions.nSendBufferMaxSize = 1000*GetArg("-maxsendbuffer", DEFAULT_MAXSENDBUFFER); connOptions.nReceiveFloodSize = 1000*GetArg("-maxreceivebuffer", DEFAULT_MAXRECEIVEBUFFER); + connOptions.nMaxOutboundTimeframe = nMaxOutboundTimeframe; + connOptions.nMaxOutboundLimit = nMaxOutboundLimit; + if(!connman.Start(threadGroup, scheduler, strNodeError, connOptions)) return InitError(strNodeError); diff --git a/src/key.cpp b/src/key.cpp index 79023566c3..aae9b042ac 100644 --- a/src/key.cpp +++ b/src/key.cpp @@ -243,12 +243,12 @@ bool CKey::Derive(CKey& keyChild, ChainCode &ccChild, unsigned int nChild, const return ret; } -bool CExtKey::Derive(CExtKey &out, unsigned int nChild) const { +bool CExtKey::Derive(CExtKey &out, unsigned int _nChild) const { out.nDepth = nDepth + 1; CKeyID id = key.GetPubKey().GetID(); memcpy(&out.vchFingerprint[0], &id, 4); - out.nChild = nChild; - return key.Derive(out.key, out.chaincode, nChild, chaincode); + out.nChild = _nChild; + return key.Derive(out.key, out.chaincode, _nChild, chaincode); } void CExtKey::SetMaster(const unsigned char *seed, unsigned int nSeedLen) { diff --git a/src/main.cpp b/src/main.cpp index cb6e942272..c33b41ac4e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -113,6 +113,8 @@ CScript COINBASE_FLAGS; const string strMessageMagic = "Bitcoin Signed Message:\n"; +static const uint64_t RANDOMIZER_ID_ADDRESS_RELAY = 0x3cac0035b5866b90ULL; // SHA256("main address relay")[0:8] + // Internal stuff namespace { @@ -1183,9 +1185,9 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C bool fReplacementOptOut = true; if (fEnableReplacement) { - BOOST_FOREACH(const CTxIn &txin, ptxConflicting->vin) + BOOST_FOREACH(const CTxIn &_txin, ptxConflicting->vin) { - if (txin.nSequence < std::numeric_limits<unsigned int>::max()-1) + if (_txin.nSequence < std::numeric_limits<unsigned int>::max()-1) { fReplacementOptOut = false; break; @@ -2062,7 +2064,7 @@ bool UndoReadFromDisk(CBlockUndo& blockundo, const CDiskBlockPos& pos, const uin // Open history file to read CAutoFile filein(OpenUndoFile(pos, true), SER_DISK, CLIENT_VERSION); if (filein.IsNull()) - return error("%s: OpenBlockFile failed", __func__); + return error("%s: OpenUndoFile failed", __func__); // Read block uint256 hashChecksum; @@ -2386,6 +2388,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin // Start enforcing WITNESS rules using versionbits logic. if (IsWitnessEnabled(pindex->pprev, chainparams.GetConsensus())) { flags |= SCRIPT_VERIFY_WITNESS; + flags |= SCRIPT_VERIFY_NULLDUMMY; } int64_t nTime2 = GetTimeMicros(); nTimeForks += nTime2 - nTime1; @@ -2496,14 +2499,14 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin if (pindex->GetUndoPos().IsNull() || !pindex->IsValid(BLOCK_VALID_SCRIPTS)) { if (pindex->GetUndoPos().IsNull()) { - CDiskBlockPos pos; - if (!FindUndoPos(state, pindex->nFile, pos, ::GetSerializeSize(blockundo, SER_DISK, CLIENT_VERSION) + 40)) + CDiskBlockPos _pos; + if (!FindUndoPos(state, pindex->nFile, _pos, ::GetSerializeSize(blockundo, SER_DISK, CLIENT_VERSION) + 40)) return error("ConnectBlock(): FindUndoPos failed"); - if (!UndoWriteToDisk(blockundo, pos, pindex->pprev->GetBlockHash(), chainparams.MessageStart())) + if (!UndoWriteToDisk(blockundo, _pos, pindex->pprev->GetBlockHash(), chainparams.MessageStart())) return AbortNode(state, "Failed to write undo data"); // update nUndoPos in block index - pindex->nUndoPos = pos.nPos; + pindex->nUndoPos = _pos.nPos; pindex->nStatus |= BLOCK_HAVE_UNDO; } @@ -3816,10 +3819,10 @@ void PruneOneBlockFile(const int fileNumber) // mapBlocksUnlinked or setBlockIndexCandidates. std::pair<std::multimap<CBlockIndex*, CBlockIndex*>::iterator, std::multimap<CBlockIndex*, CBlockIndex*>::iterator> range = mapBlocksUnlinked.equal_range(pindex->pprev); while (range.first != range.second) { - std::multimap<CBlockIndex *, CBlockIndex *>::iterator it = range.first; + std::multimap<CBlockIndex *, CBlockIndex *>::iterator _it = range.first; range.first++; - if (it->second == pindex) { - mapBlocksUnlinked.erase(it); + if (_it->second == pindex) { + mapBlocksUnlinked.erase(_it); } } } @@ -4659,12 +4662,12 @@ std::string GetWarnings(const std::string& strFor) if (fLargeWorkForkFound) { strStatusBar = strRPC = "Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues."; - strGUI += strGUI.empty() ? "" : uiAlertSeperator + _("Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues."); + strGUI += (strGUI.empty() ? "" : uiAlertSeperator) + _("Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues."); } else if (fLargeWorkInvalidChainFound) { strStatusBar = strRPC = "Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade."; - strGUI += strGUI.empty() ? "" : uiAlertSeperator + _("Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade."); + strGUI += (strGUI.empty() ? "" : uiAlertSeperator) + _("Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade."); } if (strFor == "gui") @@ -4739,11 +4742,9 @@ static void RelayAddress(const CAddress& addr, bool fReachable, CConnman& connma // Relay to a limited number of other nodes // Use deterministic randomness to send to the same nodes for 24 hours // at a time so the addrKnowns of the chosen nodes prevent repeats - static const uint64_t salt0 = GetRand(std::numeric_limits<uint64_t>::max()); - static const uint64_t salt1 = GetRand(std::numeric_limits<uint64_t>::max()); uint64_t hashAddr = addr.GetHash(); std::multimap<uint64_t, CNode*> mapMix; - const CSipHasher hasher = CSipHasher(salt0, salt1).Write(hashAddr << 32).Write((GetTime() + hashAddr) / (24*60*60)); + const CSipHasher hasher = connman.GetDeterministicRandomizer(RANDOMIZER_ID_ADDRESS_RELAY).Write(hashAddr << 32).Write((GetTime() + hashAddr) / (24*60*60)); auto sortfunc = [&mapMix, &hasher](CNode* pnode) { if (pnode->nVersion >= CADDR_TIME_VERSION) { @@ -5549,9 +5550,9 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, } if (!fRejectedParents) { BOOST_FOREACH(const CTxIn& txin, tx.vin) { - CInv inv(MSG_TX, txin.prevout.hash); - pfrom->AddInventoryKnown(inv); - if (!AlreadyHave(inv)) pfrom->AskFor(inv); + CInv _inv(MSG_TX, txin.prevout.hash); + pfrom->AddInventoryKnown(_inv); + if (!AlreadyHave(_inv)) pfrom->AskFor(_inv); } AddOrphanTx(tx, pfrom->GetId()); @@ -6316,9 +6317,9 @@ class CompareInvMempoolOrder { CTxMemPool *mp; public: - CompareInvMempoolOrder(CTxMemPool *mempool) + CompareInvMempoolOrder(CTxMemPool *_mempool) { - mp = mempool; + mp = _mempool; } bool operator()(std::set<uint256>::iterator a, std::set<uint256>::iterator b) diff --git a/src/net.cpp b/src/net.cpp index b39ef9f54a..cce06f2d64 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -63,6 +63,7 @@ const static std::string NET_MESSAGE_COMMAND_OTHER = "*other*"; +static const uint64_t RANDOMIZER_ID_NETGROUP = 0x6c0edd8036ef4036ULL; // SHA256("netgroup")[0:8] // // Global state variables // @@ -387,7 +388,7 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo addrman.Attempt(addrConnect, fCountFailure); // Add node - CNode* pnode = new CNode(GetNewNodeId(), nLocalServices, GetBestHeight(), hSocket, addrConnect, pszDest ? pszDest : "", false); + CNode* pnode = new CNode(GetNewNodeId(), nLocalServices, GetBestHeight(), hSocket, addrConnect, CalculateKeyedNetGroup(addrConnect), pszDest ? pszDest : "", false); GetNodeSignals().InitializeNode(pnode->GetId(), pnode); pnode->AddRef(); @@ -448,7 +449,7 @@ void CNode::PushVersion() { int64_t nTime = (fInbound ? GetAdjustedTime() : GetTime()); CAddress addrYou = (addr.IsRoutable() && !IsProxy(addr) ? addr : CAddress(CService(), addr.nServices)); - CAddress addrMe = GetLocalAddress(&addr, nLocalServices); + CAddress addrMe = CAddress(CService(), nLocalServices); if (fLogIPs) LogPrint("net", "send version message: version %d, blocks=%d, us=%s, them=%s, peer=%d\n", PROTOCOL_VERSION, nMyStartingHeight, addrMe.ToString(), addrYou.ToString(), id); else @@ -1022,7 +1023,7 @@ void CConnman::AcceptConnection(const ListenSocket& hListenSocket) { } } - CNode* pnode = new CNode(GetNewNodeId(), nLocalServices, GetBestHeight(), hSocket, addr, "", true); + CNode* pnode = new CNode(GetNewNodeId(), nLocalServices, GetBestHeight(), hSocket, addr, CalculateKeyedNetGroup(addr), "", true); GetNodeSignals().InitializeNode(pnode->GetId(), pnode); pnode->AddRef(); pnode->fWhitelisted = whitelisted; @@ -2023,7 +2024,7 @@ void Discover(boost::thread_group& threadGroup) #endif } -CConnman::CConnman() +CConnman::CConnman(uint64_t nSeed0In, uint64_t nSeed1In) : nSeed0(nSeed0In), nSeed1(nSeed1In) { setBannedIsDirty = false; fAddressesInitialized = false; @@ -2046,9 +2047,7 @@ bool CConnman::Start(boost::thread_group& threadGroup, CScheduler& scheduler, st { nTotalBytesRecv = 0; nTotalBytesSent = 0; - nMaxOutboundLimit = 0; nMaxOutboundTotalBytesSentInCycle = 0; - nMaxOutboundTimeframe = 60*60*24; //1 day nMaxOutboundCycleStartTime = 0; nRelevantServices = connOptions.nRelevantServices; @@ -2060,6 +2059,9 @@ bool CConnman::Start(boost::thread_group& threadGroup, CScheduler& scheduler, st nSendBufferMaxSize = connOptions.nSendBufferMaxSize; nReceiveFloodSize = connOptions.nSendBufferMaxSize; + nMaxOutboundLimit = connOptions.nMaxOutboundLimit; + nMaxOutboundTimeframe = connOptions.nMaxOutboundTimeframe; + SetBestHeight(connOptions.nBestHeight); clientInterface = connOptions.uiInterface; @@ -2108,7 +2110,7 @@ bool CConnman::Start(boost::thread_group& threadGroup, CScheduler& scheduler, st if (pnodeLocalHost == NULL) { CNetAddr local; LookupHost("127.0.0.1", local, false); - pnodeLocalHost = new CNode(GetNewNodeId(), nLocalServices, GetBestHeight(), INVALID_SOCKET, CAddress(CService(local, 0), nLocalServices)); + pnodeLocalHost = new CNode(GetNewNodeId(), nLocalServices, GetBestHeight(), INVALID_SOCKET, CAddress(CService(local, 0), nLocalServices), 0); GetNodeSignals().InitializeNode(pnodeLocalHost->GetId(), pnodeLocalHost); } @@ -2205,6 +2207,7 @@ void CConnman::DeleteNode(CNode* pnode) CConnman::~CConnman() { + Stop(); } size_t CConnman::GetAddressCount() const @@ -2362,11 +2365,7 @@ void CConnman::RecordBytesSent(uint64_t bytes) void CConnman::SetMaxOutboundTarget(uint64_t limit) { LOCK(cs_totalBytesSent); - uint64_t recommendedMinimum = (nMaxOutboundTimeframe / 600) * MAX_BLOCK_SERIALIZED_SIZE; nMaxOutboundLimit = limit; - - if (limit > 0 && limit < recommendedMinimum) - LogPrintf("Max outbound target is very small (%s bytes) and will be overshot. Recommended minimum is %s bytes.\n", nMaxOutboundLimit, recommendedMinimum); } uint64_t CConnman::GetMaxOutboundTarget() @@ -2501,10 +2500,10 @@ void CNode::Fuzz(int nChance) unsigned int CConnman::GetReceiveFloodSize() const { return nReceiveFloodSize; } unsigned int CConnman::GetSendBufferSize() const{ return nSendBufferMaxSize; } -CNode::CNode(NodeId idIn, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn, SOCKET hSocketIn, const CAddress& addrIn, const std::string& addrNameIn, bool fInboundIn) : +CNode::CNode(NodeId idIn, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn, SOCKET hSocketIn, const CAddress& addrIn, uint64_t nKeyedNetGroupIn, const std::string& addrNameIn, bool fInboundIn) : ssSend(SER_NETWORK, INIT_PROTO_VERSION), addr(addrIn), - nKeyedNetGroup(CalculateKeyedNetGroup(addrIn)), + nKeyedNetGroup(nKeyedNetGroupIn), addrKnown(5000, 0.001), filterInventoryKnown(50000, 0.000001) { @@ -2697,12 +2696,14 @@ int64_t PoissonNextSend(int64_t nNow, int average_interval_seconds) { return nNow + (int64_t)(log1p(GetRand(1ULL << 48) * -0.0000000000000035527136788 /* -1/2^48 */) * average_interval_seconds * -1000000.0 + 0.5); } -/* static */ uint64_t CNode::CalculateKeyedNetGroup(const CAddress& ad) +CSipHasher CConnman::GetDeterministicRandomizer(uint64_t id) { - static const uint64_t k0 = GetRand(std::numeric_limits<uint64_t>::max()); - static const uint64_t k1 = GetRand(std::numeric_limits<uint64_t>::max()); + return CSipHasher(nSeed0, nSeed1).Write(id); +} +uint64_t CConnman::CalculateKeyedNetGroup(const CAddress& ad) +{ std::vector<unsigned char> vchNetGroup(ad.GetGroup()); - return CSipHasher(k0, k1).Write(&vchNetGroup[0], vchNetGroup.size()).Finalize(); + return GetDeterministicRandomizer(RANDOMIZER_ID_NETGROUP).Write(&vchNetGroup[0], vchNetGroup.size()).Finalize(); } @@ -11,6 +11,7 @@ #include "amount.h" #include "bloom.h" #include "compat.h" +#include "hash.h" #include "limitedmap.h" #include "netaddress.h" #include "protocol.h" @@ -72,6 +73,8 @@ static const size_t SETASKFOR_MAX_SZ = 2 * MAX_INV_SZ; static const unsigned int DEFAULT_MAX_PEER_CONNECTIONS = 125; /** The default for -maxuploadtarget. 0 = Unlimited */ static const uint64_t DEFAULT_MAX_UPLOAD_TARGET = 0; +/** The default timeframe for -maxuploadtarget. 1 day. */ +static const uint64_t MAX_UPLOAD_TIMEFRAME = 60 * 60 * 24; /** Default for blocks only*/ static const bool DEFAULT_BLOCKSONLY = false; @@ -120,8 +123,10 @@ public: CClientUIInterface* uiInterface = nullptr; unsigned int nSendBufferMaxSize = 0; unsigned int nReceiveFloodSize = 0; + uint64_t nMaxOutboundTimeframe = 0; + uint64_t nMaxOutboundLimit = 0; }; - CConnman(); + CConnman(uint64_t seed0, uint64_t seed1); ~CConnman(); bool Start(boost::thread_group& threadGroup, CScheduler& scheduler, std::string& strNodeError, Options options); void Stop(); @@ -294,6 +299,8 @@ public: void SetBestHeight(int height); int GetBestHeight() const; + /** Get a unique deterministic randomizer. */ + CSipHasher GetDeterministicRandomizer(uint64_t id); private: struct ListenSocket { @@ -311,6 +318,8 @@ private: void ThreadSocketHandler(); void ThreadDNSAddressSeed(); + uint64_t CalculateKeyedNetGroup(const CAddress& ad); + CNode* FindNode(const CNetAddr& ip); CNode* FindNode(const CSubNet& subNet); CNode* FindNode(const std::string& addrName); @@ -388,6 +397,9 @@ private: int nMaxFeeler; std::atomic<int> nBestHeight; CClientUIInterface* clientInterface; + + /** SipHasher seeds for deterministic randomness */ + const uint64_t nSeed0, nSeed1; }; extern std::unique_ptr<CConnman> g_connman; void Discover(boost::thread_group& threadGroup); @@ -656,16 +668,16 @@ public: CAmount lastSentFeeFilter; int64_t nextSendTimeFeeFilter; - CNode(NodeId id, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn, SOCKET hSocketIn, const CAddress &addrIn, const std::string &addrNameIn = "", bool fInboundIn = false); + CNode(NodeId id, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn, SOCKET hSocketIn, const CAddress &addrIn, uint64_t nKeyedNetGroupIn, const std::string &addrNameIn = "", bool fInboundIn = false); ~CNode(); private: CNode(const CNode&); void operator=(const CNode&); - static uint64_t CalculateKeyedNetGroup(const CAddress& ad); uint64_t nLocalHostNonce; + // Services offered to this peer ServiceFlags nLocalServices; int nMyStartingHeight; public: diff --git a/src/policy/policy.h b/src/policy/policy.h index 6bf5ca0ee5..9d6ff1233b 100644 --- a/src/policy/policy.h +++ b/src/policy/policy.h @@ -42,6 +42,8 @@ static const unsigned int STANDARD_SCRIPT_VERIFY_FLAGS = MANDATORY_SCRIPT_VERIFY SCRIPT_VERIFY_NULLDUMMY | SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS | SCRIPT_VERIFY_CLEANSTACK | + SCRIPT_VERIFY_MINIMALIF | + SCRIPT_VERIFY_NULLFAIL | SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY | SCRIPT_VERIFY_CHECKSEQUENCEVERIFY | SCRIPT_VERIFY_LOW_S | diff --git a/src/primitives/transaction.cpp b/src/primitives/transaction.cpp index 2fdc59ea07..4afbe99fd3 100644 --- a/src/primitives/transaction.cpp +++ b/src/primitives/transaction.cpp @@ -131,6 +131,11 @@ unsigned int CTransaction::CalculateModifiedSize(unsigned int nTxSize) const return nTxSize; } +unsigned int CTransaction::GetTotalSize() const +{ + return ::GetSerializeSize(*this, SER_NETWORK, PROTOCOL_VERSION); +} + std::string CTransaction::ToString() const { std::string str; diff --git a/src/primitives/transaction.h b/src/primitives/transaction.h index 5689d15bf7..16c2e5c454 100644 --- a/src/primitives/transaction.h +++ b/src/primitives/transaction.h @@ -415,6 +415,13 @@ public: // Compute modified tx size for priority calculation (optionally given tx size) unsigned int CalculateModifiedSize(unsigned int nTxSize=0) const; + + /** + * Get the total transaction size in bytes, including witness data. + * "Total Size" defined in BIP141 and BIP144. + * @return Total transaction size in bytes + */ + unsigned int GetTotalSize() const; bool IsCoinBase() const { diff --git a/src/pubkey.cpp b/src/pubkey.cpp index be4ee27cd4..91a657593a 100644 --- a/src/pubkey.cpp +++ b/src/pubkey.cpp @@ -264,12 +264,12 @@ void CExtPubKey::Decode(const unsigned char code[BIP32_EXTKEY_SIZE]) { pubkey.Set(code+41, code+BIP32_EXTKEY_SIZE); } -bool CExtPubKey::Derive(CExtPubKey &out, unsigned int nChild) const { +bool CExtPubKey::Derive(CExtPubKey &out, unsigned int _nChild) const { out.nDepth = nDepth + 1; CKeyID id = pubkey.GetID(); memcpy(&out.vchFingerprint[0], &id, 4); - out.nChild = nChild; - return pubkey.Derive(out.pubkey, out.chaincode, nChild, chaincode); + out.nChild = _nChild; + return pubkey.Derive(out.pubkey, out.chaincode, _nChild, chaincode); } /* static */ bool CPubKey::CheckLowS(const std::vector<unsigned char>& vchSig) { diff --git a/src/pubkey.h b/src/pubkey.h index aebfdbc826..3a554877f8 100644 --- a/src/pubkey.h +++ b/src/pubkey.h @@ -88,9 +88,9 @@ public: } //! Construct a public key from a byte vector. - CPubKey(const std::vector<unsigned char>& vch) + CPubKey(const std::vector<unsigned char>& _vch) { - Set(vch.begin(), vch.end()); + Set(_vch.begin(), _vch.end()); } //! Simple read-only vector-like interface to the pubkey data. diff --git a/src/qt/addressbookpage.cpp b/src/qt/addressbookpage.cpp index 135f15ffa8..58cf4dede0 100644 --- a/src/qt/addressbookpage.cpp +++ b/src/qt/addressbookpage.cpp @@ -21,12 +21,12 @@ #include <QMessageBox> #include <QSortFilterProxyModel> -AddressBookPage::AddressBookPage(const PlatformStyle *platformStyle, Mode mode, Tabs tab, QWidget *parent) : +AddressBookPage::AddressBookPage(const PlatformStyle *platformStyle, Mode _mode, Tabs _tab, QWidget *parent) : QDialog(parent), ui(new Ui::AddressBookPage), model(0), - mode(mode), - tab(tab) + mode(_mode), + tab(_tab) { ui->setupUi(this); @@ -107,14 +107,14 @@ AddressBookPage::~AddressBookPage() delete ui; } -void AddressBookPage::setModel(AddressTableModel *model) +void AddressBookPage::setModel(AddressTableModel *_model) { - this->model = model; - if(!model) + this->model = _model; + if(!_model) return; proxyModel = new QSortFilterProxyModel(this); - proxyModel->setSourceModel(model); + proxyModel->setSourceModel(_model); proxyModel->setDynamicSortFilter(true); proxyModel->setSortCaseSensitivity(Qt::CaseInsensitive); proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive); @@ -147,7 +147,7 @@ void AddressBookPage::setModel(AddressTableModel *model) this, SLOT(selectionChanged())); // Select row for newly created address - connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)), this, SLOT(selectNewAddress(QModelIndex,int,int))); + connect(_model, SIGNAL(rowsInserted(QModelIndex,int,int)), this, SLOT(selectNewAddress(QModelIndex,int,int))); selectionChanged(); } diff --git a/src/qt/addresstablemodel.cpp b/src/qt/addresstablemodel.cpp index 71ed3618e4..830c9cdf19 100644 --- a/src/qt/addresstablemodel.cpp +++ b/src/qt/addresstablemodel.cpp @@ -31,8 +31,8 @@ struct AddressTableEntry QString address; AddressTableEntry() {} - AddressTableEntry(Type type, const QString &label, const QString &address): - type(type), label(label), address(address) {} + AddressTableEntry(Type _type, const QString &_label, const QString &_address): + type(_type), label(_label), address(_address) {} }; struct AddressTableEntryLessThan @@ -73,8 +73,8 @@ public: QList<AddressTableEntry> cachedAddressTable; AddressTableModel *parent; - AddressTablePriv(CWallet *wallet, AddressTableModel *parent): - wallet(wallet), parent(parent) {} + AddressTablePriv(CWallet *_wallet, AddressTableModel *_parent): + wallet(_wallet), parent(_parent) {} void refreshAddressTable() { @@ -164,8 +164,8 @@ public: } }; -AddressTableModel::AddressTableModel(CWallet *wallet, WalletModel *parent) : - QAbstractTableModel(parent),walletModel(parent),wallet(wallet),priv(0) +AddressTableModel::AddressTableModel(CWallet *_wallet, WalletModel *parent) : + QAbstractTableModel(parent),walletModel(parent),wallet(_wallet),priv(0) { columns << tr("Label") << tr("Address"); priv = new AddressTablePriv(wallet, this); diff --git a/src/qt/askpassphrasedialog.cpp b/src/qt/askpassphrasedialog.cpp index e8aa79679c..129ea1efa4 100644 --- a/src/qt/askpassphrasedialog.cpp +++ b/src/qt/askpassphrasedialog.cpp @@ -18,10 +18,10 @@ #include <QMessageBox> #include <QPushButton> -AskPassphraseDialog::AskPassphraseDialog(Mode mode, QWidget *parent) : +AskPassphraseDialog::AskPassphraseDialog(Mode _mode, QWidget *parent) : QDialog(parent), ui(new Ui::AskPassphraseDialog), - mode(mode), + mode(_mode), model(0), fCapsLock(false) { @@ -81,9 +81,9 @@ AskPassphraseDialog::~AskPassphraseDialog() delete ui; } -void AskPassphraseDialog::setModel(WalletModel *model) +void AskPassphraseDialog::setModel(WalletModel *_model) { - this->model = model; + this->model = _model; } void AskPassphraseDialog::accept() diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index 272df3fdae..dd022ee762 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -12,6 +12,7 @@ #include "clientmodel.h" #include "guiconstants.h" #include "guiutil.h" +#include "modaloverlay.h" #include "networkstyle.h" #include "notificator.h" #include "openuridialog.h" @@ -75,8 +76,9 @@ const std::string BitcoinGUI::DEFAULT_UIPLATFORM = const QString BitcoinGUI::DEFAULT_WALLET = "~Default"; -BitcoinGUI::BitcoinGUI(const PlatformStyle *platformStyle, const NetworkStyle *networkStyle, QWidget *parent) : +BitcoinGUI::BitcoinGUI(const PlatformStyle *_platformStyle, const NetworkStyle *networkStyle, QWidget *parent) : QMainWindow(parent), + enableWallet(false), clientModel(0), walletFrame(0), unitDisplayControl(0), @@ -114,18 +116,16 @@ BitcoinGUI::BitcoinGUI(const PlatformStyle *platformStyle, const NetworkStyle *n notificator(0), rpcConsole(0), helpMessageDialog(0), + modalOverlay(0), prevBlocks(0), spinnerFrame(0), - platformStyle(platformStyle) + platformStyle(_platformStyle) { GUIUtil::restoreWindowGeometry("nWindow", QSize(850, 550), this); QString windowTitle = tr(PACKAGE_NAME) + " - "; #ifdef ENABLE_WALLET - /* if compiled with wallet support, -disablewallet can still disable the wallet */ - enableWallet = !GetBoolArg("-disablewallet", false); -#else - enableWallet = false; + enableWallet = WalletModel::isWalletEnabled(); #endif // ENABLE_WALLET if(enableWallet) { @@ -148,13 +148,13 @@ BitcoinGUI::BitcoinGUI(const PlatformStyle *platformStyle, const NetworkStyle *n setUnifiedTitleAndToolBarOnMac(true); #endif - rpcConsole = new RPCConsole(platformStyle, 0); + rpcConsole = new RPCConsole(_platformStyle, 0); helpMessageDialog = new HelpMessageDialog(this, false); #ifdef ENABLE_WALLET if(enableWallet) { /** Create wallet frame and make it the central widget */ - walletFrame = new WalletFrame(platformStyle, this); + walletFrame = new WalletFrame(_platformStyle, this); setCentralWidget(walletFrame); } else #endif // ENABLE_WALLET @@ -241,6 +241,12 @@ BitcoinGUI::BitcoinGUI(const PlatformStyle *platformStyle, const NetworkStyle *n // Subscribe to notifications from core subscribeToCoreSignals(); + + modalOverlay = new ModalOverlay(this->centralWidget()); +#ifdef ENABLE_WALLET + if(enableWallet) + connect(walletFrame, SIGNAL(requestedSyncWarningInfo()), this, SLOT(showModalOverlay())); +#endif } BitcoinGUI::~BitcoinGUI() @@ -451,38 +457,38 @@ void BitcoinGUI::createToolBars() } } -void BitcoinGUI::setClientModel(ClientModel *clientModel) +void BitcoinGUI::setClientModel(ClientModel *_clientModel) { - this->clientModel = clientModel; - if(clientModel) + this->clientModel = _clientModel; + if(_clientModel) { // Create system tray menu (or setup the dock menu) that late to prevent users from calling actions, // while the client has not yet fully loaded createTrayIconMenu(); // Keep up to date with client - setNumConnections(clientModel->getNumConnections()); - connect(clientModel, SIGNAL(numConnectionsChanged(int)), this, SLOT(setNumConnections(int))); + setNumConnections(_clientModel->getNumConnections()); + connect(_clientModel, SIGNAL(numConnectionsChanged(int)), this, SLOT(setNumConnections(int))); - setNumBlocks(clientModel->getNumBlocks(), clientModel->getLastBlockDate(), clientModel->getVerificationProgress(NULL), false); - connect(clientModel, SIGNAL(numBlocksChanged(int,QDateTime,double,bool)), this, SLOT(setNumBlocks(int,QDateTime,double,bool))); + setNumBlocks(_clientModel->getNumBlocks(), _clientModel->getLastBlockDate(), _clientModel->getVerificationProgress(NULL), false); + connect(_clientModel, SIGNAL(numBlocksChanged(int,QDateTime,double,bool)), this, SLOT(setNumBlocks(int,QDateTime,double,bool))); // Receive and report messages from client model - connect(clientModel, SIGNAL(message(QString,QString,unsigned int)), this, SLOT(message(QString,QString,unsigned int))); + connect(_clientModel, SIGNAL(message(QString,QString,unsigned int)), this, SLOT(message(QString,QString,unsigned int))); // Show progress dialog - connect(clientModel, SIGNAL(showProgress(QString,int)), this, SLOT(showProgress(QString,int))); + connect(_clientModel, SIGNAL(showProgress(QString,int)), this, SLOT(showProgress(QString,int))); - rpcConsole->setClientModel(clientModel); + rpcConsole->setClientModel(_clientModel); #ifdef ENABLE_WALLET if(walletFrame) { - walletFrame->setClientModel(clientModel); + walletFrame->setClientModel(_clientModel); } #endif // ENABLE_WALLET - unitDisplayControl->setOptionsModel(clientModel->getOptionsModel()); + unitDisplayControl->setOptionsModel(_clientModel->getOptionsModel()); - OptionsModel* optionsModel = clientModel->getOptionsModel(); + OptionsModel* optionsModel = _clientModel->getOptionsModel(); if(optionsModel) { // be aware of the tray icon disable state change reported by the OptionsModel object. @@ -491,6 +497,8 @@ void BitcoinGUI::setClientModel(ClientModel *clientModel) // initialize the disable state of the tray icon with the current value in the model. setTrayIconVisible(optionsModel->getHideTrayIcon()); } + + modalOverlay->setKnownBestHeight(clientModel->getHeaderTipHeight(), QDateTime::fromTime_t(clientModel->getHeaderTipTime())); } else { // Disable possibility to show main window via action toggleHideAction->setEnabled(false); @@ -705,7 +713,17 @@ void BitcoinGUI::setNumConnections(int count) void BitcoinGUI::setNumBlocks(int count, const QDateTime& blockDate, double nVerificationProgress, bool header) { - if(!clientModel) + if (modalOverlay) + { + if (header) { + /* use clientmodels getHeaderTipHeight and getHeaderTipTime because the NotifyHeaderTip signal does not fire when updating the best header */ + modalOverlay->setKnownBestHeight(clientModel->getHeaderTipHeight(), QDateTime::fromTime_t(clientModel->getHeaderTipTime())); + } + else { + modalOverlay->tipUpdate(count, blockDate, nVerificationProgress); + } + } + if (!clientModel) return; // Prevent orphan statusbar messages (e.g. hover Quit in main menu, wait until chain-sync starts -> garbelled text) @@ -754,7 +772,10 @@ void BitcoinGUI::setNumBlocks(int count, const QDateTime& blockDate, double nVer #ifdef ENABLE_WALLET if(walletFrame) + { walletFrame->showOutOfSyncWarning(false); + modalOverlay->showHide(true, true); + } #endif // ENABLE_WALLET progressBarLabel->setVisible(false); @@ -762,30 +783,7 @@ void BitcoinGUI::setNumBlocks(int count, const QDateTime& blockDate, double nVer } else { - // Represent time from last generated block in human readable text - QString timeBehindText; - const int HOUR_IN_SECONDS = 60*60; - const int DAY_IN_SECONDS = 24*60*60; - const int WEEK_IN_SECONDS = 7*24*60*60; - const int YEAR_IN_SECONDS = 31556952; // Average length of year in Gregorian calendar - if(secs < 2*DAY_IN_SECONDS) - { - timeBehindText = tr("%n hour(s)","",secs/HOUR_IN_SECONDS); - } - else if(secs < 2*WEEK_IN_SECONDS) - { - timeBehindText = tr("%n day(s)","",secs/DAY_IN_SECONDS); - } - else if(secs < YEAR_IN_SECONDS) - { - timeBehindText = tr("%n week(s)","",secs/WEEK_IN_SECONDS); - } - else - { - qint64 years = secs / YEAR_IN_SECONDS; - qint64 remainder = secs % YEAR_IN_SECONDS; - timeBehindText = tr("%1 and %2").arg(tr("%n year(s)", "", years)).arg(tr("%n week(s)","", remainder/WEEK_IN_SECONDS)); - } + QString timeBehindText = GUIUtil::formateNiceTimeOffset(secs); progressBarLabel->setVisible(true); progressBar->setFormat(tr("%1 behind").arg(timeBehindText)); @@ -805,7 +803,10 @@ void BitcoinGUI::setNumBlocks(int count, const QDateTime& blockDate, double nVer #ifdef ENABLE_WALLET if(walletFrame) + { walletFrame->showOutOfSyncWarning(true); + modalOverlay->showHide(); + } #endif // ENABLE_WALLET tooltip += QString("<br>"); @@ -1101,6 +1102,12 @@ void BitcoinGUI::setTrayIconVisible(bool fHideTrayIcon) } } +void BitcoinGUI::showModalOverlay() +{ + if (modalOverlay) + modalOverlay->showHide(false, true); +} + static bool ThreadSafeMessageBox(BitcoinGUI *gui, const std::string& message, const std::string& caption, unsigned int style) { bool modal = (style & CClientUIInterface::MODAL); @@ -1170,17 +1177,17 @@ void UnitDisplayStatusBarControl::createContextMenu() } /** Lets the control know about the Options Model (and its signals) */ -void UnitDisplayStatusBarControl::setOptionsModel(OptionsModel *optionsModel) +void UnitDisplayStatusBarControl::setOptionsModel(OptionsModel *_optionsModel) { - if (optionsModel) + if (_optionsModel) { - this->optionsModel = optionsModel; + this->optionsModel = _optionsModel; // be aware of a display unit change reported by the OptionsModel object. - connect(optionsModel,SIGNAL(displayUnitChanged(int)),this,SLOT(updateDisplayUnit(int))); + connect(_optionsModel,SIGNAL(displayUnitChanged(int)),this,SLOT(updateDisplayUnit(int))); // initialize the display units label with the current value in the model. - updateDisplayUnit(optionsModel->getDisplayUnit()); + updateDisplayUnit(_optionsModel->getDisplayUnit()); } } diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h index 41770929b4..0eaa44b263 100644 --- a/src/qt/bitcoingui.h +++ b/src/qt/bitcoingui.h @@ -29,6 +29,7 @@ class UnitDisplayStatusBarControl; class WalletFrame; class WalletModel; class HelpMessageDialog; +class ModalOverlay; class CWallet; @@ -118,6 +119,7 @@ private: Notificator *notificator; RPCConsole *rpcConsole; HelpMessageDialog *helpMessageDialog; + ModalOverlay *modalOverlay; /** Keep track of previous number of blocks, to detect progress */ int prevBlocks; @@ -229,6 +231,8 @@ private Q_SLOTS: /** When hideTrayIcon setting is changed in OptionsModel hide or show the icon accordingly. */ void setTrayIconVisible(bool); + + void showModalOverlay(); }; class UnitDisplayStatusBarControl : public QLabel diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index 83c78850e2..6d19b3d122 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -27,9 +27,9 @@ static const int64_t nClientStartupTime = GetTime(); static int64_t nLastHeaderTipUpdateNotification = 0; static int64_t nLastBlockTipUpdateNotification = 0; -ClientModel::ClientModel(OptionsModel *optionsModel, QObject *parent) : +ClientModel::ClientModel(OptionsModel *_optionsModel, QObject *parent) : QObject(parent), - optionsModel(optionsModel), + optionsModel(_optionsModel), peerTableModel(0), banTableModel(0), pollTimer(0) @@ -70,6 +70,22 @@ int ClientModel::getNumBlocks() const return chainActive.Height(); } +int ClientModel::getHeaderTipHeight() const +{ + LOCK(cs_main); + if (!pindexBestHeader) + return 0; + return pindexBestHeader->nHeight; +} + +int64_t ClientModel::getHeaderTipTime() const +{ + LOCK(cs_main); + if (!pindexBestHeader) + return 0; + return pindexBestHeader->GetBlockTime(); +} + quint64 ClientModel::getTotalBytesRecv() const { if(!g_connman) @@ -240,7 +256,7 @@ static void BlockTipChanged(ClientModel *clientmodel, bool initialSync, const CB int64_t& nLastUpdateNotification = fHeader ? nLastHeaderTipUpdateNotification : nLastBlockTipUpdateNotification; // if we are in-sync, update the UI regardless of last update time - if (!initialSync || now - nLastUpdateNotification > MODEL_UPDATE_DELAY) { + if (fHeader || !initialSync || now - nLastUpdateNotification > MODEL_UPDATE_DELAY) { //pass a async signal to the UI thread QMetaObject::invokeMethod(clientmodel, "numBlocksChanged", Qt::QueuedConnection, Q_ARG(int, pIndex->nHeight), diff --git a/src/qt/clientmodel.h b/src/qt/clientmodel.h index 99fd574b9e..3fd8404cbb 100644 --- a/src/qt/clientmodel.h +++ b/src/qt/clientmodel.h @@ -51,7 +51,8 @@ public: //! Return number of connections, default is in- and outbound (total) int getNumConnections(unsigned int flags = CONNECTIONS_ALL) const; int getNumBlocks() const; - + int getHeaderTipHeight() const; + int64_t getHeaderTipTime() const; //! Return number of transactions in the mempool long getMempoolSize() const; //! Return the dynamic memory usage of the mempool diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp index f53242100c..86fd4ebd65 100644 --- a/src/qt/coincontroldialog.cpp +++ b/src/qt/coincontroldialog.cpp @@ -35,11 +35,11 @@ QList<CAmount> CoinControlDialog::payAmounts; CCoinControl* CoinControlDialog::coinControl = new CCoinControl(); bool CoinControlDialog::fSubtractFeeFromAmount = false; -CoinControlDialog::CoinControlDialog(const PlatformStyle *platformStyle, QWidget *parent) : +CoinControlDialog::CoinControlDialog(const PlatformStyle *_platformStyle, QWidget *parent) : QDialog(parent), ui(new Ui::CoinControlDialog), model(0), - platformStyle(platformStyle) + platformStyle(_platformStyle) { ui->setupUi(this); @@ -152,15 +152,15 @@ CoinControlDialog::~CoinControlDialog() delete ui; } -void CoinControlDialog::setModel(WalletModel *model) +void CoinControlDialog::setModel(WalletModel *_model) { - this->model = model; + this->model = _model; - if(model && model->getOptionsModel() && model->getAddressTableModel()) + if(_model && _model->getOptionsModel() && _model->getAddressTableModel()) { updateView(); updateLabelLocked(); - CoinControlDialog::updateLabels(model, this); + CoinControlDialog::updateLabels(_model, this); } } diff --git a/src/qt/csvmodelwriter.cpp b/src/qt/csvmodelwriter.cpp index 8a1a49bb06..f424e6cd98 100644 --- a/src/qt/csvmodelwriter.cpp +++ b/src/qt/csvmodelwriter.cpp @@ -8,15 +8,15 @@ #include <QFile> #include <QTextStream> -CSVModelWriter::CSVModelWriter(const QString &filename, QObject *parent) : +CSVModelWriter::CSVModelWriter(const QString &_filename, QObject *parent) : QObject(parent), - filename(filename), model(0) + filename(_filename), model(0) { } -void CSVModelWriter::setModel(const QAbstractItemModel *model) +void CSVModelWriter::setModel(const QAbstractItemModel *_model) { - this->model = model; + this->model = _model; } void CSVModelWriter::addColumn(const QString &title, int column, int role) diff --git a/src/qt/editaddressdialog.cpp b/src/qt/editaddressdialog.cpp index 5f45031e9e..a9ffe016fd 100644 --- a/src/qt/editaddressdialog.cpp +++ b/src/qt/editaddressdialog.cpp @@ -11,11 +11,11 @@ #include <QDataWidgetMapper> #include <QMessageBox> -EditAddressDialog::EditAddressDialog(Mode mode, QWidget *parent) : +EditAddressDialog::EditAddressDialog(Mode _mode, QWidget *parent) : QDialog(parent), ui(new Ui::EditAddressDialog), mapper(0), - mode(mode), + mode(_mode), model(0) { ui->setupUi(this); @@ -49,13 +49,13 @@ EditAddressDialog::~EditAddressDialog() delete ui; } -void EditAddressDialog::setModel(AddressTableModel *model) +void EditAddressDialog::setModel(AddressTableModel *_model) { - this->model = model; - if(!model) + this->model = _model; + if(!_model) return; - mapper->setModel(model); + mapper->setModel(_model); mapper->addMapping(ui->labelEdit, AddressTableModel::Label); mapper->addMapping(ui->addressEdit, AddressTableModel::Address); } @@ -137,8 +137,8 @@ QString EditAddressDialog::getAddress() const return address; } -void EditAddressDialog::setAddress(const QString &address) +void EditAddressDialog::setAddress(const QString &_address) { - this->address = address; - ui->addressEdit->setText(address); + this->address = _address; + ui->addressEdit->setText(_address); } diff --git a/src/qt/forms/modaloverlay.ui b/src/qt/forms/modaloverlay.ui new file mode 100644 index 0000000000..b16ecafbe4 --- /dev/null +++ b/src/qt/forms/modaloverlay.ui @@ -0,0 +1,373 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>ModalOverlay</class> + <widget class="ModalOverlay" name="ModalOverlay"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>640</width> + <height>385</height> + </rect> + </property> + <property name="windowTitle"> + <string>Form</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout" stretch="0"> + <property name="sizeConstraint"> + <enum>QLayout::SetDefaultConstraint</enum> + </property> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <widget class="QWidget" name="bgWidget" native="true"> + <property name="styleSheet"> + <string notr="true">#bgWidget { background: rgba(0,0,0,220); }</string> + </property> + <layout class="QVBoxLayout" name="verticalLayoutMain" stretch="1"> + <property name="leftMargin"> + <number>60</number> + </property> + <property name="topMargin"> + <number>60</number> + </property> + <property name="rightMargin"> + <number>60</number> + </property> + <property name="bottomMargin"> + <number>60</number> + </property> + <item> + <widget class="QWidget" name="contentWidget" native="true"> + <property name="styleSheet"> + <string notr="true">#contentWidget { background: rgba(255,255,255,240); border-radius: 6px; } + +QLabel { color: rgb(40,40,40); }</string> + </property> + <layout class="QVBoxLayout" name="verticalLayoutSub" stretch="1,0,0,0"> + <property name="spacing"> + <number>0</number> + </property> + <property name="leftMargin"> + <number>10</number> + </property> + <property name="topMargin"> + <number>10</number> + </property> + <property name="rightMargin"> + <number>10</number> + </property> + <property name="bottomMargin"> + <number>10</number> + </property> + <item> + <layout class="QHBoxLayout" name="horizontalLayoutIconText" stretch="0,1"> + <property name="topMargin"> + <number>20</number> + </property> + <item> + <layout class="QVBoxLayout" name="verticalLayoutIcon"> + <property name="leftMargin"> + <number>0</number> + </property> + <item> + <widget class="QPushButton" name="warningIcon"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string/> + </property> + <property name="icon"> + <iconset> + <normaloff>:/icons/warning</normaloff> + <disabledoff>:/icons/warning</disabledoff>:/icons/warning</iconset> + </property> + <property name="iconSize"> + <size> + <width>48</width> + <height>48</height> + </size> + </property> + <property name="flat"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <spacer name="verticalSpacerWarningIcon"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <layout class="QVBoxLayout" name="verticalLayoutInfoText"> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <item> + <widget class="QLabel" name="infoText"> + <property name="text"> + <string>The displayed information may be out of date. Your wallet automatically synchronizes with the Bitcoin network after a connection is established, but this process has not completed yet. This means that recent transactions will not be visible, and the balance will not be up-to-date until this process has completed.</string> + </property> + <property name="textFormat"> + <enum>Qt::RichText</enum> + </property> + <property name="wordWrap"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="infoTextStrong"> + <property name="font"> + <font> + <weight>75</weight> + <bold>true</bold> + </font> + </property> + <property name="text"> + <string>Spending bitcoins may not be possible during that phase!</string> + </property> + <property name="textFormat"> + <enum>Qt::RichText</enum> + </property> + <property name="wordWrap"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <spacer name="verticalSpacerInTextSpace"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + </layout> + </item> + <item> + <spacer name="verticalSpacerAfterText"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + <item> + <layout class="QFormLayout" name="formLayout"> + <property name="fieldGrowthPolicy"> + <enum>QFormLayout::FieldsStayAtSizeHint</enum> + </property> + <property name="horizontalSpacing"> + <number>6</number> + </property> + <property name="verticalSpacing"> + <number>6</number> + </property> + <property name="topMargin"> + <number>10</number> + </property> + <item row="0" column="0"> + <widget class="QLabel" name="labelNumberOfBlocksLeft"> + <property name="font"> + <font> + <weight>75</weight> + <bold>true</bold> + </font> + </property> + <property name="text"> + <string>Number of blocks left</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QLabel" name="numberOfBlocksLeft"> + <property name="text"> + <string>unknown...</string> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="labelLastBlockTime"> + <property name="font"> + <font> + <weight>75</weight> + <bold>true</bold> + </font> + </property> + <property name="text"> + <string>Last block time</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QLabel" name="newestBlockDate"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Maximum" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>unknown...</string> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="labelSyncDone"> + <property name="font"> + <font> + <weight>75</weight> + <bold>true</bold> + </font> + </property> + <property name="text"> + <string>Progress</string> + </property> + </widget> + </item> + <item row="2" column="1"> + <layout class="QHBoxLayout" name="horizontalLayoutSync" stretch="0,1"> + <item> + <widget class="QLabel" name="percentageProgress"> + <property name="text"> + <string>~</string> + </property> + </widget> + </item> + <item> + <widget class="QProgressBar" name="progressBar"> + <property name="value"> + <number>24</number> + </property> + </widget> + </item> + </layout> + </item> + <item row="4" column="0"> + <widget class="QLabel" name="labelProgressIncrease"> + <property name="font"> + <font> + <weight>75</weight> + <bold>true</bold> + </font> + </property> + <property name="text"> + <string>Progress increase per hour</string> + </property> + </widget> + </item> + <item row="4" column="1"> + <widget class="QLabel" name="progressIncreasePerH"> + <property name="text"> + <string>calculating...</string> + </property> + </widget> + </item> + <item row="5" column="0"> + <widget class="QLabel" name="labelEstimatedTimeLeft"> + <property name="font"> + <font> + <weight>75</weight> + <bold>true</bold> + </font> + </property> + <property name="text"> + <string>Estimated time left until synced</string> + </property> + </widget> + </item> + <item row="5" column="1"> + <widget class="QLabel" name="expectedTimeLeft"> + <property name="text"> + <string>calculating...</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayoutButtons"> + <property name="leftMargin"> + <number>10</number> + </property> + <property name="topMargin"> + <number>10</number> + </property> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="closeButton"> + <property name="text"> + <string>Hide</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + </item> + </layout> + </widget> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>ModalOverlay</class> + <extends>QWidget</extends> + <header>modaloverlay.h</header> + <container>1</container> + </customwidget> + </customwidgets> + <resources/> + <connections/> +</ui> diff --git a/src/qt/forms/overviewpage.ui b/src/qt/forms/overviewpage.ui index 6d792d1475..923ed68996 100644 --- a/src/qt/forms/overviewpage.ui +++ b/src/qt/forms/overviewpage.ui @@ -61,7 +61,7 @@ <item> <widget class="QPushButton" name="labelWalletStatus"> <property name="enabled"> - <bool>false</bool> + <bool>true</bool> </property> <property name="maximumSize"> <size> @@ -447,7 +447,7 @@ <item> <widget class="QPushButton" name="labelTransactionsStatus"> <property name="enabled"> - <bool>false</bool> + <bool>true</bool> </property> <property name="maximumSize"> <size> diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp index 444e35de8a..0beaddf997 100644 --- a/src/qt/guiutil.cpp +++ b/src/qt/guiutil.cpp @@ -462,9 +462,9 @@ void SubstituteFonts(const QString& language) #endif } -ToolTipToRichTextFilter::ToolTipToRichTextFilter(int size_threshold, QObject *parent) : +ToolTipToRichTextFilter::ToolTipToRichTextFilter(int _size_threshold, QObject *parent) : QObject(parent), - size_threshold(size_threshold) + size_threshold(_size_threshold) { } @@ -955,4 +955,40 @@ QString formatTimeOffset(int64_t nTimeOffset) return QString(QObject::tr("%1 s")).arg(QString::number((int)nTimeOffset, 10)); } +QString formateNiceTimeOffset(qint64 secs) +{ + // Represent time from last generated block in human readable text + QString timeBehindText; + const int HOUR_IN_SECONDS = 60*60; + const int DAY_IN_SECONDS = 24*60*60; + const int WEEK_IN_SECONDS = 7*24*60*60; + const int YEAR_IN_SECONDS = 31556952; // Average length of year in Gregorian calendar + if(secs < 60) + { + timeBehindText = QObject::tr("%n seconds(s)","",secs); + } + else if(secs < 2*HOUR_IN_SECONDS) + { + timeBehindText = QObject::tr("%n minutes(s)","",secs/60); + } + else if(secs < 2*DAY_IN_SECONDS) + { + timeBehindText = QObject::tr("%n hour(s)","",secs/HOUR_IN_SECONDS); + } + else if(secs < 2*WEEK_IN_SECONDS) + { + timeBehindText = QObject::tr("%n day(s)","",secs/DAY_IN_SECONDS); + } + else if(secs < YEAR_IN_SECONDS) + { + timeBehindText = QObject::tr("%n week(s)","",secs/WEEK_IN_SECONDS); + } + else + { + qint64 years = secs / YEAR_IN_SECONDS; + qint64 remainder = secs % YEAR_IN_SECONDS; + timeBehindText = QObject::tr("%1 and %2").arg(QObject::tr("%n year(s)", "", years)).arg(QObject::tr("%n week(s)","", remainder/WEEK_IN_SECONDS)); + } + return timeBehindText; +} } // namespace GUIUtil diff --git a/src/qt/guiutil.h b/src/qt/guiutil.h index d5a658e7c0..e28f68930f 100644 --- a/src/qt/guiutil.h +++ b/src/qt/guiutil.h @@ -200,6 +200,8 @@ namespace GUIUtil /* Format a CNodeCombinedStats.nTimeOffset into a user-readable string. */ QString formatTimeOffset(int64_t nTimeOffset); + QString formateNiceTimeOffset(qint64 secs); + #if defined(Q_OS_MAC) && QT_VERSION >= 0x050000 // workaround for Qt OSX Bug: // https://bugreports.qt-project.org/browse/QTBUG-15631 diff --git a/src/qt/intro.cpp b/src/qt/intro.cpp index 1a241ae0f0..5a336b105e 100644 --- a/src/qt/intro.cpp +++ b/src/qt/intro.cpp @@ -63,9 +63,9 @@ private: #include "intro.moc" -FreespaceChecker::FreespaceChecker(Intro *intro) +FreespaceChecker::FreespaceChecker(Intro *_intro) { - this->intro = intro; + this->intro = _intro; } void FreespaceChecker::check() diff --git a/src/qt/modaloverlay.cpp b/src/qt/modaloverlay.cpp new file mode 100644 index 0000000000..2de2dde16a --- /dev/null +++ b/src/qt/modaloverlay.cpp @@ -0,0 +1,158 @@ +// Copyright (c) 2016 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 "modaloverlay.h" +#include "ui_modaloverlay.h" + +#include "guiutil.h" + +#include <QResizeEvent> +#include <QPropertyAnimation> + +ModalOverlay::ModalOverlay(QWidget *parent) : +QWidget(parent), +ui(new Ui::ModalOverlay), +bestBlockHeight(0), +layerIsVisible(false), +userClosed(false) +{ + ui->setupUi(this); + connect(ui->closeButton, SIGNAL(clicked()), this, SLOT(closeClicked())); + if (parent) { + parent->installEventFilter(this); + raise(); + } + + blockProcessTime.clear(); + setVisible(false); +} + +ModalOverlay::~ModalOverlay() +{ + delete ui; +} + +bool ModalOverlay::eventFilter(QObject * obj, QEvent * ev) { + if (obj == parent()) { + if (ev->type() == QEvent::Resize) { + QResizeEvent * rev = static_cast<QResizeEvent*>(ev); + resize(rev->size()); + if (!layerIsVisible) + setGeometry(0, height(), width(), height()); + + } + else if (ev->type() == QEvent::ChildAdded) { + raise(); + } + } + return QWidget::eventFilter(obj, ev); +} + +//! Tracks parent widget changes +bool ModalOverlay::event(QEvent* ev) { + if (ev->type() == QEvent::ParentAboutToChange) { + if (parent()) parent()->removeEventFilter(this); + } + else if (ev->type() == QEvent::ParentChange) { + if (parent()) { + parent()->installEventFilter(this); + raise(); + } + } + return QWidget::event(ev); +} + +void ModalOverlay::setKnownBestHeight(int count, const QDateTime& blockDate) +{ + + /* only update the blockheight if the headerschain-tip is not older then 30 days */ + int64_t now = QDateTime::currentDateTime().toTime_t(); + int64_t btime = blockDate.toTime_t(); + if (btime+3600*24*30 > now) + { + if (count > bestBlockHeight) + bestBlockHeight = count; + } +} + +void ModalOverlay::tipUpdate(int count, const QDateTime& blockDate, double nVerificationProgress) +{ + QDateTime currentDate = QDateTime::currentDateTime(); + + // keep a vector of samples of verification progress at height + blockProcessTime.push_front(qMakePair(currentDate.currentMSecsSinceEpoch(), nVerificationProgress)); + + // show progress speed if we have more then one sample + if (blockProcessTime.size() >= 2) + { + double progressStart = blockProcessTime[0].second; + double progressDelta = 0; + double progressPerHour = 0; + qint64 timeDelta = 0; + qint64 remainingMSecs = 0; + double remainingProgress = 1.0 - nVerificationProgress; + for (int i = 1; i < blockProcessTime.size(); i++) + { + QPair<qint64, double> sample = blockProcessTime[i]; + + // take first sample after 500 seconds or last available one + if (sample.first < (currentDate.currentMSecsSinceEpoch() - 500*1000) || i == blockProcessTime.size()-1) + { + progressDelta = progressStart-sample.second; + timeDelta = blockProcessTime[0].first - sample.first; + progressPerHour = progressDelta/(double)timeDelta*1000*3600; + remainingMSecs = remainingProgress / progressDelta * timeDelta; + break; + } + } + // show progress increase per hour + ui->progressIncreasePerH->setText(QString::number(progressPerHour*100, 'f', 2)+"%"); + + // show expected remaining time + ui->expectedTimeLeft->setText(GUIUtil::formateNiceTimeOffset(remainingMSecs/1000.0)); + + // keep maximal 5000 samples + static const int MAX_SAMPLES = 5000; + if (blockProcessTime.count() > MAX_SAMPLES) + blockProcessTime.remove(MAX_SAMPLES, blockProcessTime.count()-MAX_SAMPLES); + } + + // show the last block date + ui->newestBlockDate->setText(blockDate.toString()); + + // show the percentage done according to nVerificationProgress + ui->percentageProgress->setText(QString::number(nVerificationProgress*100, 'f', 2)+"%"); + ui->progressBar->setValue(nVerificationProgress*100); + + // show remaining number of blocks + if (bestBlockHeight > 0) + ui->numberOfBlocksLeft->setText(QString::number(bestBlockHeight-count)); + else + ui->expectedTimeLeft->setText(tr("Unknown. Syncing Headers...")); +} + +void ModalOverlay::showHide(bool hide, bool userRequested) +{ + if ( (layerIsVisible && !hide) || (!layerIsVisible && hide) || (!hide && userClosed && !userRequested)) + return; + + if (!isVisible() && !hide) + setVisible(true); + + setGeometry(0, hide ? 0 : height(), width(), height()); + + QPropertyAnimation* animation = new QPropertyAnimation(this, "pos"); + animation->setDuration(300); + animation->setStartValue(QPoint(0, hide ? 0 : this->height())); + animation->setEndValue(QPoint(0, hide ? this->height() : 0)); + animation->setEasingCurve(QEasingCurve::OutQuad); + animation->start(QAbstractAnimation::DeleteWhenStopped); + layerIsVisible = !hide; +} + +void ModalOverlay::closeClicked() +{ + showHide(true); + userClosed = true; +} diff --git a/src/qt/modaloverlay.h b/src/qt/modaloverlay.h new file mode 100644 index 0000000000..670c9e58ab --- /dev/null +++ b/src/qt/modaloverlay.h @@ -0,0 +1,44 @@ +// Copyright (c) 2016 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_QT_MODALOVERLAY_H +#define BITCOIN_QT_MODALOVERLAY_H + +#include <QDateTime> +#include <QWidget> + +namespace Ui { + class ModalOverlay; +} + +/** Modal overlay to display information about the chain-sync state */ +class ModalOverlay : public QWidget +{ + Q_OBJECT + +public: + explicit ModalOverlay(QWidget *parent); + ~ModalOverlay(); + +public Q_SLOTS: + void tipUpdate(int count, const QDateTime& blockDate, double nVerificationProgress); + void setKnownBestHeight(int count, const QDateTime& blockDate); + + // will show or hide the modal layer + void showHide(bool hide = false, bool userRequested = false); + void closeClicked(); + +protected: + bool eventFilter(QObject * obj, QEvent * ev); + bool event(QEvent* ev); + +private: + Ui::ModalOverlay *ui; + int bestBlockHeight; //best known height (based on the headers) + QVector<QPair<qint64, double> > blockProcessTime; + bool layerIsVisible; + bool userClosed; +}; + +#endif // BITCOIN_QT_MODALOVERLAY_H diff --git a/src/qt/networkstyle.cpp b/src/qt/networkstyle.cpp index 5f31f49372..acbfee0868 100644 --- a/src/qt/networkstyle.cpp +++ b/src/qt/networkstyle.cpp @@ -22,9 +22,9 @@ static const struct { static const unsigned network_styles_count = sizeof(network_styles)/sizeof(*network_styles); // titleAddText needs to be const char* for tr() -NetworkStyle::NetworkStyle(const QString &appName, const int iconColorHueShift, const int iconColorSaturationReduction, const char *titleAddText): - appName(appName), - titleAddText(qApp->translate("SplashScreen", titleAddText)) +NetworkStyle::NetworkStyle(const QString &_appName, const int iconColorHueShift, const int iconColorSaturationReduction, const char *_titleAddText): + appName(_appName), + titleAddText(qApp->translate("SplashScreen", _titleAddText)) { // load pixmap QPixmap pixmap(":/icons/bitcoin"); diff --git a/src/qt/notificator.cpp b/src/qt/notificator.cpp index a45afde566..8277e20c90 100644 --- a/src/qt/notificator.cpp +++ b/src/qt/notificator.cpp @@ -33,17 +33,17 @@ const int FREEDESKTOP_NOTIFICATION_ICON_SIZE = 128; #endif -Notificator::Notificator(const QString &programName, QSystemTrayIcon *trayicon, QWidget *parent) : - QObject(parent), - parent(parent), - programName(programName), +Notificator::Notificator(const QString &_programName, QSystemTrayIcon *_trayIcon, QWidget *_parent) : + QObject(_parent), + parent(_parent), + programName(_programName), mode(None), - trayIcon(trayicon) + trayIcon(_trayIcon) #ifdef USE_DBUS ,interface(0) #endif { - if(trayicon && trayicon->supportsMessages()) + if(_trayIcon && _trayIcon->supportsMessages()) { mode = QSystemTray; } diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp index f73bb87064..588059d0c5 100644 --- a/src/qt/optionsdialog.cpp +++ b/src/qt/optionsdialog.cpp @@ -135,22 +135,22 @@ OptionsDialog::~OptionsDialog() delete ui; } -void OptionsDialog::setModel(OptionsModel *model) +void OptionsDialog::setModel(OptionsModel *_model) { - this->model = model; + this->model = _model; - if(model) + if(_model) { /* check if client restart is needed and show persistent message */ - if (model->isRestartRequired()) + if (_model->isRestartRequired()) showRestartWarning(true); - QString strLabel = model->getOverriddenByCommandLine(); + QString strLabel = _model->getOverriddenByCommandLine(); if (strLabel.isEmpty()) strLabel = tr("none"); ui->overriddenByCommandLineLabel->setText(strLabel); - mapper->setModel(model); + mapper->setModel(_model); setMapper(); mapper->toFirst(); diff --git a/src/qt/overviewpage.cpp b/src/qt/overviewpage.cpp index 6a0404cbf7..7ccdb89c0c 100644 --- a/src/qt/overviewpage.cpp +++ b/src/qt/overviewpage.cpp @@ -25,9 +25,9 @@ class TxViewDelegate : public QAbstractItemDelegate { Q_OBJECT public: - TxViewDelegate(const PlatformStyle *platformStyle): + TxViewDelegate(const PlatformStyle *_platformStyle): QAbstractItemDelegate(), unit(BitcoinUnits::BTC), - platformStyle(platformStyle) + platformStyle(_platformStyle) { } @@ -140,6 +140,8 @@ OverviewPage::OverviewPage(const PlatformStyle *platformStyle, QWidget *parent) // start with displaying the "out of sync" warnings showOutOfSyncWarning(true); + connect(ui->labelWalletStatus, SIGNAL(clicked()), this, SLOT(handleOutOfSyncWarningClicks())); + connect(ui->labelTransactionsStatus, SIGNAL(clicked()), this, SLOT(handleOutOfSyncWarningClicks())); } void OverviewPage::handleTransactionClicked(const QModelIndex &index) @@ -148,6 +150,11 @@ void OverviewPage::handleTransactionClicked(const QModelIndex &index) Q_EMIT transactionClicked(filter->mapToSource(index)); } +void OverviewPage::handleOutOfSyncWarningClicks() +{ + Q_EMIT outOfSyncWarningClicked(); +} + OverviewPage::~OverviewPage() { delete ui; diff --git a/src/qt/overviewpage.h b/src/qt/overviewpage.h index 911443c76a..65cd3341b6 100644 --- a/src/qt/overviewpage.h +++ b/src/qt/overviewpage.h @@ -42,6 +42,7 @@ public Q_SLOTS: Q_SIGNALS: void transactionClicked(const QModelIndex &index); + void outOfSyncWarningClicked(); private: Ui::OverviewPage *ui; @@ -62,6 +63,7 @@ private Q_SLOTS: void handleTransactionClicked(const QModelIndex &index); void updateAlerts(const QString &warnings); void updateWatchOnlyLabels(bool showWatchOnly); + void handleOutOfSyncWarningClicks(); }; #endif // BITCOIN_QT_OVERVIEWPAGE_H diff --git a/src/qt/paymentrequest.proto b/src/qt/paymentrequest.proto index b2281c4c7b..d2721a34bd 100644 --- a/src/qt/paymentrequest.proto +++ b/src/qt/paymentrequest.proto @@ -6,6 +6,8 @@ // https://en.bitcoin.it/wiki/Payment_Request // +syntax = "proto2"; + package payments; option java_package = "org.bitcoin.protocols.payments"; option java_outer_classname = "Protos"; diff --git a/src/qt/paymentserver.cpp b/src/qt/paymentserver.cpp index c80aebb009..9f23e77a13 100644 --- a/src/qt/paymentserver.cpp +++ b/src/qt/paymentserver.cpp @@ -749,9 +749,9 @@ void PaymentServer::reportSslErrors(QNetworkReply* reply, const QList<QSslError> Q_EMIT message(tr("Network request error"), errString, CClientUIInterface::MSG_ERROR); } -void PaymentServer::setOptionsModel(OptionsModel *optionsModel) +void PaymentServer::setOptionsModel(OptionsModel *_optionsModel) { - this->optionsModel = optionsModel; + this->optionsModel = _optionsModel; } void PaymentServer::handlePaymentACK(const QString& paymentACKMsg) diff --git a/src/qt/platformstyle.cpp b/src/qt/platformstyle.cpp index 11cbc7a47c..e4438cc43d 100644 --- a/src/qt/platformstyle.cpp +++ b/src/qt/platformstyle.cpp @@ -73,11 +73,11 @@ QIcon ColorizeIcon(const QString& filename, const QColor& colorbase) } -PlatformStyle::PlatformStyle(const QString &name, bool imagesOnButtons, bool colorizeIcons, bool useExtraSpacing): - name(name), - imagesOnButtons(imagesOnButtons), - colorizeIcons(colorizeIcons), - useExtraSpacing(useExtraSpacing), +PlatformStyle::PlatformStyle(const QString &_name, bool _imagesOnButtons, bool _colorizeIcons, bool _useExtraSpacing): + name(_name), + imagesOnButtons(_imagesOnButtons), + colorizeIcons(_colorizeIcons), + useExtraSpacing(_useExtraSpacing), singleColor(0,0,0), textColor(0,0,0) { diff --git a/src/qt/qvalidatedlineedit.cpp b/src/qt/qvalidatedlineedit.cpp index baa2eb67f7..492b96ff09 100644 --- a/src/qt/qvalidatedlineedit.cpp +++ b/src/qt/qvalidatedlineedit.cpp @@ -15,14 +15,14 @@ QValidatedLineEdit::QValidatedLineEdit(QWidget *parent) : connect(this, SIGNAL(textChanged(QString)), this, SLOT(markValid())); } -void QValidatedLineEdit::setValid(bool valid) +void QValidatedLineEdit::setValid(bool _valid) { - if(valid == this->valid) + if(_valid == this->valid) { return; } - if(valid) + if(_valid) { setStyleSheet(""); } @@ -30,7 +30,7 @@ void QValidatedLineEdit::setValid(bool valid) { setStyleSheet(STYLE_INVALID); } - this->valid = valid; + this->valid = _valid; } void QValidatedLineEdit::focusInEvent(QFocusEvent *evt) diff --git a/src/qt/qvaluecombobox.cpp b/src/qt/qvaluecombobox.cpp index 146f3dd578..2f2478783c 100644 --- a/src/qt/qvaluecombobox.cpp +++ b/src/qt/qvaluecombobox.cpp @@ -20,9 +20,9 @@ void QValueComboBox::setValue(const QVariant &value) setCurrentIndex(findData(value, role)); } -void QValueComboBox::setRole(int role) +void QValueComboBox::setRole(int _role) { - this->role = role; + this->role = _role; } void QValueComboBox::handleSelectionChanged(int idx) diff --git a/src/qt/receivecoinsdialog.cpp b/src/qt/receivecoinsdialog.cpp index 0b355837ab..5c6dc97b20 100644 --- a/src/qt/receivecoinsdialog.cpp +++ b/src/qt/receivecoinsdialog.cpp @@ -22,24 +22,24 @@ #include <QScrollBar> #include <QTextDocument> -ReceiveCoinsDialog::ReceiveCoinsDialog(const PlatformStyle *platformStyle, QWidget *parent) : +ReceiveCoinsDialog::ReceiveCoinsDialog(const PlatformStyle *_platformStyle, QWidget *parent) : QDialog(parent), ui(new Ui::ReceiveCoinsDialog), model(0), - platformStyle(platformStyle) + platformStyle(_platformStyle) { ui->setupUi(this); - if (!platformStyle->getImagesOnButtons()) { + if (!_platformStyle->getImagesOnButtons()) { ui->clearButton->setIcon(QIcon()); ui->receiveButton->setIcon(QIcon()); ui->showRequestButton->setIcon(QIcon()); ui->removeRequestButton->setIcon(QIcon()); } else { - ui->clearButton->setIcon(platformStyle->SingleColorIcon(":/icons/remove")); - ui->receiveButton->setIcon(platformStyle->SingleColorIcon(":/icons/receiving_addresses")); - ui->showRequestButton->setIcon(platformStyle->SingleColorIcon(":/icons/edit")); - ui->removeRequestButton->setIcon(platformStyle->SingleColorIcon(":/icons/remove")); + ui->clearButton->setIcon(_platformStyle->SingleColorIcon(":/icons/remove")); + ui->receiveButton->setIcon(_platformStyle->SingleColorIcon(":/icons/receiving_addresses")); + ui->showRequestButton->setIcon(_platformStyle->SingleColorIcon(":/icons/edit")); + ui->removeRequestButton->setIcon(_platformStyle->SingleColorIcon(":/icons/remove")); } // context menu actions @@ -62,21 +62,21 @@ ReceiveCoinsDialog::ReceiveCoinsDialog(const PlatformStyle *platformStyle, QWidg connect(ui->clearButton, SIGNAL(clicked()), this, SLOT(clear())); } -void ReceiveCoinsDialog::setModel(WalletModel *model) +void ReceiveCoinsDialog::setModel(WalletModel *_model) { - this->model = model; + this->model = _model; - if(model && model->getOptionsModel()) + if(_model && _model->getOptionsModel()) { - model->getRecentRequestsTableModel()->sort(RecentRequestsTableModel::Date, Qt::DescendingOrder); - connect(model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit())); + _model->getRecentRequestsTableModel()->sort(RecentRequestsTableModel::Date, Qt::DescendingOrder); + connect(_model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit())); updateDisplayUnit(); QTableView* tableView = ui->recentRequestsView; tableView->verticalHeader()->hide(); tableView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - tableView->setModel(model->getRecentRequestsTableModel()); + tableView->setModel(_model->getRecentRequestsTableModel()); tableView->setAlternatingRowColors(true); tableView->setSelectionBehavior(QAbstractItemView::SelectRows); tableView->setSelectionMode(QAbstractItemView::ContiguousSelection); diff --git a/src/qt/receiverequestdialog.cpp b/src/qt/receiverequestdialog.cpp index b13ea3df70..998c9176d7 100644 --- a/src/qt/receiverequestdialog.cpp +++ b/src/qt/receiverequestdialog.cpp @@ -109,20 +109,20 @@ ReceiveRequestDialog::~ReceiveRequestDialog() delete ui; } -void ReceiveRequestDialog::setModel(OptionsModel *model) +void ReceiveRequestDialog::setModel(OptionsModel *_model) { - this->model = model; + this->model = _model; - if (model) - connect(model, SIGNAL(displayUnitChanged(int)), this, SLOT(update())); + if (_model) + connect(_model, SIGNAL(displayUnitChanged(int)), this, SLOT(update())); // update the display unit if necessary update(); } -void ReceiveRequestDialog::setInfo(const SendCoinsRecipient &info) +void ReceiveRequestDialog::setInfo(const SendCoinsRecipient &_info) { - this->info = info; + this->info = _info; update(); } diff --git a/src/qt/res/movies/makespinner.sh b/src/qt/res/movies/makespinner.sh index a4c2fddbbf..d0deb1238c 100755 --- a/src/qt/res/movies/makespinner.sh +++ b/src/qt/res/movies/makespinner.sh @@ -1,3 +1,7 @@ +# Copyright (c) 2014-2015 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + FRAMEDIR=$(dirname $0) for i in {0..35} do diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index f35f401d06..ace9f1ceaa 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -83,8 +83,8 @@ class QtRPCTimerBase: public QObject, public RPCTimerBase { Q_OBJECT public: - QtRPCTimerBase(boost::function<void(void)>& func, int64_t millis): - func(func) + QtRPCTimerBase(boost::function<void(void)>& _func, int64_t millis): + func(_func) { timer.setSingleShot(true); connect(&timer, SIGNAL(timeout()), this, SLOT(timeout())); @@ -113,9 +113,11 @@ public: #include "rpcconsole.moc" /** - * Split shell command line into a list of arguments. Aims to emulate \c bash and friends. + * Split shell command line into a list of arguments and execute the command(s). + * Aims to emulate \c bash and friends. * - * - Arguments are delimited with whitespace + * - Command nesting is possible with brackets [example: validateaddress(getnewaddress())] + * - Arguments are delimited with whitespace or comma * - Extra whitespace at the beginning and end and between arguments will be ignored * - Text can be "double" or 'single' quoted * - The backslash \c \ is used as escape character @@ -123,11 +125,15 @@ public: * - Within double quotes, only escape \c " and backslashes before a \c " or another backslash * - Within single quotes, no escaping is possible and no special interpretation takes place * - * @param[out] args Parsed arguments will be appended to this list + * @param[out] result stringified Result from the executed command(chain) * @param[in] strCommand Command line to split */ -bool parseCommandLine(std::vector<std::string> &args, const std::string &strCommand) + +bool RPCConsole::RPCExecuteCommandLine(std::string &strResult, const std::string &strCommand) { + std::vector< std::vector<std::string> > stack; + stack.push_back(std::vector<std::string>()); + enum CmdParseState { STATE_EATING_SPACES, @@ -135,95 +141,180 @@ bool parseCommandLine(std::vector<std::string> &args, const std::string &strComm STATE_SINGLEQUOTED, STATE_DOUBLEQUOTED, STATE_ESCAPE_OUTER, - STATE_ESCAPE_DOUBLEQUOTED + STATE_ESCAPE_DOUBLEQUOTED, + STATE_COMMAND_EXECUTED, + STATE_COMMAND_EXECUTED_INNER } state = STATE_EATING_SPACES; std::string curarg; - Q_FOREACH(char ch, strCommand) + UniValue lastResult; + + std::string strCommandTerminated = strCommand; + if (strCommandTerminated.back() != '\n') + strCommandTerminated += "\n"; + for(char ch: strCommandTerminated) { switch(state) { - case STATE_ARGUMENT: // In or after argument - case STATE_EATING_SPACES: // Handle runs of whitespace - switch(ch) + case STATE_COMMAND_EXECUTED_INNER: + case STATE_COMMAND_EXECUTED: { - case '"': state = STATE_DOUBLEQUOTED; break; - case '\'': state = STATE_SINGLEQUOTED; break; - case '\\': state = STATE_ESCAPE_OUTER; break; - case ' ': case '\n': case '\t': - if(state == STATE_ARGUMENT) // Space ends argument + bool breakParsing = true; + switch(ch) { - args.push_back(curarg); - curarg.clear(); + case '[': curarg.clear(); state = STATE_COMMAND_EXECUTED_INNER; break; + default: + if (state == STATE_COMMAND_EXECUTED_INNER) + { + if (ch != ']') + { + // append char to the current argument (which is also used for the query command) + curarg += ch; + break; + } + if (curarg.size()) + { + // if we have a value query, query arrays with index and objects with a string key + UniValue subelement; + if (lastResult.isArray()) + { + for(char argch: curarg) + if (!std::isdigit(argch)) + throw std::runtime_error("Invalid result query"); + subelement = lastResult[atoi(curarg.c_str())]; + } + else if (lastResult.isObject()) + subelement = find_value(lastResult, curarg); + else + throw std::runtime_error("Invalid result query"); //no array or object: abort + lastResult = subelement; + } + + state = STATE_COMMAND_EXECUTED; + break; + } + // don't break parsing when the char is required for the next argument + breakParsing = false; + + // pop the stack and return the result to the current command arguments + stack.pop_back(); + + // don't stringify the json in case of a string to avoid doublequotes + if (lastResult.isStr()) + curarg = lastResult.get_str(); + else + curarg = lastResult.write(2); + + // if we have a non empty result, use it as stack argument otherwise as general result + if (curarg.size()) + { + if (stack.size()) + stack.back().push_back(curarg); + else + strResult = curarg; + } + curarg.clear(); + // assume eating space state + state = STATE_EATING_SPACES; } - state = STATE_EATING_SPACES; - break; - default: curarg += ch; state = STATE_ARGUMENT; + if (breakParsing) + break; } - break; - case STATE_SINGLEQUOTED: // Single-quoted string - switch(ch) + case STATE_ARGUMENT: // In or after argument + case STATE_EATING_SPACES: // Handle runs of whitespace + switch(ch) { - case '\'': state = STATE_ARGUMENT; break; - default: curarg += ch; + case '"': state = STATE_DOUBLEQUOTED; break; + case '\'': state = STATE_SINGLEQUOTED; break; + case '\\': state = STATE_ESCAPE_OUTER; break; + case '(': case ')': case '\n': + if (state == STATE_ARGUMENT) + { + if (ch == '(' && stack.size() && stack.back().size() > 0) + stack.push_back(std::vector<std::string>()); + if (curarg.size()) + { + // don't allow commands after executed commands on baselevel + if (!stack.size()) + throw std::runtime_error("Invalid Syntax"); + stack.back().push_back(curarg); + } + curarg.clear(); + state = STATE_EATING_SPACES; + } + if ((ch == ')' || ch == '\n') && stack.size() > 0) + { + std::string strPrint; + // Convert argument list to JSON objects in method-dependent way, + // and pass it along with the method name to the dispatcher. + lastResult = tableRPC.execute(stack.back()[0], RPCConvertValues(stack.back()[0], std::vector<std::string>(stack.back().begin() + 1, stack.back().end()))); + + state = STATE_COMMAND_EXECUTED; + curarg.clear(); + } + break; + case ' ': case ',': case '\t': + if(state == STATE_ARGUMENT) // Space ends argument + { + if (curarg.size()) + stack.back().push_back(curarg); + curarg.clear(); + } + state = STATE_EATING_SPACES; + break; + default: curarg += ch; state = STATE_ARGUMENT; } - break; - case STATE_DOUBLEQUOTED: // Double-quoted string - switch(ch) + break; + case STATE_SINGLEQUOTED: // Single-quoted string + switch(ch) { - case '"': state = STATE_ARGUMENT; break; - case '\\': state = STATE_ESCAPE_DOUBLEQUOTED; break; - default: curarg += ch; + case '\'': state = STATE_ARGUMENT; break; + default: curarg += ch; } - break; - case STATE_ESCAPE_OUTER: // '\' outside quotes - curarg += ch; state = STATE_ARGUMENT; - break; - case STATE_ESCAPE_DOUBLEQUOTED: // '\' in double-quoted text - if(ch != '"' && ch != '\\') curarg += '\\'; // keep '\' for everything but the quote and '\' itself - curarg += ch; state = STATE_DOUBLEQUOTED; - break; + break; + case STATE_DOUBLEQUOTED: // Double-quoted string + switch(ch) + { + case '"': state = STATE_ARGUMENT; break; + case '\\': state = STATE_ESCAPE_DOUBLEQUOTED; break; + default: curarg += ch; + } + break; + case STATE_ESCAPE_OUTER: // '\' outside quotes + curarg += ch; state = STATE_ARGUMENT; + break; + case STATE_ESCAPE_DOUBLEQUOTED: // '\' in double-quoted text + if(ch != '"' && ch != '\\') curarg += '\\'; // keep '\' for everything but the quote and '\' itself + curarg += ch; state = STATE_DOUBLEQUOTED; + break; } } switch(state) // final state { - case STATE_EATING_SPACES: - return true; - case STATE_ARGUMENT: - args.push_back(curarg); - return true; - default: // ERROR to end in one of the other states - return false; + case STATE_COMMAND_EXECUTED: + if (lastResult.isStr()) + strResult = lastResult.get_str(); + else + strResult = lastResult.write(2); + case STATE_ARGUMENT: + case STATE_EATING_SPACES: + return true; + default: // ERROR to end in one of the other states + return false; } } void RPCExecutor::request(const QString &command) { - std::vector<std::string> args; - if(!parseCommandLine(args, command.toStdString())) - { - Q_EMIT reply(RPCConsole::CMD_ERROR, QString("Parse error: unbalanced ' or \"")); - return; - } - if(args.empty()) - return; // Nothing to do try { - std::string strPrint; - // Convert argument list to JSON objects in method-dependent way, - // and pass it along with the method name to the dispatcher. - UniValue result = tableRPC.execute( - args[0], - RPCConvertValues(args[0], std::vector<std::string>(args.begin() + 1, args.end()))); - - // Format result reply - if (result.isNull()) - strPrint = ""; - else if (result.isStr()) - strPrint = result.get_str(); - else - strPrint = result.write(2); - - Q_EMIT reply(RPCConsole::CMD_REPLY, QString::fromStdString(strPrint)); + std::string result; + std::string executableCommand = command.toStdString() + "\n"; + if(!RPCConsole::RPCExecuteCommandLine(result, executableCommand)) + { + Q_EMIT reply(RPCConsole::CMD_ERROR, QString("Parse error: unbalanced ' or \"")); + return; + } + Q_EMIT reply(RPCConsole::CMD_REPLY, QString::fromStdString(result)); } catch (UniValue& objError) { @@ -244,13 +335,13 @@ void RPCExecutor::request(const QString &command) } } -RPCConsole::RPCConsole(const PlatformStyle *platformStyle, QWidget *parent) : +RPCConsole::RPCConsole(const PlatformStyle *_platformStyle, QWidget *parent) : QWidget(parent), ui(new Ui::RPCConsole), clientModel(0), historyPtr(0), cachedNodeid(-1), - platformStyle(platformStyle), + platformStyle(_platformStyle), peersTableContextMenu(0), banTableContextMenu(0), consoleFontSize(0) diff --git a/src/qt/rpcconsole.h b/src/qt/rpcconsole.h index 28affa954d..50224a1cc0 100644 --- a/src/qt/rpcconsole.h +++ b/src/qt/rpcconsole.h @@ -35,6 +35,8 @@ public: explicit RPCConsole(const PlatformStyle *platformStyle, QWidget *parent); ~RPCConsole(); + static bool RPCExecuteCommandLine(std::string &strResult, const std::string &strCommand); + void setClientModel(ClientModel *model); enum MessageClass { diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp index 3e96bb18c3..4b2ba7d624 100644 --- a/src/qt/sendcoinsdialog.cpp +++ b/src/qt/sendcoinsdialog.cpp @@ -30,25 +30,25 @@ #define SEND_CONFIRM_DELAY 3 -SendCoinsDialog::SendCoinsDialog(const PlatformStyle *platformStyle, QWidget *parent) : +SendCoinsDialog::SendCoinsDialog(const PlatformStyle *_platformStyle, QWidget *parent) : QDialog(parent), ui(new Ui::SendCoinsDialog), clientModel(0), model(0), fNewRecipientAllowed(true), fFeeMinimized(true), - platformStyle(platformStyle) + platformStyle(_platformStyle) { ui->setupUi(this); - if (!platformStyle->getImagesOnButtons()) { + if (!_platformStyle->getImagesOnButtons()) { ui->addButton->setIcon(QIcon()); ui->clearButton->setIcon(QIcon()); ui->sendButton->setIcon(QIcon()); } else { - ui->addButton->setIcon(platformStyle->SingleColorIcon(":/icons/add")); - ui->clearButton->setIcon(platformStyle->SingleColorIcon(":/icons/remove")); - ui->sendButton->setIcon(platformStyle->SingleColorIcon(":/icons/send")); + ui->addButton->setIcon(_platformStyle->SingleColorIcon(":/icons/add")); + ui->clearButton->setIcon(_platformStyle->SingleColorIcon(":/icons/remove")); + ui->sendButton->setIcon(_platformStyle->SingleColorIcon(":/icons/send")); } GUIUtil::setupAddressWidget(ui->lineEditCoinControlChange, this); @@ -116,40 +116,40 @@ SendCoinsDialog::SendCoinsDialog(const PlatformStyle *platformStyle, QWidget *pa minimizeFeeSection(settings.value("fFeeSectionMinimized").toBool()); } -void SendCoinsDialog::setClientModel(ClientModel *clientModel) +void SendCoinsDialog::setClientModel(ClientModel *_clientModel) { - this->clientModel = clientModel; + this->clientModel = _clientModel; - if (clientModel) { - connect(clientModel, SIGNAL(numBlocksChanged(int,QDateTime,double,bool)), this, SLOT(updateSmartFeeLabel())); + if (_clientModel) { + connect(_clientModel, SIGNAL(numBlocksChanged(int,QDateTime,double,bool)), this, SLOT(updateSmartFeeLabel())); } } -void SendCoinsDialog::setModel(WalletModel *model) +void SendCoinsDialog::setModel(WalletModel *_model) { - this->model = model; + this->model = _model; - if(model && model->getOptionsModel()) + if(_model && _model->getOptionsModel()) { for(int i = 0; i < ui->entries->count(); ++i) { SendCoinsEntry *entry = qobject_cast<SendCoinsEntry*>(ui->entries->itemAt(i)->widget()); if(entry) { - entry->setModel(model); + entry->setModel(_model); } } - setBalance(model->getBalance(), model->getUnconfirmedBalance(), model->getImmatureBalance(), - model->getWatchBalance(), model->getWatchUnconfirmedBalance(), model->getWatchImmatureBalance()); - connect(model, SIGNAL(balanceChanged(CAmount,CAmount,CAmount,CAmount,CAmount,CAmount)), this, SLOT(setBalance(CAmount,CAmount,CAmount,CAmount,CAmount,CAmount))); - connect(model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit())); + setBalance(_model->getBalance(), _model->getUnconfirmedBalance(), _model->getImmatureBalance(), + _model->getWatchBalance(), _model->getWatchUnconfirmedBalance(), _model->getWatchImmatureBalance()); + connect(_model, SIGNAL(balanceChanged(CAmount,CAmount,CAmount,CAmount,CAmount,CAmount)), this, SLOT(setBalance(CAmount,CAmount,CAmount,CAmount,CAmount,CAmount))); + connect(_model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit())); updateDisplayUnit(); // Coin Control - connect(model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(coinControlUpdateLabels())); - connect(model->getOptionsModel(), SIGNAL(coinControlFeaturesChanged(bool)), this, SLOT(coinControlFeatureChanged(bool))); - ui->frameCoinControl->setVisible(model->getOptionsModel()->getCoinControlFeatures()); + connect(_model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(coinControlUpdateLabels())); + connect(_model->getOptionsModel(), SIGNAL(coinControlFeaturesChanged(bool)), this, SLOT(coinControlFeatureChanged(bool))); + ui->frameCoinControl->setVisible(_model->getOptionsModel()->getCoinControlFeatures()); coinControlUpdateLabels(); // fee section @@ -589,6 +589,9 @@ void SendCoinsDialog::updateGlobalFeeVariables() { nTxConfirmTarget = defaultConfirmTarget - ui->sliderSmartFee->value(); payTxFee = CFeeRate(0); + + // set nMinimumTotalFee to 0 to not accidentally pay a custom fee + CoinControlDialog::coinControl->nMinimumTotalFee = 0; } else { @@ -781,7 +784,7 @@ void SendCoinsDialog::coinControlUpdateLabels() ui->radioCustomAtLeast->setVisible(true); // only enable the feature if inputs are selected - ui->radioCustomAtLeast->setEnabled(CoinControlDialog::coinControl->HasSelected()); + ui->radioCustomAtLeast->setEnabled(ui->radioCustomFee->isChecked() && !ui->checkBoxMinimumFee->isChecked() &&CoinControlDialog::coinControl->HasSelected()); } else { @@ -823,9 +826,9 @@ void SendCoinsDialog::coinControlUpdateLabels() } } -SendConfirmationDialog::SendConfirmationDialog(const QString &title, const QString &text, int secDelay, +SendConfirmationDialog::SendConfirmationDialog(const QString &title, const QString &text, int _secDelay, QWidget *parent) : - QMessageBox(QMessageBox::Question, title, text, QMessageBox::Yes | QMessageBox::Cancel, parent), secDelay(secDelay) + QMessageBox(QMessageBox::Question, title, text, QMessageBox::Yes | QMessageBox::Cancel, parent), secDelay(_secDelay) { setDefaultButton(QMessageBox::Cancel); yesButton = button(QMessageBox::Yes); diff --git a/src/qt/sendcoinsentry.cpp b/src/qt/sendcoinsentry.cpp index d063f2c891..7eb1eb7e3a 100644 --- a/src/qt/sendcoinsentry.cpp +++ b/src/qt/sendcoinsentry.cpp @@ -15,11 +15,11 @@ #include <QApplication> #include <QClipboard> -SendCoinsEntry::SendCoinsEntry(const PlatformStyle *platformStyle, QWidget *parent) : +SendCoinsEntry::SendCoinsEntry(const PlatformStyle *_platformStyle, QWidget *parent) : QStackedWidget(parent), ui(new Ui::SendCoinsEntry), model(0), - platformStyle(platformStyle) + platformStyle(_platformStyle) { ui->setupUi(this); @@ -79,12 +79,12 @@ void SendCoinsEntry::on_payTo_textChanged(const QString &address) updateLabel(address); } -void SendCoinsEntry::setModel(WalletModel *model) +void SendCoinsEntry::setModel(WalletModel *_model) { - this->model = model; + this->model = _model; - if (model && model->getOptionsModel()) - connect(model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit())); + if (_model && _model->getOptionsModel()) + connect(_model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit())); clear(); } diff --git a/src/qt/signverifymessagedialog.cpp b/src/qt/signverifymessagedialog.cpp index 8e2e8a5098..4061909b71 100644 --- a/src/qt/signverifymessagedialog.cpp +++ b/src/qt/signverifymessagedialog.cpp @@ -20,11 +20,11 @@ #include <QClipboard> -SignVerifyMessageDialog::SignVerifyMessageDialog(const PlatformStyle *platformStyle, QWidget *parent) : +SignVerifyMessageDialog::SignVerifyMessageDialog(const PlatformStyle *_platformStyle, QWidget *parent) : QDialog(parent), ui(new Ui::SignVerifyMessageDialog), model(0), - platformStyle(platformStyle) + platformStyle(_platformStyle) { ui->setupUi(this); @@ -60,9 +60,9 @@ SignVerifyMessageDialog::~SignVerifyMessageDialog() delete ui; } -void SignVerifyMessageDialog::setModel(WalletModel *model) +void SignVerifyMessageDialog::setModel(WalletModel *_model) { - this->model = model; + this->model = _model; } void SignVerifyMessageDialog::setAddress_SM(const QString &address) diff --git a/src/qt/test/rpcnestedtests.cpp b/src/qt/test/rpcnestedtests.cpp new file mode 100644 index 0000000000..3dae33bafb --- /dev/null +++ b/src/qt/test/rpcnestedtests.cpp @@ -0,0 +1,93 @@ +// Copyright (c) 2016 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 "rpcnestedtests.h" + +#include "chainparams.h" +#include "consensus/validation.h" +#include "main.h" +#include "rpc/register.h" +#include "rpc/server.h" +#include "rpcconsole.h" +#include "test/testutil.h" +#include "univalue.h" +#include "util.h" + +#include <QDir> + +#include <boost/filesystem.hpp> + +void RPCNestedTests::rpcNestedTests() +{ + UniValue jsonRPCError; + + // do some test setup + // could be moved to a more generic place when we add more tests on QT level + const CChainParams& chainparams = Params(); + RegisterAllCoreRPCCommands(tableRPC); + ClearDatadirCache(); + std::string path = QDir::tempPath().toStdString() + "/" + strprintf("test_bitcoin_qt_%lu_%i", (unsigned long)GetTime(), (int)(GetRand(100000))); + QDir dir(QString::fromStdString(path)); + dir.mkpath("."); + mapArgs["-datadir"] = path; + //mempool.setSanityCheck(1.0); + pblocktree = new CBlockTreeDB(1 << 20, true); + pcoinsdbview = new CCoinsViewDB(1 << 23, true); + pcoinsTip = new CCoinsViewCache(pcoinsdbview); + InitBlockIndex(chainparams); + { + CValidationState state; + bool ok = ActivateBestChain(state, chainparams); + QVERIFY(ok); + } + + SetRPCWarmupFinished(); + + std::string result; + std::string result2; + RPCConsole::RPCExecuteCommandLine(result, "getblockchaininfo()[chain]"); //simple result filtering with path + QVERIFY(result=="main"); + + RPCConsole::RPCExecuteCommandLine(result, "getblock(getbestblockhash())"); //simple 2 level nesting + RPCConsole::RPCExecuteCommandLine(result, "getblock(getblock(getbestblockhash())[hash], true)"); + + RPCConsole::RPCExecuteCommandLine(result, "getblock( getblock( getblock(getbestblockhash())[hash] )[hash], true)"); //4 level nesting with whitespace, filtering path and boolean parameter + + RPCConsole::RPCExecuteCommandLine(result, "getblockchaininfo"); + QVERIFY(result.substr(0,1) == "{"); + + RPCConsole::RPCExecuteCommandLine(result, "getblockchaininfo()"); + QVERIFY(result.substr(0,1) == "{"); + + RPCConsole::RPCExecuteCommandLine(result, "getblockchaininfo "); //whitespace at the end will be tolerated + QVERIFY(result.substr(0,1) == "{"); + +#if QT_VERSION >= 0x050300 + // do the QVERIFY_EXCEPTION_THROWN checks only with Qt5.3 and higher (QVERIFY_EXCEPTION_THROWN was introduced in Qt5.3) + QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(result, "getblockchaininfo() .\n"), std::runtime_error); //invalid syntax + QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(result, "getblockchaininfo() getblockchaininfo()"), std::runtime_error); //invalid syntax + (RPCConsole::RPCExecuteCommandLine(result, "getblockchaininfo(")); //tolerate non closing brackets if we have no arguments + (RPCConsole::RPCExecuteCommandLine(result, "getblockchaininfo()()()")); //tolerate non command brackts + QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(result, "getblockchaininfo(True)"), UniValue); //invalid argument + QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(result, "a(getblockchaininfo(True))"), UniValue); //method not found +#endif + + (RPCConsole::RPCExecuteCommandLine(result, "getblockchaininfo()[\"chain\"]")); //Quote path identifier are allowed, but look after a child contaning the quotes in the key + QVERIFY(result == "null"); + + (RPCConsole::RPCExecuteCommandLine(result, "createrawtransaction [] {} 0")); //parameter not in brackets are allowed + (RPCConsole::RPCExecuteCommandLine(result2, "createrawtransaction([],{},0)")); //parameter in brackets are allowed + QVERIFY(result == result2); + (RPCConsole::RPCExecuteCommandLine(result2, "createrawtransaction( [], {} , 0 )")); //whitespace between parametres is allowed + QVERIFY(result == result2); + + RPCConsole::RPCExecuteCommandLine(result, "getblock(getbestblockhash())[tx][0]"); + QVERIFY(result == "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"); + + delete pcoinsTip; + delete pcoinsdbview; + delete pblocktree; + + boost::filesystem::remove_all(boost::filesystem::path(path)); +} diff --git a/src/qt/test/rpcnestedtests.h b/src/qt/test/rpcnestedtests.h new file mode 100644 index 0000000000..9ad409019f --- /dev/null +++ b/src/qt/test/rpcnestedtests.h @@ -0,0 +1,25 @@ +// Copyright (c) 2016 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_QT_TEST_RPC_NESTED_TESTS_H +#define BITCOIN_QT_TEST_RPC_NESTED_TESTS_H + +#include <QObject> +#include <QTest> + +#include "txdb.h" +#include "txmempool.h" + +class RPCNestedTests : public QObject +{ + Q_OBJECT + + private Q_SLOTS: + void rpcNestedTests(); + +private: + CCoinsViewDB *pcoinsdbview; +}; + +#endif // BITCOIN_QT_TEST_RPC_NESTED_TESTS_H diff --git a/src/qt/test/test_main.cpp b/src/qt/test/test_main.cpp index db193420bf..dbaab54fb6 100644 --- a/src/qt/test/test_main.cpp +++ b/src/qt/test/test_main.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2009-2015 The Bitcoin Core developers +// Copyright (c) 2009-2016 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -6,6 +6,9 @@ #include "config/bitcoin-config.h" #endif +#include "chainparams.h" +#include "key.h" +#include "rpcnestedtests.h" #include "util.h" #include "uritests.h" @@ -27,10 +30,17 @@ Q_IMPORT_PLUGIN(qtwcodecs) Q_IMPORT_PLUGIN(qkrcodecs) #endif +extern void noui_connect(); + // This is all you need to run all the tests int main(int argc, char *argv[]) { + ECC_Start(); SetupEnvironment(); + SetupNetworking(); + SelectParams(CBaseChainParams::MAIN); + noui_connect(); + bool fInvalid = false; // Don't remove this, it's needed to access @@ -48,6 +58,10 @@ int main(int argc, char *argv[]) if (QTest::qExec(&test2) != 0) fInvalid = true; #endif + RPCNestedTests test3; + if (QTest::qExec(&test3) != 0) + fInvalid = true; + ECC_Stop(); return fInvalid; } diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp index bae0cbd1c8..65144e7865 100644 --- a/src/qt/transactiondesc.cpp +++ b/src/qt/transactiondesc.cpp @@ -241,6 +241,7 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco strHTML += "<br><b>" + tr("Comment") + ":</b><br>" + GUIUtil::HtmlEscape(wtx.mapValue["comment"], true) + "<br>"; strHTML += "<b>" + tr("Transaction ID") + ":</b> " + rec->getTxID() + "<br>"; + strHTML += "<b>" + tr("Transaction total size") + ":</b> " + QString::number(wtx.GetTotalSize()) + " bytes<br>"; strHTML += "<b>" + tr("Output index") + ":</b> " + QString::number(rec->getOutputIndex()) + "<br>"; // Message from normal bitcoin:URI (bitcoin:123...?message=example) diff --git a/src/qt/transactionfilterproxy.cpp b/src/qt/transactionfilterproxy.cpp index 9dcb72f55e..e21b89b935 100644 --- a/src/qt/transactionfilterproxy.cpp +++ b/src/qt/transactionfilterproxy.cpp @@ -66,9 +66,9 @@ void TransactionFilterProxy::setDateRange(const QDateTime &from, const QDateTime invalidateFilter(); } -void TransactionFilterProxy::setAddressPrefix(const QString &addrPrefix) +void TransactionFilterProxy::setAddressPrefix(const QString &_addrPrefix) { - this->addrPrefix = addrPrefix; + this->addrPrefix = _addrPrefix; invalidateFilter(); } @@ -95,9 +95,9 @@ void TransactionFilterProxy::setLimit(int limit) this->limitRows = limit; } -void TransactionFilterProxy::setShowInactive(bool showInactive) +void TransactionFilterProxy::setShowInactive(bool _showInactive) { - this->showInactive = showInactive; + this->showInactive = _showInactive; invalidateFilter(); } diff --git a/src/qt/transactionrecord.h b/src/qt/transactionrecord.h index 8c754c3aad..8eff302aff 100644 --- a/src/qt/transactionrecord.h +++ b/src/qt/transactionrecord.h @@ -88,16 +88,16 @@ public: { } - TransactionRecord(uint256 hash, qint64 time): - hash(hash), time(time), type(Other), address(""), debit(0), + TransactionRecord(uint256 _hash, qint64 _time): + hash(_hash), time(_time), type(Other), address(""), debit(0), credit(0), idx(0) { } - TransactionRecord(uint256 hash, qint64 time, - Type type, const std::string &address, - const CAmount& debit, const CAmount& credit): - hash(hash), time(time), type(type), address(address), debit(debit), credit(credit), + TransactionRecord(uint256 _hash, qint64 _time, + Type _type, const std::string &_address, + const CAmount& _debit, const CAmount& _credit): + hash(_hash), time(_time), type(_type), address(_address), debit(_debit), credit(_credit), idx(0) { } diff --git a/src/qt/transactiontablemodel.cpp b/src/qt/transactiontablemodel.cpp index b29ecf8348..52261ff04b 100644 --- a/src/qt/transactiontablemodel.cpp +++ b/src/qt/transactiontablemodel.cpp @@ -59,9 +59,9 @@ struct TxLessThan class TransactionTablePriv { public: - TransactionTablePriv(CWallet *wallet, TransactionTableModel *parent) : - wallet(wallet), - parent(parent) + TransactionTablePriv(CWallet *_wallet, TransactionTableModel *_parent) : + wallet(_wallet), + parent(_parent) { } @@ -235,13 +235,13 @@ public: } }; -TransactionTableModel::TransactionTableModel(const PlatformStyle *platformStyle, CWallet* wallet, WalletModel *parent): +TransactionTableModel::TransactionTableModel(const PlatformStyle *_platformStyle, CWallet* _wallet, WalletModel *parent): QAbstractTableModel(parent), - wallet(wallet), + wallet(_wallet), walletModel(parent), - priv(new TransactionTablePriv(wallet, this)), + priv(new TransactionTablePriv(_wallet, this)), fProcessingQueuedTransactions(false), - platformStyle(platformStyle) + platformStyle(_platformStyle) { columns << QString() << QString() << tr("Date") << tr("Type") << tr("Label") << BitcoinUnits::getAmountColumnTitle(walletModel->getOptionsModel()->getDisplayUnit()); priv->refreshWallet(); @@ -714,8 +714,8 @@ struct TransactionNotification { public: TransactionNotification() {} - TransactionNotification(uint256 hash, ChangeType status, bool showTransaction): - hash(hash), status(status), showTransaction(showTransaction) {} + TransactionNotification(uint256 _hash, ChangeType _status, bool _showTransaction): + hash(_hash), status(_status), showTransaction(_showTransaction) {} void invoke(QObject *ttm) { diff --git a/src/qt/transactionview.cpp b/src/qt/transactionview.cpp index 48cf940502..856b16d2c4 100644 --- a/src/qt/transactionview.cpp +++ b/src/qt/transactionview.cpp @@ -184,13 +184,13 @@ TransactionView::TransactionView(const PlatformStyle *platformStyle, QWidget *pa connect(showDetailsAction, SIGNAL(triggered()), this, SLOT(showDetails())); } -void TransactionView::setModel(WalletModel *model) +void TransactionView::setModel(WalletModel *_model) { - this->model = model; - if(model) + this->model = _model; + if(_model) { transactionProxyModel = new TransactionFilterProxy(this); - transactionProxyModel->setSourceModel(model->getTransactionTableModel()); + transactionProxyModel->setSourceModel(_model->getTransactionTableModel()); transactionProxyModel->setDynamicSortFilter(true); transactionProxyModel->setSortCaseSensitivity(Qt::CaseInsensitive); transactionProxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive); @@ -214,10 +214,10 @@ void TransactionView::setModel(WalletModel *model) columnResizingFixer = new GUIUtil::TableViewLastColumnResizingFixer(transactionView, AMOUNT_MINIMUM_COLUMN_WIDTH, MINIMUM_COLUMN_WIDTH); - if (model->getOptionsModel()) + if (_model->getOptionsModel()) { // Add third party transaction URLs to context menu - QStringList listUrls = model->getOptionsModel()->getThirdPartyTxUrls().split("|", QString::SkipEmptyParts); + QStringList listUrls = _model->getOptionsModel()->getThirdPartyTxUrls().split("|", QString::SkipEmptyParts); for (int i = 0; i < listUrls.size(); ++i) { QString host = QUrl(listUrls[i].trimmed(), QUrl::StrictMode).host(); @@ -234,10 +234,10 @@ void TransactionView::setModel(WalletModel *model) } // show/hide column Watch-only - updateWatchOnlyColumn(model->haveWatchOnly()); + updateWatchOnlyColumn(_model->haveWatchOnly()); // Watch-only signal - connect(model, SIGNAL(notifyWatchonlyChanged(bool)), this, SLOT(updateWatchOnlyColumn(bool))); + connect(_model, SIGNAL(notifyWatchonlyChanged(bool)), this, SLOT(updateWatchOnlyColumn(bool))); } } diff --git a/src/qt/walletframe.cpp b/src/qt/walletframe.cpp index e4ca5e1831..69dcc9abb1 100644 --- a/src/qt/walletframe.cpp +++ b/src/qt/walletframe.cpp @@ -12,10 +12,10 @@ #include <QHBoxLayout> #include <QLabel> -WalletFrame::WalletFrame(const PlatformStyle *platformStyle, BitcoinGUI *_gui) : +WalletFrame::WalletFrame(const PlatformStyle *_platformStyle, BitcoinGUI *_gui) : QFrame(_gui), gui(_gui), - platformStyle(platformStyle) + platformStyle(_platformStyle) { // Leave HBox hook for adding a list view later QHBoxLayout *walletFrameLayout = new QHBoxLayout(this); @@ -33,9 +33,9 @@ WalletFrame::~WalletFrame() { } -void WalletFrame::setClientModel(ClientModel *clientModel) +void WalletFrame::setClientModel(ClientModel *_clientModel) { - this->clientModel = clientModel; + this->clientModel = _clientModel; } bool WalletFrame::addWallet(const QString& name, WalletModel *walletModel) @@ -57,6 +57,8 @@ bool WalletFrame::addWallet(const QString& name, WalletModel *walletModel) // Ensure a walletView is able to show the main window connect(walletView, SIGNAL(showNormalIfMinimized()), gui, SLOT(showNormalIfMinimized())); + connect(walletView, SIGNAL(outOfSyncWarningClicked()), this, SLOT(outOfSyncWarningClicked())); + return true; } @@ -195,3 +197,7 @@ WalletView *WalletFrame::currentWalletView() return qobject_cast<WalletView*>(walletStack->currentWidget()); } +void WalletFrame::outOfSyncWarningClicked() +{ + Q_EMIT requestedSyncWarningInfo(); +} diff --git a/src/qt/walletframe.h b/src/qt/walletframe.h index 9a5bc273c2..00c2f56363 100644 --- a/src/qt/walletframe.h +++ b/src/qt/walletframe.h @@ -38,6 +38,10 @@ public: void showOutOfSyncWarning(bool fShow); +Q_SIGNALS: + /** Notify that the user has requested more information about the out-of-sync warning */ + void requestedSyncWarningInfo(); + private: QStackedWidget *walletStack; BitcoinGUI *gui; @@ -78,6 +82,8 @@ public Q_SLOTS: void usedSendingAddresses(); /** Show used receiving addresses */ void usedReceivingAddresses(); + /** Pass on signal over requested out-of-sync-warning information */ + void outOfSyncWarningClicked(); }; #endif // BITCOIN_QT_WALLETFRAME_H diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index 73851e97fc..c8a2cb37ec 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -27,8 +27,8 @@ #include <boost/foreach.hpp> -WalletModel::WalletModel(const PlatformStyle *platformStyle, CWallet *wallet, OptionsModel *optionsModel, QObject *parent) : - QObject(parent), wallet(wallet), optionsModel(optionsModel), addressTableModel(0), +WalletModel::WalletModel(const PlatformStyle *platformStyle, CWallet *_wallet, OptionsModel *_optionsModel, QObject *parent) : + QObject(parent), wallet(_wallet), optionsModel(_optionsModel), addressTableModel(0), transactionTableModel(0), recentRequestsTableModel(0), cachedBalance(0), cachedUnconfirmedBalance(0), cachedImmatureBalance(0), @@ -531,10 +531,10 @@ WalletModel::UnlockContext WalletModel::requestUnlock() return UnlockContext(this, valid, was_locked); } -WalletModel::UnlockContext::UnlockContext(WalletModel *wallet, bool valid, bool relock): - wallet(wallet), - valid(valid), - relock(relock) +WalletModel::UnlockContext::UnlockContext(WalletModel *_wallet, bool _valid, bool _relock): + wallet(_wallet), + valid(_valid), + relock(_relock) { } @@ -684,6 +684,11 @@ bool WalletModel::abandonTransaction(uint256 hash) const return wallet->AbandonTransaction(hash); } +bool WalletModel::isWalletEnabled() +{ + return !GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET); +} + bool WalletModel::hdEnabled() const { return wallet->IsHDEnabled(); diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h index 6515faceac..b105c6d991 100644 --- a/src/qt/walletmodel.h +++ b/src/qt/walletmodel.h @@ -38,8 +38,8 @@ class SendCoinsRecipient { public: explicit SendCoinsRecipient() : amount(0), fSubtractFeeFromAmount(false), nVersion(SendCoinsRecipient::CURRENT_VERSION) { } - explicit SendCoinsRecipient(const QString &addr, const QString &label, const CAmount& amount, const QString &message): - address(addr), label(label), amount(amount), message(message), fSubtractFeeFromAmount(false), nVersion(SendCoinsRecipient::CURRENT_VERSION) {} + explicit SendCoinsRecipient(const QString &addr, const QString &_label, const CAmount& _amount, const QString &_message): + address(addr), label(_label), amount(_amount), message(_message), fSubtractFeeFromAmount(false), nVersion(SendCoinsRecipient::CURRENT_VERSION) {} // If from an unauthenticated payment request, this is used for storing // the addresses, e.g. address-A<br />address-B<br />address-C. @@ -144,8 +144,8 @@ public: // Return status record for SendCoins, contains error id + information struct SendCoinsReturn { - SendCoinsReturn(StatusCode status = OK): - status(status) {} + SendCoinsReturn(StatusCode _status = OK): + status(_status) {} StatusCode status; }; @@ -202,6 +202,8 @@ public: bool transactionCanBeAbandoned(uint256 hash) const; bool abandonTransaction(uint256 hash) const; + static bool isWalletEnabled(); + bool hdEnabled() const; private: diff --git a/src/qt/walletmodeltransaction.cpp b/src/qt/walletmodeltransaction.cpp index ffadf89cc8..fdec6a1c86 100644 --- a/src/qt/walletmodeltransaction.cpp +++ b/src/qt/walletmodeltransaction.cpp @@ -7,8 +7,8 @@ #include "policy/policy.h" #include "wallet/wallet.h" -WalletModelTransaction::WalletModelTransaction(const QList<SendCoinsRecipient> &recipients) : - recipients(recipients), +WalletModelTransaction::WalletModelTransaction(const QList<SendCoinsRecipient> &_recipients) : + recipients(_recipients), walletTransaction(0), keyChange(0), fee(0) diff --git a/src/qt/walletview.cpp b/src/qt/walletview.cpp index 495ebfd834..a9518413c2 100644 --- a/src/qt/walletview.cpp +++ b/src/qt/walletview.cpp @@ -29,11 +29,11 @@ #include <QPushButton> #include <QVBoxLayout> -WalletView::WalletView(const PlatformStyle *platformStyle, QWidget *parent): +WalletView::WalletView(const PlatformStyle *_platformStyle, QWidget *parent): QStackedWidget(parent), clientModel(0), walletModel(0), - platformStyle(platformStyle) + platformStyle(_platformStyle) { // Create tabs overviewPage = new OverviewPage(platformStyle); @@ -66,6 +66,7 @@ WalletView::WalletView(const PlatformStyle *platformStyle, QWidget *parent): // Clicking on a transaction on the overview pre-selects the transaction on the transaction history page connect(overviewPage, SIGNAL(transactionClicked(QModelIndex)), transactionView, SLOT(focusTransaction(QModelIndex))); + connect(overviewPage, SIGNAL(outOfSyncWarningClicked()), this, SLOT(requestedSyncWarningInfo())); // Double-clicking on a transaction on the transaction history page shows details connect(transactionView, SIGNAL(doubleClicked(QModelIndex)), transactionView, SLOT(showDetails())); @@ -104,47 +105,47 @@ void WalletView::setBitcoinGUI(BitcoinGUI *gui) } } -void WalletView::setClientModel(ClientModel *clientModel) +void WalletView::setClientModel(ClientModel *_clientModel) { - this->clientModel = clientModel; + this->clientModel = _clientModel; - overviewPage->setClientModel(clientModel); - sendCoinsPage->setClientModel(clientModel); + overviewPage->setClientModel(_clientModel); + sendCoinsPage->setClientModel(_clientModel); } -void WalletView::setWalletModel(WalletModel *walletModel) +void WalletView::setWalletModel(WalletModel *_walletModel) { - this->walletModel = walletModel; + this->walletModel = _walletModel; // Put transaction list in tabs - transactionView->setModel(walletModel); - overviewPage->setWalletModel(walletModel); - receiveCoinsPage->setModel(walletModel); - sendCoinsPage->setModel(walletModel); - usedReceivingAddressesPage->setModel(walletModel->getAddressTableModel()); - usedSendingAddressesPage->setModel(walletModel->getAddressTableModel()); - - if (walletModel) + transactionView->setModel(_walletModel); + overviewPage->setWalletModel(_walletModel); + receiveCoinsPage->setModel(_walletModel); + sendCoinsPage->setModel(_walletModel); + usedReceivingAddressesPage->setModel(_walletModel->getAddressTableModel()); + usedSendingAddressesPage->setModel(_walletModel->getAddressTableModel()); + + if (_walletModel) { // Receive and pass through messages from wallet model - connect(walletModel, SIGNAL(message(QString,QString,unsigned int)), this, SIGNAL(message(QString,QString,unsigned int))); + connect(_walletModel, SIGNAL(message(QString,QString,unsigned int)), this, SIGNAL(message(QString,QString,unsigned int))); // Handle changes in encryption status - connect(walletModel, SIGNAL(encryptionStatusChanged(int)), this, SIGNAL(encryptionStatusChanged(int))); + connect(_walletModel, SIGNAL(encryptionStatusChanged(int)), this, SIGNAL(encryptionStatusChanged(int))); updateEncryptionStatus(); // update HD status - Q_EMIT hdEnabledStatusChanged(walletModel->hdEnabled()); + Q_EMIT hdEnabledStatusChanged(_walletModel->hdEnabled()); // Balloon pop-up for new transaction - connect(walletModel->getTransactionTableModel(), SIGNAL(rowsInserted(QModelIndex,int,int)), + connect(_walletModel->getTransactionTableModel(), SIGNAL(rowsInserted(QModelIndex,int,int)), this, SLOT(processNewTransaction(QModelIndex,int,int))); // Ask for passphrase if needed - connect(walletModel, SIGNAL(requireUnlock()), this, SLOT(unlockWallet())); + connect(_walletModel, SIGNAL(requireUnlock()), this, SLOT(unlockWallet())); // Show progress dialog - connect(walletModel, SIGNAL(showProgress(QString,int)), this, SLOT(showProgress(QString,int))); + connect(_walletModel, SIGNAL(showProgress(QString,int)), this, SLOT(showProgress(QString,int))); } } @@ -322,3 +323,8 @@ void WalletView::showProgress(const QString &title, int nProgress) else if (progressDialog) progressDialog->setValue(nProgress); } + +void WalletView::requestedSyncWarningInfo() +{ + Q_EMIT outOfSyncWarningClicked(); +} diff --git a/src/qt/walletview.h b/src/qt/walletview.h index 2045605954..aaa6aacbf0 100644 --- a/src/qt/walletview.h +++ b/src/qt/walletview.h @@ -110,6 +110,9 @@ public Q_SLOTS: /** Show progress dialog e.g. for rescan */ void showProgress(const QString &title, int nProgress); + /** User has requested more information about the out of sync state */ + void requestedSyncWarningInfo(); + Q_SIGNALS: /** Signal that we want to show the main window */ void showNormalIfMinimized(); @@ -121,6 +124,8 @@ Q_SIGNALS: void hdEnabledStatusChanged(int hdEnabled); /** Notify that a new transaction appeared */ void incomingTransaction(const QString& date, int unit, const CAmount& amount, const QString& type, const QString& address, const QString& label); + /** Notify that the out of sync warning icon has been pressed */ + void outOfSyncWarningClicked(); }; #endif // BITCOIN_QT_WALLETVIEW_H diff --git a/src/reverselock.h b/src/reverselock.h index fac1ccb793..1fd8de5d80 100644 --- a/src/reverselock.h +++ b/src/reverselock.h @@ -13,9 +13,9 @@ class reverse_lock { public: - explicit reverse_lock(Lock& lock) : lock(lock) { - lock.unlock(); - lock.swap(templock); + explicit reverse_lock(Lock& _lock) : lock(_lock) { + _lock.unlock(); + _lock.swap(templock); } ~reverse_lock() { diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index f05f8ff358..41d862934a 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -497,10 +497,10 @@ UniValue getmempoolancestors(const UniValue& params, bool fHelp) UniValue o(UniValue::VOBJ); BOOST_FOREACH(CTxMemPool::txiter ancestorIt, setAncestors) { const CTxMemPoolEntry &e = *ancestorIt; - const uint256& hash = e.GetTx().GetHash(); + const uint256& _hash = e.GetTx().GetHash(); UniValue info(UniValue::VOBJ); entryToJSON(info, e); - o.push_back(Pair(hash.ToString(), info)); + o.push_back(Pair(_hash.ToString(), info)); } return o; } @@ -561,10 +561,10 @@ UniValue getmempooldescendants(const UniValue& params, bool fHelp) UniValue o(UniValue::VOBJ); BOOST_FOREACH(CTxMemPool::txiter descendantIt, setDescendants) { const CTxMemPoolEntry &e = *descendantIt; - const uint256& hash = e.GetTx().GetHash(); + const uint256& _hash = e.GetTx().GetHash(); UniValue info(UniValue::VOBJ); entryToJSON(info, e); - o.push_back(Pair(hash.ToString(), info)); + o.push_back(Pair(_hash.ToString(), info)); } return o; } @@ -848,6 +848,8 @@ UniValue gettxoutsetinfo(const UniValue& params, bool fHelp) ret.push_back(Pair("bytes_serialized", (int64_t)stats.nSerializedSize)); ret.push_back(Pair("hash_serialized", stats.hashSerialized.GetHex())); ret.push_back(Pair("total_amount", ValueFromAmount(stats.nTotalAmount))); + } else { + throw JSONRPCError(RPC_INTERNAL_ERROR, "Unable to read UTXO set"); } return ret; } diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 7794ac619d..6b13aa5bab 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -607,8 +607,8 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp) UniValue aRules(UniValue::VARR); UniValue vbavailable(UniValue::VOBJ); - for (int i = 0; i < (int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; ++i) { - Consensus::DeploymentPos pos = Consensus::DeploymentPos(i); + for (int j = 0; j < (int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; ++j) { + Consensus::DeploymentPos pos = Consensus::DeploymentPos(j); ThresholdState state = VersionBitsState(pindexPrev, consensusParams, pos, versionbitscache); switch (state) { case THRESHOLD_DEFINED: diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index 2b5782367c..f0b7e0a07c 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -44,7 +44,7 @@ UniValue getinfo(const UniValue& params, bool fHelp) if (fHelp || params.size() != 0) throw runtime_error( "getinfo\n" - "Returns an object containing various state info.\n" + "\nDEPRECATED. Returns an object containing various state info.\n" "\nResult:\n" "{\n" " \"version\": xxxxx, (numeric) the server version\n" @@ -321,43 +321,6 @@ UniValue createmultisig(const UniValue& params, bool fHelp) return result; } -UniValue createwitnessaddress(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() < 1 || params.size() > 1) - { - string msg = "createwitnessaddress \"script\"\n" - "\nCreates a witness address for a particular script.\n" - "It returns a json object with the address and witness script.\n" - - "\nArguments:\n" - "1. \"script\" (string, required) A hex encoded script\n" - - "\nResult:\n" - "{\n" - " \"address\":\"multisigaddress\", (string) The value of the new address (P2SH of witness script).\n" - " \"witnessScript\":\"script\" (string) The string value of the hex-encoded witness script.\n" - "}\n" - ; - throw runtime_error(msg); - } - - if (!IsHex(params[0].get_str())) { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Script must be hex-encoded"); - } - - std::vector<unsigned char> code = ParseHex(params[0].get_str()); - CScript script(code.begin(), code.end()); - CScript witscript = GetScriptForWitness(script); - CScriptID witscriptid(witscript); - CBitcoinAddress address(witscriptid); - - UniValue result(UniValue::VOBJ); - result.push_back(Pair("address", address.ToString())); - result.push_back(Pair("witnessScript", HexStr(witscript.begin(), witscript.end()))); - - return result; -} - UniValue verifymessage(const UniValue& params, bool fHelp) { if (fHelp || params.size() != 3) @@ -493,7 +456,6 @@ static const CRPCCommand commands[] = { "control", "getinfo", &getinfo, true }, /* uses wallet if enabled */ { "util", "validateaddress", &validateaddress, true }, /* uses wallet if enabled */ { "util", "createmultisig", &createmultisig, true }, - { "util", "createwitnessaddress", &createwitnessaddress, true }, { "util", "verifymessage", &verifymessage, true }, { "util", "signmessagewithprivkey", &signmessagewithprivkey, true }, diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp index 47ea261e31..41756ea711 100644 --- a/src/script/interpreter.cpp +++ b/src/script/interpreter.cpp @@ -428,6 +428,12 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un if (stack.size() < 1) return set_error(serror, SCRIPT_ERR_UNBALANCED_CONDITIONAL); valtype& vch = stacktop(-1); + if (sigversion == SIGVERSION_WITNESS_V0 && (flags & SCRIPT_VERIFY_MINIMALIF)) { + if (vch.size() > 1) + return set_error(serror, SCRIPT_ERR_MINIMALIF); + if (vch.size() == 1 && vch[0] != 1) + return set_error(serror, SCRIPT_ERR_MINIMALIF); + } fValue = CastToBool(vch); if (opcode == OP_NOTIF) fValue = !fValue; @@ -879,6 +885,9 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un } bool fSuccess = checker.CheckSig(vchSig, vchPubKey, scriptCode, sigversion); + if (!fSuccess && (flags & SCRIPT_VERIFY_NULLFAIL) && vchSig.size()) + return set_error(serror, SCRIPT_ERR_SIG_NULLFAIL); + popstack(stack); popstack(stack); stack.push_back(fSuccess ? vchTrue : vchFalse); @@ -908,6 +917,9 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un if (nOpCount > MAX_OPS_PER_SCRIPT) return set_error(serror, SCRIPT_ERR_OP_COUNT); int ikey = ++i; + // ikey2 is the position of last non-signature item in the stack. Top stack item = 1. + // With SCRIPT_VERIFY_NULLFAIL, this is used for cleanup if operation fails. + int ikey2 = nKeysCount + 2; i += nKeysCount; if ((int)stack.size() < i) return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION); @@ -964,8 +976,14 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un } // Clean up stack of actual arguments - while (i-- > 1) + while (i-- > 1) { + // If the operation failed, we require that all signatures must be empty vector + if (!fSuccess && (flags & SCRIPT_VERIFY_NULLFAIL) && !ikey2 && stacktop(-1).size()) + return set_error(serror, SCRIPT_ERR_SIG_NULLFAIL); + if (ikey2 > 0) + ikey2--; popstack(stack); + } // A bug causes CHECKMULTISIG to consume one extra argument // whose contents were not checked in any way. diff --git a/src/script/interpreter.h b/src/script/interpreter.h index e5d7865cd3..0adc9482ff 100644 --- a/src/script/interpreter.h +++ b/src/script/interpreter.h @@ -94,6 +94,14 @@ enum // Making v1-v16 witness program non-standard // SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM = (1U << 12), + + // Segwit script only: Require the argument of OP_IF/NOTIF to be exactly 0x01 or empty vector + // + SCRIPT_VERIFY_MINIMALIF = (1U << 13), + + // Signature(s) must be empty vector if an CHECK(MULTI)SIG operation failed + // + SCRIPT_VERIFY_NULLFAIL = (1U << 14), }; bool CheckSignatureEncoding(const std::vector<unsigned char> &vchSig, unsigned int flags, ScriptError* serror); diff --git a/src/script/script_error.cpp b/src/script/script_error.cpp index cef807edcf..e27b715c2c 100644 --- a/src/script/script_error.cpp +++ b/src/script/script_error.cpp @@ -63,6 +63,10 @@ const char* ScriptErrorString(const ScriptError serror) return "Non-canonical signature: S value is unnecessarily high"; case SCRIPT_ERR_SIG_NULLDUMMY: return "Dummy CHECKMULTISIG argument must be zero"; + case SCRIPT_ERR_MINIMALIF: + return "OP_IF/NOTIF argument must be minimal"; + case SCRIPT_ERR_SIG_NULLFAIL: + return "Signature must be zero for failed CHECK(MULTI)SIG operation"; case SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS: return "NOPx reserved for soft-fork upgrades"; case SCRIPT_ERR_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM: diff --git a/src/script/script_error.h b/src/script/script_error.h index 09dc6945ad..bccfdb99e2 100644 --- a/src/script/script_error.h +++ b/src/script/script_error.h @@ -39,7 +39,7 @@ typedef enum ScriptError_t SCRIPT_ERR_NEGATIVE_LOCKTIME, SCRIPT_ERR_UNSATISFIED_LOCKTIME, - /* BIP62 */ + /* Malleability */ SCRIPT_ERR_SIG_HASHTYPE, SCRIPT_ERR_SIG_DER, SCRIPT_ERR_MINIMALDATA, @@ -48,6 +48,8 @@ typedef enum ScriptError_t SCRIPT_ERR_SIG_NULLDUMMY, SCRIPT_ERR_PUBKEYTYPE, SCRIPT_ERR_CLEANSTACK, + SCRIPT_ERR_MINIMALIF, + SCRIPT_ERR_SIG_NULLFAIL, /* softfork safeness */ SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS, diff --git a/src/support/pagelocker.h b/src/support/pagelocker.h index 6b3979e551..538bf39453 100644 --- a/src/support/pagelocker.h +++ b/src/support/pagelocker.h @@ -28,11 +28,11 @@ template <class Locker> class LockedPageManagerBase { public: - LockedPageManagerBase(size_t page_size) : page_size(page_size) + LockedPageManagerBase(size_t _page_size) : page_size(_page_size) { // Determine bitmask for extracting page from address - assert(!(page_size & (page_size - 1))); // size must be power of two - page_mask = ~(page_size - 1); + assert(!(_page_size & (_page_size - 1))); // size must be power of two + page_mask = ~(_page_size - 1); } ~LockedPageManagerBase() diff --git a/src/test/DoS_tests.cpp b/src/test/DoS_tests.cpp index 33f107d84b..97abeb7211 100644 --- a/src/test/DoS_tests.cpp +++ b/src/test/DoS_tests.cpp @@ -48,7 +48,7 @@ BOOST_AUTO_TEST_CASE(DoS_banning) { connman->ClearBanned(); CAddress addr1(ip(0xa0b0c001), NODE_NONE); - CNode dummyNode1(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr1, "", true); + CNode dummyNode1(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr1, 0, "", true); GetNodeSignals().InitializeNode(dummyNode1.GetId(), &dummyNode1); dummyNode1.nVersion = 1; Misbehaving(dummyNode1.GetId(), 100); // Should get banned @@ -57,7 +57,7 @@ BOOST_AUTO_TEST_CASE(DoS_banning) BOOST_CHECK(!connman->IsBanned(ip(0xa0b0c001|0x0000ff00))); // Different IP, not banned CAddress addr2(ip(0xa0b0c002), NODE_NONE); - CNode dummyNode2(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr2, "", true); + CNode dummyNode2(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr2, 1, "", true); GetNodeSignals().InitializeNode(dummyNode2.GetId(), &dummyNode2); dummyNode2.nVersion = 1; Misbehaving(dummyNode2.GetId(), 50); @@ -74,7 +74,7 @@ BOOST_AUTO_TEST_CASE(DoS_banscore) connman->ClearBanned(); mapArgs["-banscore"] = "111"; // because 11 is my favorite number CAddress addr1(ip(0xa0b0c001), NODE_NONE); - CNode dummyNode1(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr1, "", true); + CNode dummyNode1(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr1, 3, "", true); GetNodeSignals().InitializeNode(dummyNode1.GetId(), &dummyNode1); dummyNode1.nVersion = 1; Misbehaving(dummyNode1.GetId(), 100); @@ -96,7 +96,7 @@ BOOST_AUTO_TEST_CASE(DoS_bantime) SetMockTime(nStartTime); // Overrides future calls to GetTime() CAddress addr(ip(0xa0b0c001), NODE_NONE); - CNode dummyNode(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr, "", true); + CNode dummyNode(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr, 4, "", true); GetNodeSignals().InitializeNode(dummyNode.GetId(), &dummyNode); dummyNode.nVersion = 1; diff --git a/src/test/addrman_tests.cpp b/src/test/addrman_tests.cpp index 5f150e4812..5ccaeb57bb 100644 --- a/src/test/addrman_tests.cpp +++ b/src/test/addrman_tests.cpp @@ -257,8 +257,7 @@ BOOST_AUTO_TEST_CASE(addrman_tried_collisions) addrman.Good(CAddress(addr, NODE_NONE)); //Test 15: No collision in tried table yet. - BOOST_TEST_MESSAGE(addrman.size()); - BOOST_CHECK(addrman.size() == i); + BOOST_CHECK_EQUAL(addrman.size(), i); } //Test 16: tried table collision! @@ -543,4 +542,4 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_new_bucket) // than 64 buckets. BOOST_CHECK(buckets.size() > 64); } -BOOST_AUTO_TEST_SUITE_END()
\ No newline at end of file +BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/crypto_tests.cpp b/src/test/crypto_tests.cpp index 58a62ee022..ff0adae1d2 100644 --- a/src/test/crypto_tests.cpp +++ b/src/test/crypto_tests.cpp @@ -133,13 +133,13 @@ void TestAES128CBC(const std::string &hexkey, const std::string &hexiv, bool pad { std::vector<unsigned char> sub(i, in.end()); std::vector<unsigned char> subout(sub.size() + AES_BLOCKSIZE); - int size = enc.Encrypt(&sub[0], sub.size(), &subout[0]); - if (size != 0) + int _size = enc.Encrypt(&sub[0], sub.size(), &subout[0]); + if (_size != 0) { - subout.resize(size); + subout.resize(_size); std::vector<unsigned char> subdecrypted(subout.size()); - size = dec.Decrypt(&subout[0], subout.size(), &subdecrypted[0]); - subdecrypted.resize(size); + _size = dec.Decrypt(&subout[0], subout.size(), &subdecrypted[0]); + subdecrypted.resize(_size); BOOST_CHECK(decrypted.size() == in.size()); BOOST_CHECK_MESSAGE(subdecrypted == sub, HexStr(subdecrypted) + std::string(" != ") + HexStr(sub)); } @@ -174,13 +174,13 @@ void TestAES256CBC(const std::string &hexkey, const std::string &hexiv, bool pad { std::vector<unsigned char> sub(i, in.end()); std::vector<unsigned char> subout(sub.size() + AES_BLOCKSIZE); - int size = enc.Encrypt(&sub[0], sub.size(), &subout[0]); - if (size != 0) + int _size = enc.Encrypt(&sub[0], sub.size(), &subout[0]); + if (_size != 0) { - subout.resize(size); + subout.resize(_size); std::vector<unsigned char> subdecrypted(subout.size()); - size = dec.Decrypt(&subout[0], subout.size(), &subdecrypted[0]); - subdecrypted.resize(size); + _size = dec.Decrypt(&subout[0], subout.size(), &subdecrypted[0]); + subdecrypted.resize(_size); BOOST_CHECK(decrypted.size() == in.size()); BOOST_CHECK_MESSAGE(subdecrypted == sub, HexStr(subdecrypted) + std::string(" != ") + HexStr(sub)); } diff --git a/src/test/data/bitcoin-util-test.json b/src/test/data/bitcoin-util-test.json index 5cb383de85..9df61a7e79 100644 --- a/src/test/data/bitcoin-util-test.json +++ b/src/test/data/bitcoin-util-test.json @@ -1,19 +1,33 @@ [ - { "exec": "././bitcoin-tx", + { "exec": "./bitcoin-tx", "args": ["-create"], "output_cmp": "blanktx.hex" }, { "exec": "./bitcoin-tx", + "args": ["-json","-create"], + "output_cmp": "blanktx.json" + }, + { "exec": "./bitcoin-tx", "args": ["-"], "input": "blanktx.hex", "output_cmp": "blanktx.hex" }, { "exec": "./bitcoin-tx", + "args": ["-json","-"], + "input": "blanktx.hex", + "output_cmp": "blanktx.json" + }, + { "exec": "./bitcoin-tx", "args": ["-", "delin=1"], "input": "tx394b54bb.hex", "output_cmp": "tt-delin1-out.hex" }, { "exec": "./bitcoin-tx", + "args": ["-json", "-", "delin=1"], + "input": "tx394b54bb.hex", + "output_cmp": "tt-delin1-out.json" + }, + { "exec": "./bitcoin-tx", "args": ["-", "delin=31"], "input": "tx394b54bb.hex", "return_code": 1 @@ -24,6 +38,11 @@ "output_cmp": "tt-delout1-out.hex" }, { "exec": "./bitcoin-tx", + "args": ["-json", "-", "delout=1"], + "input": "tx394b54bb.hex", + "output_cmp": "tt-delout1-out.json" + }, + { "exec": "./bitcoin-tx", "args": ["-", "delout=2"], "input": "tx394b54bb.hex", "return_code": 1 @@ -34,6 +53,11 @@ "output_cmp": "tt-locktime317000-out.hex" }, { "exec": "./bitcoin-tx", + "args": ["-json", "-", "locktime=317000"], + "input": "tx394b54bb.hex", + "output_cmp": "tt-locktime317000-out.json" + }, + { "exec": "./bitcoin-tx", "args": ["-create", "in=5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f:0", @@ -44,10 +68,25 @@ "output_cmp": "txcreate1.hex" }, { "exec": "./bitcoin-tx", + "args": + ["-json", + "-create", + "in=5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f:0", + "in=bf829c6bcf84579331337659d31f89dfd138f7f7785802d5501c92333145ca7c:18", + "in=22a6f904655d53ae2ff70e701a0bbd90aa3975c0f40bfc6cc996a9049e31cdfc:1", + "outaddr=0.18:13tuJJDR2RgArmgfv6JScSdreahzgc4T6o", + "outaddr=4:1P8yWvZW8jVihP1bzHeqfE4aoXNX8AVa46"], + "output_cmp": "txcreate1.json" + }, + { "exec": "./bitcoin-tx", "args": ["-create", "outscript=0:"], "output_cmp": "txcreate2.hex" }, { "exec": "./bitcoin-tx", + "args": ["-json", "-create", "outscript=0:"], + "output_cmp": "txcreate2.json" + }, + { "exec": "./bitcoin-tx", "args": ["-create", "in=4d49a71ec9da436f71ec4ee231d04f292a29cd316f598bb7068feccabdc59485:0", @@ -59,6 +98,17 @@ }, { "exec": "./bitcoin-tx", "args": + ["-json", + "-create", + "in=4d49a71ec9da436f71ec4ee231d04f292a29cd316f598bb7068feccabdc59485:0", + "set=privatekeys:[\"5HpHagT65TZzG1PH3CSu63k8DbpvD8s5ip4nEB3kEsreAnchuDf\"]", + "set=prevtxs:[{\"txid\":\"4d49a71ec9da436f71ec4ee231d04f292a29cd316f598bb7068feccabdc59485\",\"vout\":0,\"scriptPubKey\":\"76a91491b24bf9f5288532960ac687abb035127b1d28a588ac\"}]", + "sign=ALL", + "outaddr=0.001:193P6LtvS4nCnkDvM9uXn1gsSRqh4aDAz7"], + "output_cmp": "txcreatesign.json" + }, + { "exec": "./bitcoin-tx", + "args": ["-create", "in=5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f:0", "outdata=4:badhexdata"], @@ -81,6 +131,15 @@ }, { "exec": "./bitcoin-tx", "args": + ["-json", + "-create", + "in=5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f:0", + "outaddr=0.18:13tuJJDR2RgArmgfv6JScSdreahzgc4T6o", + "outdata=4:54686973204f505f52455455524e207472616e73616374696f6e206f7574707574207761732063726561746564206279206d6f646966696564206372656174657261777472616e73616374696f6e2e"], + "output_cmp": "txcreatedata1.json" + }, + { "exec": "./bitcoin-tx", + "args": ["-create", "in=5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f:0", "outaddr=0.18:13tuJJDR2RgArmgfv6JScSdreahzgc4T6o", @@ -89,6 +148,15 @@ }, { "exec": "./bitcoin-tx", "args": + ["-json", + "-create", + "in=5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f:0", + "outaddr=0.18:13tuJJDR2RgArmgfv6JScSdreahzgc4T6o", + "outdata=54686973204f505f52455455524e207472616e73616374696f6e206f7574707574207761732063726561746564206279206d6f646966696564206372656174657261777472616e73616374696f6e2e"], + "output_cmp": "txcreatedata2.json" + }, + { "exec": "./bitcoin-tx", + "args": ["-create", "in=5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f:0:4294967293", "outaddr=0.18:13tuJJDR2RgArmgfv6JScSdreahzgc4T6o"], @@ -96,8 +164,23 @@ }, { "exec": "./bitcoin-tx", "args": + ["-json", + "-create", + "in=5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f:0:4294967293", + "outaddr=0.18:13tuJJDR2RgArmgfv6JScSdreahzgc4T6o"], + "output_cmp": "txcreatedata_seq0.json" + }, + { "exec": "./bitcoin-tx", + "args": ["01000000011f5c38dfcf6f1a5f5a87c416076d392c87e6d41970d5ad5e477a02d66bde97580000000000fdffffff0180a81201000000001976a9141fc11f39be1729bf973a7ab6a615ca4729d6457488ac00000000", "in=5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f:0:1"], "output_cmp": "txcreatedata_seq1.hex" + }, + { "exec": "./bitcoin-tx", + "args": + ["-json", + "01000000011f5c38dfcf6f1a5f5a87c416076d392c87e6d41970d5ad5e477a02d66bde97580000000000fdffffff0180a81201000000001976a9141fc11f39be1729bf973a7ab6a615ca4729d6457488ac00000000", + "in=5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f:0:1"], + "output_cmp": "txcreatedata_seq1.json" } ] diff --git a/src/test/data/blanktx.json b/src/test/data/blanktx.json new file mode 100644 index 0000000000..f6d6ab5884 --- /dev/null +++ b/src/test/data/blanktx.json @@ -0,0 +1,10 @@ +{ + "txid": "d21633ba23f70118185227be58a63527675641ad37967e2aa461559f577aec43", + "version": 1, + "locktime": 0, + "vin": [ + ], + "vout": [ + ], + "hex": "01000000000000000000" +} diff --git a/src/test/data/script_tests.json b/src/test/data/script_tests.json index fcd5457386..06103ea5bd 100644 --- a/src/test/data/script_tests.json +++ b/src/test/data/script_tests.json @@ -1492,6 +1492,27 @@ "BIP66 example 4, with DERSIG" ], [ + "0x09 0x300602010102010101", + "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT", + "DERSIG", + "OK", + "BIP66 example 4, with DERSIG, non-null DER-compliant signature" +], +[ + "0", + "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT", + "DERSIG,NULLFAIL", + "OK", + "BIP66 example 4, with DERSIG and NULLFAIL" +], +[ + "0x09 0x300602010102010101", + "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT", + "DERSIG,NULLFAIL", + "NULLFAIL", + "BIP66 example 4, with DERSIG and NULLFAIL, non-null DER-compliant signature" +], +[ "1", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG", "", @@ -2125,5 +2146,98 @@ ["0", "CHECKSEQUENCEVERIFY", "CHECKSEQUENCEVERIFY", "UNSATISFIED_LOCKTIME", "CSV fails if stack top bit 1 << 31 is set and the tx version < 2"], ["4294967296", "CHECKSEQUENCEVERIFY", "CHECKSEQUENCEVERIFY", "UNSATISFIED_LOCKTIME", "CSV fails if stack top bit 1 << 31 is not set, and tx version < 2"], + +["MINIMALIF tests"], +["MINIMALIF is not applied to non-segwit scripts"], +["1", "IF 1 ENDIF", "P2SH,WITNESS,MINIMALIF", "OK"], +["2", "IF 1 ENDIF", "P2SH,WITNESS,MINIMALIF", "OK"], +["0x02 0x0100", "IF 1 ENDIF", "P2SH,WITNESS,MINIMALIF", "OK"], +["0", "IF 1 ENDIF", "P2SH,WITNESS,MINIMALIF", "EVAL_FALSE"], +["0x01 0x00", "IF 1 ENDIF", "P2SH,WITNESS,MINIMALIF", "EVAL_FALSE"], +["1", "NOTIF 1 ENDIF", "P2SH,WITNESS,MINIMALIF", "EVAL_FALSE"], +["2", "NOTIF 1 ENDIF", "P2SH,WITNESS,MINIMALIF", "EVAL_FALSE"], +["0x02 0x0100", "NOTIF 1 ENDIF", "P2SH,WITNESS,MINIMALIF", "EVAL_FALSE"], +["0", "NOTIF 1 ENDIF", "P2SH,WITNESS,MINIMALIF", "OK"], +["0x01 0x00", "NOTIF 1 ENDIF", "P2SH,WITNESS,MINIMALIF", "OK"], +["Normal P2SH IF 1 ENDIF"], +["1 0x03 0x635168", "HASH160 0x14 0xe7309652a8e3f600f06f5d8d52d6df03d2176cc3 EQUAL", "P2SH,WITNESS,MINIMALIF", "OK"], +["2 0x03 0x635168", "HASH160 0x14 0xe7309652a8e3f600f06f5d8d52d6df03d2176cc3 EQUAL", "P2SH,WITNESS,MINIMALIF", "OK"], +["0x02 0x0100 0x03 0x635168", "HASH160 0x14 0xe7309652a8e3f600f06f5d8d52d6df03d2176cc3 EQUAL", "P2SH,WITNESS,MINIMALIF", "OK"], +["0 0x03 0x635168", "HASH160 0x14 0xe7309652a8e3f600f06f5d8d52d6df03d2176cc3 EQUAL", "P2SH,WITNESS,MINIMALIF", "EVAL_FALSE"], +["0x01 0x00 0x03 0x635168", "HASH160 0x14 0xe7309652a8e3f600f06f5d8d52d6df03d2176cc3 EQUAL", "P2SH,WITNESS,MINIMALIF", "EVAL_FALSE"], +["0x03 0x635168", "HASH160 0x14 0xe7309652a8e3f600f06f5d8d52d6df03d2176cc3 EQUAL", "P2SH,WITNESS,MINIMALIF", "UNBALANCED_CONDITIONAL"], +["Normal P2SH NOTIF 1 ENDIF"], +["1 0x03 0x645168", "HASH160 0x14 0x0c3f8fe3d6ca266e76311ecda544c67d15fdd5b0 EQUAL", "P2SH,WITNESS,MINIMALIF", "EVAL_FALSE"], +["2 0x03 0x645168", "HASH160 0x14 0x0c3f8fe3d6ca266e76311ecda544c67d15fdd5b0 EQUAL", "P2SH,WITNESS,MINIMALIF", "EVAL_FALSE"], +["0x02 0x0100 0x03 0x645168", "HASH160 0x14 0x0c3f8fe3d6ca266e76311ecda544c67d15fdd5b0 EQUAL", "P2SH,WITNESS,MINIMALIF", "EVAL_FALSE"], +["0 0x03 0x645168", "HASH160 0x14 0x0c3f8fe3d6ca266e76311ecda544c67d15fdd5b0 EQUAL", "P2SH,WITNESS,MINIMALIF", "OK"], +["0x01 0x00 0x03 0x645168", "HASH160 0x14 0x0c3f8fe3d6ca266e76311ecda544c67d15fdd5b0 EQUAL", "P2SH,WITNESS,MINIMALIF", "OK"], +["0x03 0x645168", "HASH160 0x14 0x0c3f8fe3d6ca266e76311ecda544c67d15fdd5b0 EQUAL", "P2SH,WITNESS,MINIMALIF", "UNBALANCED_CONDITIONAL"], +["P2WSH IF 1 ENDIF"], +[["01", "635168", 0.00000001], "", "0 0x20 0xc7eaf06d5ae01a58e376e126eb1e6fab2036076922b96b2711ffbec1e590665d", "P2SH,WITNESS", "OK"], +[["02", "635168", 0.00000001], "", "0 0x20 0xc7eaf06d5ae01a58e376e126eb1e6fab2036076922b96b2711ffbec1e590665d", "P2SH,WITNESS", "OK"], +[["0100", "635168", 0.00000001], "", "0 0x20 0xc7eaf06d5ae01a58e376e126eb1e6fab2036076922b96b2711ffbec1e590665d", "P2SH,WITNESS", "OK"], +[["", "635168", 0.00000001], "", "0 0x20 0xc7eaf06d5ae01a58e376e126eb1e6fab2036076922b96b2711ffbec1e590665d", "P2SH,WITNESS", "EVAL_FALSE"], +[["00", "635168", 0.00000001], "", "0 0x20 0xc7eaf06d5ae01a58e376e126eb1e6fab2036076922b96b2711ffbec1e590665d", "P2SH,WITNESS", "EVAL_FALSE"], +[["01", "635168", 0.00000001], "", "0 0x20 0xc7eaf06d5ae01a58e376e126eb1e6fab2036076922b96b2711ffbec1e590665d", "P2SH,WITNESS,MINIMALIF", "OK"], +[["02", "635168", 0.00000001], "", "0 0x20 0xc7eaf06d5ae01a58e376e126eb1e6fab2036076922b96b2711ffbec1e590665d", "P2SH,WITNESS,MINIMALIF", "MINIMALIF"], +[["0100", "635168", 0.00000001], "", "0 0x20 0xc7eaf06d5ae01a58e376e126eb1e6fab2036076922b96b2711ffbec1e590665d", "P2SH,WITNESS,MINIMALIF", "MINIMALIF"], +[["", "635168", 0.00000001], "", "0 0x20 0xc7eaf06d5ae01a58e376e126eb1e6fab2036076922b96b2711ffbec1e590665d", "P2SH,WITNESS,MINIMALIF", "EVAL_FALSE"], +[["00", "635168", 0.00000001], "", "0 0x20 0xc7eaf06d5ae01a58e376e126eb1e6fab2036076922b96b2711ffbec1e590665d", "P2SH,WITNESS,MINIMALIF", "MINIMALIF"], +[["635168", 0.00000001], "", "0 0x20 0xc7eaf06d5ae01a58e376e126eb1e6fab2036076922b96b2711ffbec1e590665d", "P2SH,WITNESS", "UNBALANCED_CONDITIONAL"], +[["635168", 0.00000001], "", "0 0x20 0xc7eaf06d5ae01a58e376e126eb1e6fab2036076922b96b2711ffbec1e590665d", "P2SH,WITNESS,MINIMALIF", "UNBALANCED_CONDITIONAL"], +["P2WSH NOTIF 1 ENDIF"], +[["01", "645168", 0.00000001], "", "0 0x20 0xf913eacf2e38a5d6fc3a8311d72ae704cb83866350a984dd3e5eb76d2a8c28e8", "P2SH,WITNESS", "EVAL_FALSE"], +[["02", "645168", 0.00000001], "", "0 0x20 0xf913eacf2e38a5d6fc3a8311d72ae704cb83866350a984dd3e5eb76d2a8c28e8", "P2SH,WITNESS", "EVAL_FALSE"], +[["0100", "645168", 0.00000001], "", "0 0x20 0xf913eacf2e38a5d6fc3a8311d72ae704cb83866350a984dd3e5eb76d2a8c28e8", "P2SH,WITNESS", "EVAL_FALSE"], +[["", "645168", 0.00000001], "", "0 0x20 0xf913eacf2e38a5d6fc3a8311d72ae704cb83866350a984dd3e5eb76d2a8c28e8", "P2SH,WITNESS", "OK"], +[["00", "645168", 0.00000001], "", "0 0x20 0xf913eacf2e38a5d6fc3a8311d72ae704cb83866350a984dd3e5eb76d2a8c28e8", "P2SH,WITNESS", "OK"], +[["01", "645168", 0.00000001], "", "0 0x20 0xf913eacf2e38a5d6fc3a8311d72ae704cb83866350a984dd3e5eb76d2a8c28e8", "P2SH,WITNESS,MINIMALIF", "EVAL_FALSE"], +[["02", "645168", 0.00000001], "", "0 0x20 0xf913eacf2e38a5d6fc3a8311d72ae704cb83866350a984dd3e5eb76d2a8c28e8", "P2SH,WITNESS,MINIMALIF", "MINIMALIF"], +[["0100", "645168", 0.00000001], "", "0 0x20 0xf913eacf2e38a5d6fc3a8311d72ae704cb83866350a984dd3e5eb76d2a8c28e8", "P2SH,WITNESS,MINIMALIF", "MINIMALIF"], +[["", "645168", 0.00000001], "", "0 0x20 0xf913eacf2e38a5d6fc3a8311d72ae704cb83866350a984dd3e5eb76d2a8c28e8", "P2SH,WITNESS,MINIMALIF", "OK"], +[["00", "645168", 0.00000001], "", "0 0x20 0xf913eacf2e38a5d6fc3a8311d72ae704cb83866350a984dd3e5eb76d2a8c28e8", "P2SH,WITNESS,MINIMALIF", "MINIMALIF"], +[["645168", 0.00000001], "", "0 0x20 0xf913eacf2e38a5d6fc3a8311d72ae704cb83866350a984dd3e5eb76d2a8c28e8", "P2SH,WITNESS", "UNBALANCED_CONDITIONAL"], +[["645168", 0.00000001], "", "0 0x20 0xf913eacf2e38a5d6fc3a8311d72ae704cb83866350a984dd3e5eb76d2a8c28e8", "P2SH,WITNESS,MINIMALIF", "UNBALANCED_CONDITIONAL"], + + + +["P2SH-P2WSH IF 1 ENDIF"], +[["01", "635168", 0.00000001], "0x22 0x0020c7eaf06d5ae01a58e376e126eb1e6fab2036076922b96b2711ffbec1e590665d", "HASH160 0x14 0x9b27ee6d9010c21bf837b334d043be5d150e7ba7 EQUAL", "P2SH,WITNESS", "OK"], +[["02", "635168", 0.00000001], "0x22 0x0020c7eaf06d5ae01a58e376e126eb1e6fab2036076922b96b2711ffbec1e590665d", "HASH160 0x14 0x9b27ee6d9010c21bf837b334d043be5d150e7ba7 EQUAL", "P2SH,WITNESS", "OK"], +[["0100", "635168", 0.00000001], "0x22 0x0020c7eaf06d5ae01a58e376e126eb1e6fab2036076922b96b2711ffbec1e590665d", "HASH160 0x14 0x9b27ee6d9010c21bf837b334d043be5d150e7ba7 EQUAL", "P2SH,WITNESS", "OK"], +[["", "635168", 0.00000001], "0x22 0x0020c7eaf06d5ae01a58e376e126eb1e6fab2036076922b96b2711ffbec1e590665d", "HASH160 0x14 0x9b27ee6d9010c21bf837b334d043be5d150e7ba7 EQUAL", "P2SH,WITNESS", "EVAL_FALSE"], +[["00", "635168", 0.00000001], "0x22 0x0020c7eaf06d5ae01a58e376e126eb1e6fab2036076922b96b2711ffbec1e590665d", "HASH160 0x14 0x9b27ee6d9010c21bf837b334d043be5d150e7ba7 EQUAL", "P2SH,WITNESS", "EVAL_FALSE"], +[["01", "635168", 0.00000001], "0x22 0x0020c7eaf06d5ae01a58e376e126eb1e6fab2036076922b96b2711ffbec1e590665d", "HASH160 0x14 0x9b27ee6d9010c21bf837b334d043be5d150e7ba7 EQUAL", "P2SH,WITNESS,MINIMALIF", "OK"], +[["02", "635168", 0.00000001], "0x22 0x0020c7eaf06d5ae01a58e376e126eb1e6fab2036076922b96b2711ffbec1e590665d", "HASH160 0x14 0x9b27ee6d9010c21bf837b334d043be5d150e7ba7 EQUAL", "P2SH,WITNESS,MINIMALIF", "MINIMALIF"], +[["0100", "635168", 0.00000001], "0x22 0x0020c7eaf06d5ae01a58e376e126eb1e6fab2036076922b96b2711ffbec1e590665d", "HASH160 0x14 0x9b27ee6d9010c21bf837b334d043be5d150e7ba7 EQUAL", "P2SH,WITNESS,MINIMALIF", "MINIMALIF"], +[["", "635168", 0.00000001], "0x22 0x0020c7eaf06d5ae01a58e376e126eb1e6fab2036076922b96b2711ffbec1e590665d", "HASH160 0x14 0x9b27ee6d9010c21bf837b334d043be5d150e7ba7 EQUAL", "P2SH,WITNESS,MINIMALIF", "EVAL_FALSE"], +[["00", "635168", 0.00000001], "0x22 0x0020c7eaf06d5ae01a58e376e126eb1e6fab2036076922b96b2711ffbec1e590665d", "HASH160 0x14 0x9b27ee6d9010c21bf837b334d043be5d150e7ba7 EQUAL", "P2SH,WITNESS,MINIMALIF", "MINIMALIF"], +[["635168", 0.00000001], "0x22 0x0020c7eaf06d5ae01a58e376e126eb1e6fab2036076922b96b2711ffbec1e590665d", "HASH160 0x14 0x9b27ee6d9010c21bf837b334d043be5d150e7ba7 EQUAL", "P2SH,WITNESS", "UNBALANCED_CONDITIONAL"], +[["635168", 0.00000001], "0x22 0x0020c7eaf06d5ae01a58e376e126eb1e6fab2036076922b96b2711ffbec1e590665d", "HASH160 0x14 0x9b27ee6d9010c21bf837b334d043be5d150e7ba7 EQUAL", "P2SH,WITNESS,MINIMALIF", "UNBALANCED_CONDITIONAL"], +["P2SH-P2WSH NOTIF 1 ENDIF"], +[["01", "645168", 0.00000001], "0x22 0x0020f913eacf2e38a5d6fc3a8311d72ae704cb83866350a984dd3e5eb76d2a8c28e8", "HASH160 0x14 0xdbb7d1c0a56b7a9c423300c8cca6e6e065baf1dc EQUAL", "P2SH,WITNESS", "EVAL_FALSE"], +[["02", "645168", 0.00000001], "0x22 0x0020f913eacf2e38a5d6fc3a8311d72ae704cb83866350a984dd3e5eb76d2a8c28e8", "HASH160 0x14 0xdbb7d1c0a56b7a9c423300c8cca6e6e065baf1dc EQUAL", "P2SH,WITNESS", "EVAL_FALSE"], +[["0100", "645168", 0.00000001], "0x22 0x0020f913eacf2e38a5d6fc3a8311d72ae704cb83866350a984dd3e5eb76d2a8c28e8", "HASH160 0x14 0xdbb7d1c0a56b7a9c423300c8cca6e6e065baf1dc EQUAL", "P2SH,WITNESS", "EVAL_FALSE"], +[["", "645168", 0.00000001], "0x22 0x0020f913eacf2e38a5d6fc3a8311d72ae704cb83866350a984dd3e5eb76d2a8c28e8", "HASH160 0x14 0xdbb7d1c0a56b7a9c423300c8cca6e6e065baf1dc EQUAL", "P2SH,WITNESS", "OK"], +[["00", "645168", 0.00000001], "0x22 0x0020f913eacf2e38a5d6fc3a8311d72ae704cb83866350a984dd3e5eb76d2a8c28e8", "HASH160 0x14 0xdbb7d1c0a56b7a9c423300c8cca6e6e065baf1dc EQUAL", "P2SH,WITNESS", "OK"], +[["01", "645168", 0.00000001], "0x22 0x0020f913eacf2e38a5d6fc3a8311d72ae704cb83866350a984dd3e5eb76d2a8c28e8", "HASH160 0x14 0xdbb7d1c0a56b7a9c423300c8cca6e6e065baf1dc EQUAL", "P2SH,WITNESS,MINIMALIF", "EVAL_FALSE"], +[["02", "645168", 0.00000001], "0x22 0x0020f913eacf2e38a5d6fc3a8311d72ae704cb83866350a984dd3e5eb76d2a8c28e8", "HASH160 0x14 0xdbb7d1c0a56b7a9c423300c8cca6e6e065baf1dc EQUAL", "P2SH,WITNESS,MINIMALIF", "MINIMALIF"], +[["0100", "645168", 0.00000001], "0x22 0x0020f913eacf2e38a5d6fc3a8311d72ae704cb83866350a984dd3e5eb76d2a8c28e8", "HASH160 0x14 0xdbb7d1c0a56b7a9c423300c8cca6e6e065baf1dc EQUAL", "P2SH,WITNESS,MINIMALIF", "MINIMALIF"], +[["", "645168", 0.00000001], "0x22 0x0020f913eacf2e38a5d6fc3a8311d72ae704cb83866350a984dd3e5eb76d2a8c28e8", "HASH160 0x14 0xdbb7d1c0a56b7a9c423300c8cca6e6e065baf1dc EQUAL", "P2SH,WITNESS,MINIMALIF", "OK"], +[["00", "645168", 0.00000001], "0x22 0x0020f913eacf2e38a5d6fc3a8311d72ae704cb83866350a984dd3e5eb76d2a8c28e8", "HASH160 0x14 0xdbb7d1c0a56b7a9c423300c8cca6e6e065baf1dc EQUAL", "P2SH,WITNESS,MINIMALIF", "MINIMALIF"], +[["645168", 0.00000001], "0x22 0x0020f913eacf2e38a5d6fc3a8311d72ae704cb83866350a984dd3e5eb76d2a8c28e8", "HASH160 0x14 0xdbb7d1c0a56b7a9c423300c8cca6e6e065baf1dc EQUAL", "P2SH,WITNESS", "UNBALANCED_CONDITIONAL"], +[["645168", 0.00000001], "0x22 0x0020f913eacf2e38a5d6fc3a8311d72ae704cb83866350a984dd3e5eb76d2a8c28e8", "HASH160 0x14 0xdbb7d1c0a56b7a9c423300c8cca6e6e065baf1dc EQUAL", "P2SH,WITNESS,MINIMALIF", "UNBALANCED_CONDITIONAL"], + +["NULLFAIL should cover all signatures and signatures only"], +["0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0", "0x01 0x14 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0x01 0x14 CHECKMULTISIG NOT", "DERSIG", "OK", "BIP66 and NULLFAIL-compliant"], +["0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0", "0x01 0x14 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0x01 0x14 CHECKMULTISIG NOT", "DERSIG,NULLFAIL", "OK", "BIP66 and NULLFAIL-compliant"], +["1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0", "0x01 0x14 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0x01 0x14 CHECKMULTISIG NOT", "DERSIG,NULLFAIL", "OK", "BIP66 and NULLFAIL-compliant, not NULLDUMMY-compliant"], +["1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0", "0x01 0x14 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0x01 0x14 CHECKMULTISIG NOT", "DERSIG,NULLFAIL,NULLDUMMY", "SIG_NULLDUMMY", "BIP66 and NULLFAIL-compliant, not NULLDUMMY-compliant"], +["0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0x09 0x300602010102010101", "0x01 0x14 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0x01 0x14 CHECKMULTISIG NOT", "DERSIG", "OK", "BIP66-compliant but not NULLFAIL-compliant"], +["0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0x09 0x300602010102010101", "0x01 0x14 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0x01 0x14 CHECKMULTISIG NOT", "DERSIG,NULLFAIL", "NULLFAIL", "BIP66-compliant but not NULLFAIL-compliant"], +["0 0x09 0x300602010102010101 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0", "0x01 0x14 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0x01 0x14 CHECKMULTISIG NOT", "DERSIG", "OK", "BIP66-compliant but not NULLFAIL-compliant"], +["0 0x09 0x300602010102010101 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0", "0x01 0x14 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0x01 0x14 CHECKMULTISIG NOT", "DERSIG,NULLFAIL", "NULLFAIL", "BIP66-compliant but not NULLFAIL-compliant"], + ["The End"] ] diff --git a/src/test/data/tt-delin1-out.json b/src/test/data/tt-delin1-out.json new file mode 100644 index 0000000000..2c7a68636a --- /dev/null +++ b/src/test/data/tt-delin1-out.json @@ -0,0 +1,216 @@ +{ + "txid": "81b2035be1da1abe745c6141174a73d151009ec17b3d5ebffa2e177408c50dfd", + "version": 1, + "locktime": 0, + "vin": [ + { + "txid": "27871a1a27d833e99cd392a502a647beaaeda6da535417501c76312d52235cfd", + "vout": 332, + "scriptSig": { + "asm": "3046022100b4251ecd63778a3dde0155abe4cd162947620ae9ee45a874353551092325b116022100db307baf4ff3781ec520bd18f387948cedd15dc27bafe17c894b0fe6ffffcafa[ALL] 03091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc", + "hex": "493046022100b4251ecd63778a3dde0155abe4cd162947620ae9ee45a874353551092325b116022100db307baf4ff3781ec520bd18f387948cedd15dc27bafe17c894b0fe6ffffcafa012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc" + }, + "sequence": 4294967295 + }, + { + "txid": "752f7f69b915637dc1c2f7aed1466ad676f6f3e24cf922809705f664e97ab3c1", + "vout": 1, + "scriptSig": { + "asm": "3044022079bd62ee09621a3be96b760c39e8ef78170101d46313923c6b07ae60a95c90670220238e51ea29fc70b04b65508450523caedbb11cb4dd5aa608c81487de798925ba[ALL] 027a759be8df971a6a04fafcb4f6babf75dc811c5cdaa0734cddbe9b942ce75b34", + "hex": "473044022079bd62ee09621a3be96b760c39e8ef78170101d46313923c6b07ae60a95c90670220238e51ea29fc70b04b65508450523caedbb11cb4dd5aa608c81487de798925ba0121027a759be8df971a6a04fafcb4f6babf75dc811c5cdaa0734cddbe9b942ce75b34" + }, + "sequence": 4294967295 + }, + { + "txid": "b0ac9cca2e69cd02410e31b1f4402a25758e71abd1ab06c265ef9077dc05d0ed", + "vout": 209, + "scriptSig": { + "asm": "304502207722d6f9038673c86a1019b1c4de2d687ae246477cd4ca7002762be0299de385022100e594a11e3a313942595f7666dcf7078bcb14f1330f4206b95c917e7ec0e82fac[ALL] 03091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc", + "hex": "48304502207722d6f9038673c86a1019b1c4de2d687ae246477cd4ca7002762be0299de385022100e594a11e3a313942595f7666dcf7078bcb14f1330f4206b95c917e7ec0e82fac012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc" + }, + "sequence": 4294967295 + }, + { + "txid": "a135eafb595eaf4c1ea59ccb111cdc0eae1b2c979b226a1e5aa8b76fe2d628df", + "vout": 0, + "scriptSig": { + "asm": "3045022100a63a4788027b79b65c6f9d9e054f68cf3b4eed19efd82a2d53f70dcbe64683390220526f243671425b2bd05745fcf2729361f985cfe84ea80c7cfc817b93d8134374[ALL] 03a621f08be22d1bbdcbe4e527ee4927006aa555fc65e2aafa767d4ea2fe9dfa52", + "hex": "483045022100a63a4788027b79b65c6f9d9e054f68cf3b4eed19efd82a2d53f70dcbe64683390220526f243671425b2bd05745fcf2729361f985cfe84ea80c7cfc817b93d8134374012103a621f08be22d1bbdcbe4e527ee4927006aa555fc65e2aafa767d4ea2fe9dfa52" + }, + "sequence": 4294967295 + }, + { + "txid": "a5d6bf53ba21140b8a4d554feb00fe8bb9a62430ff9e4624aa2f58a120232aae", + "vout": 1, + "scriptSig": { + "asm": "3046022100b200ac6db16842f76dab9abe807ce423c992805879bc50abd46ed8275a59d9cf022100c0d518e85dd345b3c29dd4dc47b9a420d3ce817b18720e94966d2fe23413a408[ALL] 03091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc", + "hex": "493046022100b200ac6db16842f76dab9abe807ce423c992805879bc50abd46ed8275a59d9cf022100c0d518e85dd345b3c29dd4dc47b9a420d3ce817b18720e94966d2fe23413a408012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc" + }, + "sequence": 4294967295 + }, + { + "txid": "1b299cf14f1a22e81ea56d71b7affbd7cf386807bf2b4d4b79a18a54125accb3", + "vout": 0, + "scriptSig": { + "asm": "3045022100ededc441c3103a6f2bd6cab7639421af0f6ec5e60503bce1e603cf34f00aee1c02205cb75f3f519a13fb348783b21db3085cb5ec7552c59e394fdbc3e1feea43f967[ALL] 03a621f08be22d1bbdcbe4e527ee4927006aa555fc65e2aafa767d4ea2fe9dfa52", + "hex": "483045022100ededc441c3103a6f2bd6cab7639421af0f6ec5e60503bce1e603cf34f00aee1c02205cb75f3f519a13fb348783b21db3085cb5ec7552c59e394fdbc3e1feea43f967012103a621f08be22d1bbdcbe4e527ee4927006aa555fc65e2aafa767d4ea2fe9dfa52" + }, + "sequence": 4294967295 + }, + { + "txid": "071df1cdcb3f0070f9d6af7b0274f02d0be2324a274727cfd288383167531485", + "vout": 21, + "scriptSig": { + "asm": "3045022100d9eed5413d2a4b4b98625aa6e3169edc4fb4663e7862316d69224454e70cd8ca022061e506521d5ced51dd0ea36496e75904d756a4c4f9fb111568555075d5f68d9a[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", + "hex": "483045022100d9eed5413d2a4b4b98625aa6e3169edc4fb4663e7862316d69224454e70cd8ca022061e506521d5ced51dd0ea36496e75904d756a4c4f9fb111568555075d5f68d9a012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" + }, + "sequence": 4294967295 + }, + { + "txid": "b012e500eb7adf7a13ed332dd6ece849f94f7a62bb3eac5babab356d1fc19282", + "vout": 9, + "scriptSig": { + "asm": "304502207e84b27139c4c19c828cb1e30c349bba88e4d9b59be97286960793b5ddc0a2af0221008cdc7a951e7f31c20953ed5635fbabf228e80b7047f32faaa0313e7693005177[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", + "hex": "48304502207e84b27139c4c19c828cb1e30c349bba88e4d9b59be97286960793b5ddc0a2af0221008cdc7a951e7f31c20953ed5635fbabf228e80b7047f32faaa0313e7693005177012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" + }, + "sequence": 4294967295 + }, + { + "txid": "58840fee9c833f2f2d40575842f30f4b8d2553094d06ad88b03d06869acf3d88", + "vout": 30, + "scriptSig": { + "asm": "30440220426540dfed9c4ab5812e5f06df705b8bcf307dd7d20f7fa6512298b2a6314f420220064055096e3ca62f6c7352c66a5447767c53f946acdf35025ab3807ddb2fa404[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", + "hex": "4730440220426540dfed9c4ab5812e5f06df705b8bcf307dd7d20f7fa6512298b2a6314f420220064055096e3ca62f6c7352c66a5447767c53f946acdf35025ab3807ddb2fa404012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" + }, + "sequence": 4294967295 + }, + { + "txid": "e69f9cd16946e570a665245354428a3f507ea69f4568b581e4af98edb3db9766", + "vout": 114, + "scriptSig": { + "asm": "304402200a5e673996f2fc88e21cc8613611f08a650bc0370338803591d85d0ec5663764022040b6664a0d1ec83a7f01975b8fde5232992b8ca58bf48af6725d2f92a936ab2e[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", + "hex": "47304402200a5e673996f2fc88e21cc8613611f08a650bc0370338803591d85d0ec5663764022040b6664a0d1ec83a7f01975b8fde5232992b8ca58bf48af6725d2f92a936ab2e012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" + }, + "sequence": 4294967295 + }, + { + "txid": "595d1257f654ed2cbe5a65421e8aefd2b4d70b5b6c89a03f1d7e518221fc3f02", + "vout": 103, + "scriptSig": { + "asm": "3046022100d93b30219c5735f673be5c3b4688366d96f545561c74cb62c6958c00f6960806022100ec8200adcb028f2184fa2a4f6faac7f8bb57cb4503bb7584ac11051fece31b3d[ALL] 03091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc", + "hex": "493046022100d93b30219c5735f673be5c3b4688366d96f545561c74cb62c6958c00f6960806022100ec8200adcb028f2184fa2a4f6faac7f8bb57cb4503bb7584ac11051fece31b3d012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc" + }, + "sequence": 4294967295 + }, + { + "txid": "06fc818f9555a261248ecd7aad0993eafb5a82ceb2b5c87c3ddfb06671c7f816", + "vout": 1, + "scriptSig": { + "asm": "3045022100a13934e68d3f5b22b130c4cb33f4da468cffc52323a47fbfbe06b64858162246022047081e0a70ff770e64a2e2d31e5d520d9102268b57a47009a72fe73ec7669018[ALL] 0234b9d9413f247bb78cd3293b7b65a2c38018ba5621ea9ee737f3a6a3523fb4cd", + "hex": "483045022100a13934e68d3f5b22b130c4cb33f4da468cffc52323a47fbfbe06b64858162246022047081e0a70ff770e64a2e2d31e5d520d9102268b57a47009a72fe73ec766901801210234b9d9413f247bb78cd3293b7b65a2c38018ba5621ea9ee737f3a6a3523fb4cd" + }, + "sequence": 4294967295 + }, + { + "txid": "fb416c8155d6bb1d43f9395466ca90a638a7c2dd3ff617aadf3a7ac8f3967b19", + "vout": 0, + "scriptSig": { + "asm": "304602210097f1f35d5bdc1a3a60390a1b015b8e7c4f916aa3847aafd969e04975e15bbe70022100a9052eb25517d481f1fda1b129eb1b534da50ea1a51f3ee012dca3601c11b86a[ALL] 027a759be8df971a6a04fafcb4f6babf75dc811c5cdaa0734cddbe9b942ce75b34", + "hex": "49304602210097f1f35d5bdc1a3a60390a1b015b8e7c4f916aa3847aafd969e04975e15bbe70022100a9052eb25517d481f1fda1b129eb1b534da50ea1a51f3ee012dca3601c11b86a0121027a759be8df971a6a04fafcb4f6babf75dc811c5cdaa0734cddbe9b942ce75b34" + }, + "sequence": 4294967295 + }, + { + "txid": "3940b9683bd6104ad24c978e640ba4095993cafdb27d2ed91baa27ee61a2d920", + "vout": 221, + "scriptSig": { + "asm": "3045022012b3138c591bf7154b6fef457f2c4a3c7162225003788ac0024a99355865ff13022100b71b125ae1ffb2e1d1571f580cd3ebc8cd049a2d7a8a41f138ba94aeb982106f[ALL] 03091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc", + "hex": "483045022012b3138c591bf7154b6fef457f2c4a3c7162225003788ac0024a99355865ff13022100b71b125ae1ffb2e1d1571f580cd3ebc8cd049a2d7a8a41f138ba94aeb982106f012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc" + }, + "sequence": 4294967295 + }, + { + "txid": "711b5714d3b5136147c02194cd95bde94a4648c4263ca6f972d86cd1d579f150", + "vout": 1, + "scriptSig": { + "asm": "3045022100f834ccc8b22ee72712a3e5e6ef4acb8b2fb791b5385b70e2cd4332674d6667f4022024fbda0a997e0c253503f217501f508a4d56edce2c813ecdd9ad796dbeba9074[ALL] 0234b9d9413f247bb78cd3293b7b65a2c38018ba5621ea9ee737f3a6a3523fb4cd", + "hex": "483045022100f834ccc8b22ee72712a3e5e6ef4acb8b2fb791b5385b70e2cd4332674d6667f4022024fbda0a997e0c253503f217501f508a4d56edce2c813ecdd9ad796dbeba907401210234b9d9413f247bb78cd3293b7b65a2c38018ba5621ea9ee737f3a6a3523fb4cd" + }, + "sequence": 4294967295 + }, + { + "txid": "6364b5c5efe018430789e7fb4e338209546cae5d9c5f5e300aac68155d861b55", + "vout": 27, + "scriptSig": { + "asm": "304502203b2fd1e39ae0e469d7a15768f262661b0de41470daf0fe8c4fd0c26542a0870002210081c57e331f9a2d214457d953e3542904727ee412c63028113635d7224da3dccc[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", + "hex": "48304502203b2fd1e39ae0e469d7a15768f262661b0de41470daf0fe8c4fd0c26542a0870002210081c57e331f9a2d214457d953e3542904727ee412c63028113635d7224da3dccc012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" + }, + "sequence": 4294967295 + }, + { + "txid": "0bb57f6e38012c86d4c5a28c904f2675082859147921a707d48961015a3e5057", + "vout": 1095, + "scriptSig": { + "asm": "304502206947a9c54f0664ece4430fd4ae999891dc50bb6126bc36b6a15a3189f29d25e9022100a86cfc4e2fdd9e39a20e305cfd1b76509c67b3e313e0f118229105caa0e823c9[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", + "hex": "48304502206947a9c54f0664ece4430fd4ae999891dc50bb6126bc36b6a15a3189f29d25e9022100a86cfc4e2fdd9e39a20e305cfd1b76509c67b3e313e0f118229105caa0e823c9012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" + }, + "sequence": 4294967295 + }, + { + "txid": "9b34274814a2540bb062107117f8f3e75ef85d953e9372d8261a3e9dfbc1163f", + "vout": 37, + "scriptSig": { + "asm": "3045022100c7128fe10b2d38744ae8177776054c29fc8ec13f07207723e70766ab7164847402201d2cf09009b9596de74c0183d1ab832e5edddb7a9965880bb400097e850850f8[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", + "hex": "483045022100c7128fe10b2d38744ae8177776054c29fc8ec13f07207723e70766ab7164847402201d2cf09009b9596de74c0183d1ab832e5edddb7a9965880bb400097e850850f8012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" + }, + "sequence": 4294967295 + }, + { + "txid": "b86b5cc0d8a7374d94e277850b0a249cb26a7b42ddf014f28a49b8859da64241", + "vout": 20, + "scriptSig": { + "asm": "304502203b89a71628a28cc3703d170ca3be77786cff6b867e38a18b719705f8a326578f022100b2a9879e1acf621faa6466c207746a7f3eb4c8514c1482969aba3f2a957f1321[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", + "hex": "48304502203b89a71628a28cc3703d170ca3be77786cff6b867e38a18b719705f8a326578f022100b2a9879e1acf621faa6466c207746a7f3eb4c8514c1482969aba3f2a957f1321012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" + }, + "sequence": 4294967295 + }, + { + "txid": "3d0a2353eeec44d3c10aed259038db321912122cd4150048f7bfa4c0ecfee236", + "vout": 242, + "scriptSig": { + "asm": "3046022100ef794a8ef7fd6752d2a183c18866ff6e8dc0f5bd889a63e2c21cf303a6302461022100c1b09662d9e92988c3f9fcf17d1bcc79b5403647095d7212b9f8a1278a532d68[ALL] 03091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc", + "hex": "493046022100ef794a8ef7fd6752d2a183c18866ff6e8dc0f5bd889a63e2c21cf303a6302461022100c1b09662d9e92988c3f9fcf17d1bcc79b5403647095d7212b9f8a1278a532d68012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc" + }, + "sequence": 4294967295 + } + ], + "vout": [ + { + "value": 1.3782, + "n": 0, + "scriptPubKey": { + "asm": "OP_DUP OP_HASH160 8fd139bb39ced713f231c58a4d07bf6954d1c201 OP_EQUALVERIFY OP_CHECKSIG", + "hex": "76a9148fd139bb39ced713f231c58a4d07bf6954d1c20188ac", + "reqSigs": 1, + "type": "pubkeyhash", + "addresses": [ + "1E7SGgAZFCHDnVZLuRViX3gUmxpMfdvd2o" + ] + } + }, + { + "value": 0.01000001, + "n": 1, + "scriptPubKey": { + "asm": "OP_DUP OP_HASH160 6c772e9cf96371bba3da8cb733da70a2fcf20078 OP_EQUALVERIFY OP_CHECKSIG", + "hex": "76a9146c772e9cf96371bba3da8cb733da70a2fcf2007888ac", + "reqSigs": 1, + "type": "pubkeyhash", + "addresses": [ + "1AtWkdmfmYkErU16d3KYykJUbEp9MAj9Sb" + ] + } + } + ], + "hex": "0100000014fd5c23522d31761c50175453daa6edaabe47a602a592d39ce933d8271a1a87274c0100006c493046022100b4251ecd63778a3dde0155abe4cd162947620ae9ee45a874353551092325b116022100db307baf4ff3781ec520bd18f387948cedd15dc27bafe17c894b0fe6ffffcafa012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adcffffffffc1b37ae964f605978022f94ce2f3f676d66a46d1aef7c2c17d6315b9697f2f75010000006a473044022079bd62ee09621a3be96b760c39e8ef78170101d46313923c6b07ae60a95c90670220238e51ea29fc70b04b65508450523caedbb11cb4dd5aa608c81487de798925ba0121027a759be8df971a6a04fafcb4f6babf75dc811c5cdaa0734cddbe9b942ce75b34ffffffffedd005dc7790ef65c206abd1ab718e75252a40f4b1310e4102cd692eca9cacb0d10000006b48304502207722d6f9038673c86a1019b1c4de2d687ae246477cd4ca7002762be0299de385022100e594a11e3a313942595f7666dcf7078bcb14f1330f4206b95c917e7ec0e82fac012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adcffffffffdf28d6e26fb7a85a1e6a229b972c1bae0edc1c11cb9ca51e4caf5e59fbea35a1000000006b483045022100a63a4788027b79b65c6f9d9e054f68cf3b4eed19efd82a2d53f70dcbe64683390220526f243671425b2bd05745fcf2729361f985cfe84ea80c7cfc817b93d8134374012103a621f08be22d1bbdcbe4e527ee4927006aa555fc65e2aafa767d4ea2fe9dfa52ffffffffae2a2320a1582faa24469eff3024a6b98bfe00eb4f554d8a0b1421ba53bfd6a5010000006c493046022100b200ac6db16842f76dab9abe807ce423c992805879bc50abd46ed8275a59d9cf022100c0d518e85dd345b3c29dd4dc47b9a420d3ce817b18720e94966d2fe23413a408012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adcffffffffb3cc5a12548aa1794b4d2bbf076838cfd7fbafb7716da51ee8221a4ff19c291b000000006b483045022100ededc441c3103a6f2bd6cab7639421af0f6ec5e60503bce1e603cf34f00aee1c02205cb75f3f519a13fb348783b21db3085cb5ec7552c59e394fdbc3e1feea43f967012103a621f08be22d1bbdcbe4e527ee4927006aa555fc65e2aafa767d4ea2fe9dfa52ffffffff85145367313888d2cf2747274a32e20b2df074027bafd6f970003fcbcdf11d07150000006b483045022100d9eed5413d2a4b4b98625aa6e3169edc4fb4663e7862316d69224454e70cd8ca022061e506521d5ced51dd0ea36496e75904d756a4c4f9fb111568555075d5f68d9a012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff8292c11f6d35abab5bac3ebb627a4ff949e8ecd62d33ed137adf7aeb00e512b0090000006b48304502207e84b27139c4c19c828cb1e30c349bba88e4d9b59be97286960793b5ddc0a2af0221008cdc7a951e7f31c20953ed5635fbabf228e80b7047f32faaa0313e7693005177012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff883dcf9a86063db088ad064d0953258d4b0ff3425857402d2f3f839cee0f84581e0000006a4730440220426540dfed9c4ab5812e5f06df705b8bcf307dd7d20f7fa6512298b2a6314f420220064055096e3ca62f6c7352c66a5447767c53f946acdf35025ab3807ddb2fa404012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff6697dbb3ed98afe481b568459fa67e503f8a4254532465a670e54669d19c9fe6720000006a47304402200a5e673996f2fc88e21cc8613611f08a650bc0370338803591d85d0ec5663764022040b6664a0d1ec83a7f01975b8fde5232992b8ca58bf48af6725d2f92a936ab2e012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff023ffc2182517e1d3fa0896c5b0bd7b4d2ef8a1e42655abe2ced54f657125d59670000006c493046022100d93b30219c5735f673be5c3b4688366d96f545561c74cb62c6958c00f6960806022100ec8200adcb028f2184fa2a4f6faac7f8bb57cb4503bb7584ac11051fece31b3d012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adcffffffff16f8c77166b0df3d7cc8b5b2ce825afbea9309ad7acd8e2461a255958f81fc06010000006b483045022100a13934e68d3f5b22b130c4cb33f4da468cffc52323a47fbfbe06b64858162246022047081e0a70ff770e64a2e2d31e5d520d9102268b57a47009a72fe73ec766901801210234b9d9413f247bb78cd3293b7b65a2c38018ba5621ea9ee737f3a6a3523fb4cdffffffff197b96f3c87a3adfaa17f63fddc2a738a690ca665439f9431dbbd655816c41fb000000006c49304602210097f1f35d5bdc1a3a60390a1b015b8e7c4f916aa3847aafd969e04975e15bbe70022100a9052eb25517d481f1fda1b129eb1b534da50ea1a51f3ee012dca3601c11b86a0121027a759be8df971a6a04fafcb4f6babf75dc811c5cdaa0734cddbe9b942ce75b34ffffffff20d9a261ee27aa1bd92e7db2fdca935909a40b648e974cd24a10d63b68b94039dd0000006b483045022012b3138c591bf7154b6fef457f2c4a3c7162225003788ac0024a99355865ff13022100b71b125ae1ffb2e1d1571f580cd3ebc8cd049a2d7a8a41f138ba94aeb982106f012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adcffffffff50f179d5d16cd872f9a63c26c448464ae9bd95cd9421c0476113b5d314571b71010000006b483045022100f834ccc8b22ee72712a3e5e6ef4acb8b2fb791b5385b70e2cd4332674d6667f4022024fbda0a997e0c253503f217501f508a4d56edce2c813ecdd9ad796dbeba907401210234b9d9413f247bb78cd3293b7b65a2c38018ba5621ea9ee737f3a6a3523fb4cdffffffff551b865d1568ac0a305e5f9c5dae6c540982334efbe789074318e0efc5b564631b0000006b48304502203b2fd1e39ae0e469d7a15768f262661b0de41470daf0fe8c4fd0c26542a0870002210081c57e331f9a2d214457d953e3542904727ee412c63028113635d7224da3dccc012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff57503e5a016189d407a721791459280875264f908ca2c5d4862c01386e7fb50b470400006b48304502206947a9c54f0664ece4430fd4ae999891dc50bb6126bc36b6a15a3189f29d25e9022100a86cfc4e2fdd9e39a20e305cfd1b76509c67b3e313e0f118229105caa0e823c9012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff3f16c1fb9d3e1a26d872933e955df85ee7f3f817711062b00b54a2144827349b250000006b483045022100c7128fe10b2d38744ae8177776054c29fc8ec13f07207723e70766ab7164847402201d2cf09009b9596de74c0183d1ab832e5edddb7a9965880bb400097e850850f8012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff4142a69d85b8498af214f0dd427b6ab29c240a0b8577e2944d37a7d8c05c6bb8140000006b48304502203b89a71628a28cc3703d170ca3be77786cff6b867e38a18b719705f8a326578f022100b2a9879e1acf621faa6466c207746a7f3eb4c8514c1482969aba3f2a957f1321012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff36e2feecc0a4bff7480015d42c12121932db389025ed0ac1d344ecee53230a3df20000006c493046022100ef794a8ef7fd6752d2a183c18866ff6e8dc0f5bd889a63e2c21cf303a6302461022100c1b09662d9e92988c3f9fcf17d1bcc79b5403647095d7212b9f8a1278a532d68012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adcffffffff0260f73608000000001976a9148fd139bb39ced713f231c58a4d07bf6954d1c20188ac41420f00000000001976a9146c772e9cf96371bba3da8cb733da70a2fcf2007888ac00000000" +} diff --git a/src/test/data/tt-delout1-out.json b/src/test/data/tt-delout1-out.json new file mode 100644 index 0000000000..9cf8cbb16c --- /dev/null +++ b/src/test/data/tt-delout1-out.json @@ -0,0 +1,212 @@ +{ + "txid": "c46ccd75b5050e942b2e86a3648f843f525fe6fc000bf0534ba5973063354493", + "version": 1, + "locktime": 0, + "vin": [ + { + "txid": "27871a1a27d833e99cd392a502a647beaaeda6da535417501c76312d52235cfd", + "vout": 332, + "scriptSig": { + "asm": "3046022100b4251ecd63778a3dde0155abe4cd162947620ae9ee45a874353551092325b116022100db307baf4ff3781ec520bd18f387948cedd15dc27bafe17c894b0fe6ffffcafa[ALL] 03091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc", + "hex": "493046022100b4251ecd63778a3dde0155abe4cd162947620ae9ee45a874353551092325b116022100db307baf4ff3781ec520bd18f387948cedd15dc27bafe17c894b0fe6ffffcafa012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc" + }, + "sequence": 4294967295 + }, + { + "txid": "a72ec96bd0d022d1b0c2f9078cdd46b3725b8eecdd001e17b21e3ababad14ecb", + "vout": 0, + "scriptSig": { + "asm": "3046022100a9b617843b68c284715d3e02fd120479cd0d96a6c43bf01e697fb0a460a21a3a022100ba0a12fbe8b993d4e7911fa3467615765dbe421ddf5c51b57a9c1ee19dcc00ba[ALL] 03e633b4fa4ceb705c2da712390767199be8ef2448b3095dc01652e11b2b751505", + "hex": "493046022100a9b617843b68c284715d3e02fd120479cd0d96a6c43bf01e697fb0a460a21a3a022100ba0a12fbe8b993d4e7911fa3467615765dbe421ddf5c51b57a9c1ee19dcc00ba012103e633b4fa4ceb705c2da712390767199be8ef2448b3095dc01652e11b2b751505" + }, + "sequence": 4294967295 + }, + { + "txid": "752f7f69b915637dc1c2f7aed1466ad676f6f3e24cf922809705f664e97ab3c1", + "vout": 1, + "scriptSig": { + "asm": "3044022079bd62ee09621a3be96b760c39e8ef78170101d46313923c6b07ae60a95c90670220238e51ea29fc70b04b65508450523caedbb11cb4dd5aa608c81487de798925ba[ALL] 027a759be8df971a6a04fafcb4f6babf75dc811c5cdaa0734cddbe9b942ce75b34", + "hex": "473044022079bd62ee09621a3be96b760c39e8ef78170101d46313923c6b07ae60a95c90670220238e51ea29fc70b04b65508450523caedbb11cb4dd5aa608c81487de798925ba0121027a759be8df971a6a04fafcb4f6babf75dc811c5cdaa0734cddbe9b942ce75b34" + }, + "sequence": 4294967295 + }, + { + "txid": "b0ac9cca2e69cd02410e31b1f4402a25758e71abd1ab06c265ef9077dc05d0ed", + "vout": 209, + "scriptSig": { + "asm": "304502207722d6f9038673c86a1019b1c4de2d687ae246477cd4ca7002762be0299de385022100e594a11e3a313942595f7666dcf7078bcb14f1330f4206b95c917e7ec0e82fac[ALL] 03091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc", + "hex": "48304502207722d6f9038673c86a1019b1c4de2d687ae246477cd4ca7002762be0299de385022100e594a11e3a313942595f7666dcf7078bcb14f1330f4206b95c917e7ec0e82fac012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc" + }, + "sequence": 4294967295 + }, + { + "txid": "a135eafb595eaf4c1ea59ccb111cdc0eae1b2c979b226a1e5aa8b76fe2d628df", + "vout": 0, + "scriptSig": { + "asm": "3045022100a63a4788027b79b65c6f9d9e054f68cf3b4eed19efd82a2d53f70dcbe64683390220526f243671425b2bd05745fcf2729361f985cfe84ea80c7cfc817b93d8134374[ALL] 03a621f08be22d1bbdcbe4e527ee4927006aa555fc65e2aafa767d4ea2fe9dfa52", + "hex": "483045022100a63a4788027b79b65c6f9d9e054f68cf3b4eed19efd82a2d53f70dcbe64683390220526f243671425b2bd05745fcf2729361f985cfe84ea80c7cfc817b93d8134374012103a621f08be22d1bbdcbe4e527ee4927006aa555fc65e2aafa767d4ea2fe9dfa52" + }, + "sequence": 4294967295 + }, + { + "txid": "a5d6bf53ba21140b8a4d554feb00fe8bb9a62430ff9e4624aa2f58a120232aae", + "vout": 1, + "scriptSig": { + "asm": "3046022100b200ac6db16842f76dab9abe807ce423c992805879bc50abd46ed8275a59d9cf022100c0d518e85dd345b3c29dd4dc47b9a420d3ce817b18720e94966d2fe23413a408[ALL] 03091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc", + "hex": "493046022100b200ac6db16842f76dab9abe807ce423c992805879bc50abd46ed8275a59d9cf022100c0d518e85dd345b3c29dd4dc47b9a420d3ce817b18720e94966d2fe23413a408012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc" + }, + "sequence": 4294967295 + }, + { + "txid": "1b299cf14f1a22e81ea56d71b7affbd7cf386807bf2b4d4b79a18a54125accb3", + "vout": 0, + "scriptSig": { + "asm": "3045022100ededc441c3103a6f2bd6cab7639421af0f6ec5e60503bce1e603cf34f00aee1c02205cb75f3f519a13fb348783b21db3085cb5ec7552c59e394fdbc3e1feea43f967[ALL] 03a621f08be22d1bbdcbe4e527ee4927006aa555fc65e2aafa767d4ea2fe9dfa52", + "hex": "483045022100ededc441c3103a6f2bd6cab7639421af0f6ec5e60503bce1e603cf34f00aee1c02205cb75f3f519a13fb348783b21db3085cb5ec7552c59e394fdbc3e1feea43f967012103a621f08be22d1bbdcbe4e527ee4927006aa555fc65e2aafa767d4ea2fe9dfa52" + }, + "sequence": 4294967295 + }, + { + "txid": "071df1cdcb3f0070f9d6af7b0274f02d0be2324a274727cfd288383167531485", + "vout": 21, + "scriptSig": { + "asm": "3045022100d9eed5413d2a4b4b98625aa6e3169edc4fb4663e7862316d69224454e70cd8ca022061e506521d5ced51dd0ea36496e75904d756a4c4f9fb111568555075d5f68d9a[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", + "hex": "483045022100d9eed5413d2a4b4b98625aa6e3169edc4fb4663e7862316d69224454e70cd8ca022061e506521d5ced51dd0ea36496e75904d756a4c4f9fb111568555075d5f68d9a012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" + }, + "sequence": 4294967295 + }, + { + "txid": "b012e500eb7adf7a13ed332dd6ece849f94f7a62bb3eac5babab356d1fc19282", + "vout": 9, + "scriptSig": { + "asm": "304502207e84b27139c4c19c828cb1e30c349bba88e4d9b59be97286960793b5ddc0a2af0221008cdc7a951e7f31c20953ed5635fbabf228e80b7047f32faaa0313e7693005177[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", + "hex": "48304502207e84b27139c4c19c828cb1e30c349bba88e4d9b59be97286960793b5ddc0a2af0221008cdc7a951e7f31c20953ed5635fbabf228e80b7047f32faaa0313e7693005177012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" + }, + "sequence": 4294967295 + }, + { + "txid": "58840fee9c833f2f2d40575842f30f4b8d2553094d06ad88b03d06869acf3d88", + "vout": 30, + "scriptSig": { + "asm": "30440220426540dfed9c4ab5812e5f06df705b8bcf307dd7d20f7fa6512298b2a6314f420220064055096e3ca62f6c7352c66a5447767c53f946acdf35025ab3807ddb2fa404[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", + "hex": "4730440220426540dfed9c4ab5812e5f06df705b8bcf307dd7d20f7fa6512298b2a6314f420220064055096e3ca62f6c7352c66a5447767c53f946acdf35025ab3807ddb2fa404012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" + }, + "sequence": 4294967295 + }, + { + "txid": "e69f9cd16946e570a665245354428a3f507ea69f4568b581e4af98edb3db9766", + "vout": 114, + "scriptSig": { + "asm": "304402200a5e673996f2fc88e21cc8613611f08a650bc0370338803591d85d0ec5663764022040b6664a0d1ec83a7f01975b8fde5232992b8ca58bf48af6725d2f92a936ab2e[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", + "hex": "47304402200a5e673996f2fc88e21cc8613611f08a650bc0370338803591d85d0ec5663764022040b6664a0d1ec83a7f01975b8fde5232992b8ca58bf48af6725d2f92a936ab2e012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" + }, + "sequence": 4294967295 + }, + { + "txid": "595d1257f654ed2cbe5a65421e8aefd2b4d70b5b6c89a03f1d7e518221fc3f02", + "vout": 103, + "scriptSig": { + "asm": "3046022100d93b30219c5735f673be5c3b4688366d96f545561c74cb62c6958c00f6960806022100ec8200adcb028f2184fa2a4f6faac7f8bb57cb4503bb7584ac11051fece31b3d[ALL] 03091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc", + "hex": "493046022100d93b30219c5735f673be5c3b4688366d96f545561c74cb62c6958c00f6960806022100ec8200adcb028f2184fa2a4f6faac7f8bb57cb4503bb7584ac11051fece31b3d012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc" + }, + "sequence": 4294967295 + }, + { + "txid": "06fc818f9555a261248ecd7aad0993eafb5a82ceb2b5c87c3ddfb06671c7f816", + "vout": 1, + "scriptSig": { + "asm": "3045022100a13934e68d3f5b22b130c4cb33f4da468cffc52323a47fbfbe06b64858162246022047081e0a70ff770e64a2e2d31e5d520d9102268b57a47009a72fe73ec7669018[ALL] 0234b9d9413f247bb78cd3293b7b65a2c38018ba5621ea9ee737f3a6a3523fb4cd", + "hex": "483045022100a13934e68d3f5b22b130c4cb33f4da468cffc52323a47fbfbe06b64858162246022047081e0a70ff770e64a2e2d31e5d520d9102268b57a47009a72fe73ec766901801210234b9d9413f247bb78cd3293b7b65a2c38018ba5621ea9ee737f3a6a3523fb4cd" + }, + "sequence": 4294967295 + }, + { + "txid": "fb416c8155d6bb1d43f9395466ca90a638a7c2dd3ff617aadf3a7ac8f3967b19", + "vout": 0, + "scriptSig": { + "asm": "304602210097f1f35d5bdc1a3a60390a1b015b8e7c4f916aa3847aafd969e04975e15bbe70022100a9052eb25517d481f1fda1b129eb1b534da50ea1a51f3ee012dca3601c11b86a[ALL] 027a759be8df971a6a04fafcb4f6babf75dc811c5cdaa0734cddbe9b942ce75b34", + "hex": "49304602210097f1f35d5bdc1a3a60390a1b015b8e7c4f916aa3847aafd969e04975e15bbe70022100a9052eb25517d481f1fda1b129eb1b534da50ea1a51f3ee012dca3601c11b86a0121027a759be8df971a6a04fafcb4f6babf75dc811c5cdaa0734cddbe9b942ce75b34" + }, + "sequence": 4294967295 + }, + { + "txid": "3940b9683bd6104ad24c978e640ba4095993cafdb27d2ed91baa27ee61a2d920", + "vout": 221, + "scriptSig": { + "asm": "3045022012b3138c591bf7154b6fef457f2c4a3c7162225003788ac0024a99355865ff13022100b71b125ae1ffb2e1d1571f580cd3ebc8cd049a2d7a8a41f138ba94aeb982106f[ALL] 03091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc", + "hex": "483045022012b3138c591bf7154b6fef457f2c4a3c7162225003788ac0024a99355865ff13022100b71b125ae1ffb2e1d1571f580cd3ebc8cd049a2d7a8a41f138ba94aeb982106f012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc" + }, + "sequence": 4294967295 + }, + { + "txid": "711b5714d3b5136147c02194cd95bde94a4648c4263ca6f972d86cd1d579f150", + "vout": 1, + "scriptSig": { + "asm": "3045022100f834ccc8b22ee72712a3e5e6ef4acb8b2fb791b5385b70e2cd4332674d6667f4022024fbda0a997e0c253503f217501f508a4d56edce2c813ecdd9ad796dbeba9074[ALL] 0234b9d9413f247bb78cd3293b7b65a2c38018ba5621ea9ee737f3a6a3523fb4cd", + "hex": "483045022100f834ccc8b22ee72712a3e5e6ef4acb8b2fb791b5385b70e2cd4332674d6667f4022024fbda0a997e0c253503f217501f508a4d56edce2c813ecdd9ad796dbeba907401210234b9d9413f247bb78cd3293b7b65a2c38018ba5621ea9ee737f3a6a3523fb4cd" + }, + "sequence": 4294967295 + }, + { + "txid": "6364b5c5efe018430789e7fb4e338209546cae5d9c5f5e300aac68155d861b55", + "vout": 27, + "scriptSig": { + "asm": "304502203b2fd1e39ae0e469d7a15768f262661b0de41470daf0fe8c4fd0c26542a0870002210081c57e331f9a2d214457d953e3542904727ee412c63028113635d7224da3dccc[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", + "hex": "48304502203b2fd1e39ae0e469d7a15768f262661b0de41470daf0fe8c4fd0c26542a0870002210081c57e331f9a2d214457d953e3542904727ee412c63028113635d7224da3dccc012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" + }, + "sequence": 4294967295 + }, + { + "txid": "0bb57f6e38012c86d4c5a28c904f2675082859147921a707d48961015a3e5057", + "vout": 1095, + "scriptSig": { + "asm": "304502206947a9c54f0664ece4430fd4ae999891dc50bb6126bc36b6a15a3189f29d25e9022100a86cfc4e2fdd9e39a20e305cfd1b76509c67b3e313e0f118229105caa0e823c9[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", + "hex": "48304502206947a9c54f0664ece4430fd4ae999891dc50bb6126bc36b6a15a3189f29d25e9022100a86cfc4e2fdd9e39a20e305cfd1b76509c67b3e313e0f118229105caa0e823c9012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" + }, + "sequence": 4294967295 + }, + { + "txid": "9b34274814a2540bb062107117f8f3e75ef85d953e9372d8261a3e9dfbc1163f", + "vout": 37, + "scriptSig": { + "asm": "3045022100c7128fe10b2d38744ae8177776054c29fc8ec13f07207723e70766ab7164847402201d2cf09009b9596de74c0183d1ab832e5edddb7a9965880bb400097e850850f8[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", + "hex": "483045022100c7128fe10b2d38744ae8177776054c29fc8ec13f07207723e70766ab7164847402201d2cf09009b9596de74c0183d1ab832e5edddb7a9965880bb400097e850850f8012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" + }, + "sequence": 4294967295 + }, + { + "txid": "b86b5cc0d8a7374d94e277850b0a249cb26a7b42ddf014f28a49b8859da64241", + "vout": 20, + "scriptSig": { + "asm": "304502203b89a71628a28cc3703d170ca3be77786cff6b867e38a18b719705f8a326578f022100b2a9879e1acf621faa6466c207746a7f3eb4c8514c1482969aba3f2a957f1321[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", + "hex": "48304502203b89a71628a28cc3703d170ca3be77786cff6b867e38a18b719705f8a326578f022100b2a9879e1acf621faa6466c207746a7f3eb4c8514c1482969aba3f2a957f1321012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" + }, + "sequence": 4294967295 + }, + { + "txid": "3d0a2353eeec44d3c10aed259038db321912122cd4150048f7bfa4c0ecfee236", + "vout": 242, + "scriptSig": { + "asm": "3046022100ef794a8ef7fd6752d2a183c18866ff6e8dc0f5bd889a63e2c21cf303a6302461022100c1b09662d9e92988c3f9fcf17d1bcc79b5403647095d7212b9f8a1278a532d68[ALL] 03091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc", + "hex": "493046022100ef794a8ef7fd6752d2a183c18866ff6e8dc0f5bd889a63e2c21cf303a6302461022100c1b09662d9e92988c3f9fcf17d1bcc79b5403647095d7212b9f8a1278a532d68012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc" + }, + "sequence": 4294967295 + } + ], + "vout": [ + { + "value": 1.3782, + "n": 0, + "scriptPubKey": { + "asm": "OP_DUP OP_HASH160 8fd139bb39ced713f231c58a4d07bf6954d1c201 OP_EQUALVERIFY OP_CHECKSIG", + "hex": "76a9148fd139bb39ced713f231c58a4d07bf6954d1c20188ac", + "reqSigs": 1, + "type": "pubkeyhash", + "addresses": [ + "1E7SGgAZFCHDnVZLuRViX3gUmxpMfdvd2o" + ] + } + } + ], + "hex": "0100000015fd5c23522d31761c50175453daa6edaabe47a602a592d39ce933d8271a1a87274c0100006c493046022100b4251ecd63778a3dde0155abe4cd162947620ae9ee45a874353551092325b116022100db307baf4ff3781ec520bd18f387948cedd15dc27bafe17c894b0fe6ffffcafa012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adcffffffffcb4ed1baba3a1eb2171e00ddec8e5b72b346dd8c07f9c2b0d122d0d06bc92ea7000000006c493046022100a9b617843b68c284715d3e02fd120479cd0d96a6c43bf01e697fb0a460a21a3a022100ba0a12fbe8b993d4e7911fa3467615765dbe421ddf5c51b57a9c1ee19dcc00ba012103e633b4fa4ceb705c2da712390767199be8ef2448b3095dc01652e11b2b751505ffffffffc1b37ae964f605978022f94ce2f3f676d66a46d1aef7c2c17d6315b9697f2f75010000006a473044022079bd62ee09621a3be96b760c39e8ef78170101d46313923c6b07ae60a95c90670220238e51ea29fc70b04b65508450523caedbb11cb4dd5aa608c81487de798925ba0121027a759be8df971a6a04fafcb4f6babf75dc811c5cdaa0734cddbe9b942ce75b34ffffffffedd005dc7790ef65c206abd1ab718e75252a40f4b1310e4102cd692eca9cacb0d10000006b48304502207722d6f9038673c86a1019b1c4de2d687ae246477cd4ca7002762be0299de385022100e594a11e3a313942595f7666dcf7078bcb14f1330f4206b95c917e7ec0e82fac012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adcffffffffdf28d6e26fb7a85a1e6a229b972c1bae0edc1c11cb9ca51e4caf5e59fbea35a1000000006b483045022100a63a4788027b79b65c6f9d9e054f68cf3b4eed19efd82a2d53f70dcbe64683390220526f243671425b2bd05745fcf2729361f985cfe84ea80c7cfc817b93d8134374012103a621f08be22d1bbdcbe4e527ee4927006aa555fc65e2aafa767d4ea2fe9dfa52ffffffffae2a2320a1582faa24469eff3024a6b98bfe00eb4f554d8a0b1421ba53bfd6a5010000006c493046022100b200ac6db16842f76dab9abe807ce423c992805879bc50abd46ed8275a59d9cf022100c0d518e85dd345b3c29dd4dc47b9a420d3ce817b18720e94966d2fe23413a408012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adcffffffffb3cc5a12548aa1794b4d2bbf076838cfd7fbafb7716da51ee8221a4ff19c291b000000006b483045022100ededc441c3103a6f2bd6cab7639421af0f6ec5e60503bce1e603cf34f00aee1c02205cb75f3f519a13fb348783b21db3085cb5ec7552c59e394fdbc3e1feea43f967012103a621f08be22d1bbdcbe4e527ee4927006aa555fc65e2aafa767d4ea2fe9dfa52ffffffff85145367313888d2cf2747274a32e20b2df074027bafd6f970003fcbcdf11d07150000006b483045022100d9eed5413d2a4b4b98625aa6e3169edc4fb4663e7862316d69224454e70cd8ca022061e506521d5ced51dd0ea36496e75904d756a4c4f9fb111568555075d5f68d9a012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff8292c11f6d35abab5bac3ebb627a4ff949e8ecd62d33ed137adf7aeb00e512b0090000006b48304502207e84b27139c4c19c828cb1e30c349bba88e4d9b59be97286960793b5ddc0a2af0221008cdc7a951e7f31c20953ed5635fbabf228e80b7047f32faaa0313e7693005177012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff883dcf9a86063db088ad064d0953258d4b0ff3425857402d2f3f839cee0f84581e0000006a4730440220426540dfed9c4ab5812e5f06df705b8bcf307dd7d20f7fa6512298b2a6314f420220064055096e3ca62f6c7352c66a5447767c53f946acdf35025ab3807ddb2fa404012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff6697dbb3ed98afe481b568459fa67e503f8a4254532465a670e54669d19c9fe6720000006a47304402200a5e673996f2fc88e21cc8613611f08a650bc0370338803591d85d0ec5663764022040b6664a0d1ec83a7f01975b8fde5232992b8ca58bf48af6725d2f92a936ab2e012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff023ffc2182517e1d3fa0896c5b0bd7b4d2ef8a1e42655abe2ced54f657125d59670000006c493046022100d93b30219c5735f673be5c3b4688366d96f545561c74cb62c6958c00f6960806022100ec8200adcb028f2184fa2a4f6faac7f8bb57cb4503bb7584ac11051fece31b3d012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adcffffffff16f8c77166b0df3d7cc8b5b2ce825afbea9309ad7acd8e2461a255958f81fc06010000006b483045022100a13934e68d3f5b22b130c4cb33f4da468cffc52323a47fbfbe06b64858162246022047081e0a70ff770e64a2e2d31e5d520d9102268b57a47009a72fe73ec766901801210234b9d9413f247bb78cd3293b7b65a2c38018ba5621ea9ee737f3a6a3523fb4cdffffffff197b96f3c87a3adfaa17f63fddc2a738a690ca665439f9431dbbd655816c41fb000000006c49304602210097f1f35d5bdc1a3a60390a1b015b8e7c4f916aa3847aafd969e04975e15bbe70022100a9052eb25517d481f1fda1b129eb1b534da50ea1a51f3ee012dca3601c11b86a0121027a759be8df971a6a04fafcb4f6babf75dc811c5cdaa0734cddbe9b942ce75b34ffffffff20d9a261ee27aa1bd92e7db2fdca935909a40b648e974cd24a10d63b68b94039dd0000006b483045022012b3138c591bf7154b6fef457f2c4a3c7162225003788ac0024a99355865ff13022100b71b125ae1ffb2e1d1571f580cd3ebc8cd049a2d7a8a41f138ba94aeb982106f012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adcffffffff50f179d5d16cd872f9a63c26c448464ae9bd95cd9421c0476113b5d314571b71010000006b483045022100f834ccc8b22ee72712a3e5e6ef4acb8b2fb791b5385b70e2cd4332674d6667f4022024fbda0a997e0c253503f217501f508a4d56edce2c813ecdd9ad796dbeba907401210234b9d9413f247bb78cd3293b7b65a2c38018ba5621ea9ee737f3a6a3523fb4cdffffffff551b865d1568ac0a305e5f9c5dae6c540982334efbe789074318e0efc5b564631b0000006b48304502203b2fd1e39ae0e469d7a15768f262661b0de41470daf0fe8c4fd0c26542a0870002210081c57e331f9a2d214457d953e3542904727ee412c63028113635d7224da3dccc012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff57503e5a016189d407a721791459280875264f908ca2c5d4862c01386e7fb50b470400006b48304502206947a9c54f0664ece4430fd4ae999891dc50bb6126bc36b6a15a3189f29d25e9022100a86cfc4e2fdd9e39a20e305cfd1b76509c67b3e313e0f118229105caa0e823c9012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff3f16c1fb9d3e1a26d872933e955df85ee7f3f817711062b00b54a2144827349b250000006b483045022100c7128fe10b2d38744ae8177776054c29fc8ec13f07207723e70766ab7164847402201d2cf09009b9596de74c0183d1ab832e5edddb7a9965880bb400097e850850f8012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff4142a69d85b8498af214f0dd427b6ab29c240a0b8577e2944d37a7d8c05c6bb8140000006b48304502203b89a71628a28cc3703d170ca3be77786cff6b867e38a18b719705f8a326578f022100b2a9879e1acf621faa6466c207746a7f3eb4c8514c1482969aba3f2a957f1321012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff36e2feecc0a4bff7480015d42c12121932db389025ed0ac1d344ecee53230a3df20000006c493046022100ef794a8ef7fd6752d2a183c18866ff6e8dc0f5bd889a63e2c21cf303a6302461022100c1b09662d9e92988c3f9fcf17d1bcc79b5403647095d7212b9f8a1278a532d68012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adcffffffff0160f73608000000001976a9148fd139bb39ced713f231c58a4d07bf6954d1c20188ac00000000" +} diff --git a/src/test/data/tt-locktime317000-out.json b/src/test/data/tt-locktime317000-out.json new file mode 100644 index 0000000000..65b6a4451b --- /dev/null +++ b/src/test/data/tt-locktime317000-out.json @@ -0,0 +1,225 @@ +{ + "txid": "aded538f642c17e15f4d3306b8be7e1a4d1ae0c4616d641ab51ea09ba65e5cb5", + "version": 1, + "locktime": 317000, + "vin": [ + { + "txid": "27871a1a27d833e99cd392a502a647beaaeda6da535417501c76312d52235cfd", + "vout": 332, + "scriptSig": { + "asm": "3046022100b4251ecd63778a3dde0155abe4cd162947620ae9ee45a874353551092325b116022100db307baf4ff3781ec520bd18f387948cedd15dc27bafe17c894b0fe6ffffcafa[ALL] 03091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc", + "hex": "493046022100b4251ecd63778a3dde0155abe4cd162947620ae9ee45a874353551092325b116022100db307baf4ff3781ec520bd18f387948cedd15dc27bafe17c894b0fe6ffffcafa012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc" + }, + "sequence": 4294967295 + }, + { + "txid": "a72ec96bd0d022d1b0c2f9078cdd46b3725b8eecdd001e17b21e3ababad14ecb", + "vout": 0, + "scriptSig": { + "asm": "3046022100a9b617843b68c284715d3e02fd120479cd0d96a6c43bf01e697fb0a460a21a3a022100ba0a12fbe8b993d4e7911fa3467615765dbe421ddf5c51b57a9c1ee19dcc00ba[ALL] 03e633b4fa4ceb705c2da712390767199be8ef2448b3095dc01652e11b2b751505", + "hex": "493046022100a9b617843b68c284715d3e02fd120479cd0d96a6c43bf01e697fb0a460a21a3a022100ba0a12fbe8b993d4e7911fa3467615765dbe421ddf5c51b57a9c1ee19dcc00ba012103e633b4fa4ceb705c2da712390767199be8ef2448b3095dc01652e11b2b751505" + }, + "sequence": 4294967295 + }, + { + "txid": "752f7f69b915637dc1c2f7aed1466ad676f6f3e24cf922809705f664e97ab3c1", + "vout": 1, + "scriptSig": { + "asm": "3044022079bd62ee09621a3be96b760c39e8ef78170101d46313923c6b07ae60a95c90670220238e51ea29fc70b04b65508450523caedbb11cb4dd5aa608c81487de798925ba[ALL] 027a759be8df971a6a04fafcb4f6babf75dc811c5cdaa0734cddbe9b942ce75b34", + "hex": "473044022079bd62ee09621a3be96b760c39e8ef78170101d46313923c6b07ae60a95c90670220238e51ea29fc70b04b65508450523caedbb11cb4dd5aa608c81487de798925ba0121027a759be8df971a6a04fafcb4f6babf75dc811c5cdaa0734cddbe9b942ce75b34" + }, + "sequence": 4294967295 + }, + { + "txid": "b0ac9cca2e69cd02410e31b1f4402a25758e71abd1ab06c265ef9077dc05d0ed", + "vout": 209, + "scriptSig": { + "asm": "304502207722d6f9038673c86a1019b1c4de2d687ae246477cd4ca7002762be0299de385022100e594a11e3a313942595f7666dcf7078bcb14f1330f4206b95c917e7ec0e82fac[ALL] 03091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc", + "hex": "48304502207722d6f9038673c86a1019b1c4de2d687ae246477cd4ca7002762be0299de385022100e594a11e3a313942595f7666dcf7078bcb14f1330f4206b95c917e7ec0e82fac012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc" + }, + "sequence": 4294967295 + }, + { + "txid": "a135eafb595eaf4c1ea59ccb111cdc0eae1b2c979b226a1e5aa8b76fe2d628df", + "vout": 0, + "scriptSig": { + "asm": "3045022100a63a4788027b79b65c6f9d9e054f68cf3b4eed19efd82a2d53f70dcbe64683390220526f243671425b2bd05745fcf2729361f985cfe84ea80c7cfc817b93d8134374[ALL] 03a621f08be22d1bbdcbe4e527ee4927006aa555fc65e2aafa767d4ea2fe9dfa52", + "hex": "483045022100a63a4788027b79b65c6f9d9e054f68cf3b4eed19efd82a2d53f70dcbe64683390220526f243671425b2bd05745fcf2729361f985cfe84ea80c7cfc817b93d8134374012103a621f08be22d1bbdcbe4e527ee4927006aa555fc65e2aafa767d4ea2fe9dfa52" + }, + "sequence": 4294967295 + }, + { + "txid": "a5d6bf53ba21140b8a4d554feb00fe8bb9a62430ff9e4624aa2f58a120232aae", + "vout": 1, + "scriptSig": { + "asm": "3046022100b200ac6db16842f76dab9abe807ce423c992805879bc50abd46ed8275a59d9cf022100c0d518e85dd345b3c29dd4dc47b9a420d3ce817b18720e94966d2fe23413a408[ALL] 03091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc", + "hex": "493046022100b200ac6db16842f76dab9abe807ce423c992805879bc50abd46ed8275a59d9cf022100c0d518e85dd345b3c29dd4dc47b9a420d3ce817b18720e94966d2fe23413a408012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc" + }, + "sequence": 4294967295 + }, + { + "txid": "1b299cf14f1a22e81ea56d71b7affbd7cf386807bf2b4d4b79a18a54125accb3", + "vout": 0, + "scriptSig": { + "asm": "3045022100ededc441c3103a6f2bd6cab7639421af0f6ec5e60503bce1e603cf34f00aee1c02205cb75f3f519a13fb348783b21db3085cb5ec7552c59e394fdbc3e1feea43f967[ALL] 03a621f08be22d1bbdcbe4e527ee4927006aa555fc65e2aafa767d4ea2fe9dfa52", + "hex": "483045022100ededc441c3103a6f2bd6cab7639421af0f6ec5e60503bce1e603cf34f00aee1c02205cb75f3f519a13fb348783b21db3085cb5ec7552c59e394fdbc3e1feea43f967012103a621f08be22d1bbdcbe4e527ee4927006aa555fc65e2aafa767d4ea2fe9dfa52" + }, + "sequence": 4294967295 + }, + { + "txid": "071df1cdcb3f0070f9d6af7b0274f02d0be2324a274727cfd288383167531485", + "vout": 21, + "scriptSig": { + "asm": "3045022100d9eed5413d2a4b4b98625aa6e3169edc4fb4663e7862316d69224454e70cd8ca022061e506521d5ced51dd0ea36496e75904d756a4c4f9fb111568555075d5f68d9a[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", + "hex": "483045022100d9eed5413d2a4b4b98625aa6e3169edc4fb4663e7862316d69224454e70cd8ca022061e506521d5ced51dd0ea36496e75904d756a4c4f9fb111568555075d5f68d9a012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" + }, + "sequence": 4294967295 + }, + { + "txid": "b012e500eb7adf7a13ed332dd6ece849f94f7a62bb3eac5babab356d1fc19282", + "vout": 9, + "scriptSig": { + "asm": "304502207e84b27139c4c19c828cb1e30c349bba88e4d9b59be97286960793b5ddc0a2af0221008cdc7a951e7f31c20953ed5635fbabf228e80b7047f32faaa0313e7693005177[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", + "hex": "48304502207e84b27139c4c19c828cb1e30c349bba88e4d9b59be97286960793b5ddc0a2af0221008cdc7a951e7f31c20953ed5635fbabf228e80b7047f32faaa0313e7693005177012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" + }, + "sequence": 4294967295 + }, + { + "txid": "58840fee9c833f2f2d40575842f30f4b8d2553094d06ad88b03d06869acf3d88", + "vout": 30, + "scriptSig": { + "asm": "30440220426540dfed9c4ab5812e5f06df705b8bcf307dd7d20f7fa6512298b2a6314f420220064055096e3ca62f6c7352c66a5447767c53f946acdf35025ab3807ddb2fa404[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", + "hex": "4730440220426540dfed9c4ab5812e5f06df705b8bcf307dd7d20f7fa6512298b2a6314f420220064055096e3ca62f6c7352c66a5447767c53f946acdf35025ab3807ddb2fa404012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" + }, + "sequence": 4294967295 + }, + { + "txid": "e69f9cd16946e570a665245354428a3f507ea69f4568b581e4af98edb3db9766", + "vout": 114, + "scriptSig": { + "asm": "304402200a5e673996f2fc88e21cc8613611f08a650bc0370338803591d85d0ec5663764022040b6664a0d1ec83a7f01975b8fde5232992b8ca58bf48af6725d2f92a936ab2e[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", + "hex": "47304402200a5e673996f2fc88e21cc8613611f08a650bc0370338803591d85d0ec5663764022040b6664a0d1ec83a7f01975b8fde5232992b8ca58bf48af6725d2f92a936ab2e012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" + }, + "sequence": 4294967295 + }, + { + "txid": "595d1257f654ed2cbe5a65421e8aefd2b4d70b5b6c89a03f1d7e518221fc3f02", + "vout": 103, + "scriptSig": { + "asm": "3046022100d93b30219c5735f673be5c3b4688366d96f545561c74cb62c6958c00f6960806022100ec8200adcb028f2184fa2a4f6faac7f8bb57cb4503bb7584ac11051fece31b3d[ALL] 03091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc", + "hex": "493046022100d93b30219c5735f673be5c3b4688366d96f545561c74cb62c6958c00f6960806022100ec8200adcb028f2184fa2a4f6faac7f8bb57cb4503bb7584ac11051fece31b3d012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc" + }, + "sequence": 4294967295 + }, + { + "txid": "06fc818f9555a261248ecd7aad0993eafb5a82ceb2b5c87c3ddfb06671c7f816", + "vout": 1, + "scriptSig": { + "asm": "3045022100a13934e68d3f5b22b130c4cb33f4da468cffc52323a47fbfbe06b64858162246022047081e0a70ff770e64a2e2d31e5d520d9102268b57a47009a72fe73ec7669018[ALL] 0234b9d9413f247bb78cd3293b7b65a2c38018ba5621ea9ee737f3a6a3523fb4cd", + "hex": "483045022100a13934e68d3f5b22b130c4cb33f4da468cffc52323a47fbfbe06b64858162246022047081e0a70ff770e64a2e2d31e5d520d9102268b57a47009a72fe73ec766901801210234b9d9413f247bb78cd3293b7b65a2c38018ba5621ea9ee737f3a6a3523fb4cd" + }, + "sequence": 4294967295 + }, + { + "txid": "fb416c8155d6bb1d43f9395466ca90a638a7c2dd3ff617aadf3a7ac8f3967b19", + "vout": 0, + "scriptSig": { + "asm": "304602210097f1f35d5bdc1a3a60390a1b015b8e7c4f916aa3847aafd969e04975e15bbe70022100a9052eb25517d481f1fda1b129eb1b534da50ea1a51f3ee012dca3601c11b86a[ALL] 027a759be8df971a6a04fafcb4f6babf75dc811c5cdaa0734cddbe9b942ce75b34", + "hex": "49304602210097f1f35d5bdc1a3a60390a1b015b8e7c4f916aa3847aafd969e04975e15bbe70022100a9052eb25517d481f1fda1b129eb1b534da50ea1a51f3ee012dca3601c11b86a0121027a759be8df971a6a04fafcb4f6babf75dc811c5cdaa0734cddbe9b942ce75b34" + }, + "sequence": 4294967295 + }, + { + "txid": "3940b9683bd6104ad24c978e640ba4095993cafdb27d2ed91baa27ee61a2d920", + "vout": 221, + "scriptSig": { + "asm": "3045022012b3138c591bf7154b6fef457f2c4a3c7162225003788ac0024a99355865ff13022100b71b125ae1ffb2e1d1571f580cd3ebc8cd049a2d7a8a41f138ba94aeb982106f[ALL] 03091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc", + "hex": "483045022012b3138c591bf7154b6fef457f2c4a3c7162225003788ac0024a99355865ff13022100b71b125ae1ffb2e1d1571f580cd3ebc8cd049a2d7a8a41f138ba94aeb982106f012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc" + }, + "sequence": 4294967295 + }, + { + "txid": "711b5714d3b5136147c02194cd95bde94a4648c4263ca6f972d86cd1d579f150", + "vout": 1, + "scriptSig": { + "asm": "3045022100f834ccc8b22ee72712a3e5e6ef4acb8b2fb791b5385b70e2cd4332674d6667f4022024fbda0a997e0c253503f217501f508a4d56edce2c813ecdd9ad796dbeba9074[ALL] 0234b9d9413f247bb78cd3293b7b65a2c38018ba5621ea9ee737f3a6a3523fb4cd", + "hex": "483045022100f834ccc8b22ee72712a3e5e6ef4acb8b2fb791b5385b70e2cd4332674d6667f4022024fbda0a997e0c253503f217501f508a4d56edce2c813ecdd9ad796dbeba907401210234b9d9413f247bb78cd3293b7b65a2c38018ba5621ea9ee737f3a6a3523fb4cd" + }, + "sequence": 4294967295 + }, + { + "txid": "6364b5c5efe018430789e7fb4e338209546cae5d9c5f5e300aac68155d861b55", + "vout": 27, + "scriptSig": { + "asm": "304502203b2fd1e39ae0e469d7a15768f262661b0de41470daf0fe8c4fd0c26542a0870002210081c57e331f9a2d214457d953e3542904727ee412c63028113635d7224da3dccc[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", + "hex": "48304502203b2fd1e39ae0e469d7a15768f262661b0de41470daf0fe8c4fd0c26542a0870002210081c57e331f9a2d214457d953e3542904727ee412c63028113635d7224da3dccc012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" + }, + "sequence": 4294967295 + }, + { + "txid": "0bb57f6e38012c86d4c5a28c904f2675082859147921a707d48961015a3e5057", + "vout": 1095, + "scriptSig": { + "asm": "304502206947a9c54f0664ece4430fd4ae999891dc50bb6126bc36b6a15a3189f29d25e9022100a86cfc4e2fdd9e39a20e305cfd1b76509c67b3e313e0f118229105caa0e823c9[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", + "hex": "48304502206947a9c54f0664ece4430fd4ae999891dc50bb6126bc36b6a15a3189f29d25e9022100a86cfc4e2fdd9e39a20e305cfd1b76509c67b3e313e0f118229105caa0e823c9012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" + }, + "sequence": 4294967295 + }, + { + "txid": "9b34274814a2540bb062107117f8f3e75ef85d953e9372d8261a3e9dfbc1163f", + "vout": 37, + "scriptSig": { + "asm": "3045022100c7128fe10b2d38744ae8177776054c29fc8ec13f07207723e70766ab7164847402201d2cf09009b9596de74c0183d1ab832e5edddb7a9965880bb400097e850850f8[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", + "hex": "483045022100c7128fe10b2d38744ae8177776054c29fc8ec13f07207723e70766ab7164847402201d2cf09009b9596de74c0183d1ab832e5edddb7a9965880bb400097e850850f8012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" + }, + "sequence": 4294967295 + }, + { + "txid": "b86b5cc0d8a7374d94e277850b0a249cb26a7b42ddf014f28a49b8859da64241", + "vout": 20, + "scriptSig": { + "asm": "304502203b89a71628a28cc3703d170ca3be77786cff6b867e38a18b719705f8a326578f022100b2a9879e1acf621faa6466c207746a7f3eb4c8514c1482969aba3f2a957f1321[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", + "hex": "48304502203b89a71628a28cc3703d170ca3be77786cff6b867e38a18b719705f8a326578f022100b2a9879e1acf621faa6466c207746a7f3eb4c8514c1482969aba3f2a957f1321012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" + }, + "sequence": 4294967295 + }, + { + "txid": "3d0a2353eeec44d3c10aed259038db321912122cd4150048f7bfa4c0ecfee236", + "vout": 242, + "scriptSig": { + "asm": "3046022100ef794a8ef7fd6752d2a183c18866ff6e8dc0f5bd889a63e2c21cf303a6302461022100c1b09662d9e92988c3f9fcf17d1bcc79b5403647095d7212b9f8a1278a532d68[ALL] 03091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc", + "hex": "493046022100ef794a8ef7fd6752d2a183c18866ff6e8dc0f5bd889a63e2c21cf303a6302461022100c1b09662d9e92988c3f9fcf17d1bcc79b5403647095d7212b9f8a1278a532d68012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc" + }, + "sequence": 4294967295 + } + ], + "vout": [ + { + "value": 1.3782, + "n": 0, + "scriptPubKey": { + "asm": "OP_DUP OP_HASH160 8fd139bb39ced713f231c58a4d07bf6954d1c201 OP_EQUALVERIFY OP_CHECKSIG", + "hex": "76a9148fd139bb39ced713f231c58a4d07bf6954d1c20188ac", + "reqSigs": 1, + "type": "pubkeyhash", + "addresses": [ + "1E7SGgAZFCHDnVZLuRViX3gUmxpMfdvd2o" + ] + } + }, + { + "value": 0.01000001, + "n": 1, + "scriptPubKey": { + "asm": "OP_DUP OP_HASH160 6c772e9cf96371bba3da8cb733da70a2fcf20078 OP_EQUALVERIFY OP_CHECKSIG", + "hex": "76a9146c772e9cf96371bba3da8cb733da70a2fcf2007888ac", + "reqSigs": 1, + "type": "pubkeyhash", + "addresses": [ + "1AtWkdmfmYkErU16d3KYykJUbEp9MAj9Sb" + ] + } + } + ], + "hex": "0100000015fd5c23522d31761c50175453daa6edaabe47a602a592d39ce933d8271a1a87274c0100006c493046022100b4251ecd63778a3dde0155abe4cd162947620ae9ee45a874353551092325b116022100db307baf4ff3781ec520bd18f387948cedd15dc27bafe17c894b0fe6ffffcafa012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adcffffffffcb4ed1baba3a1eb2171e00ddec8e5b72b346dd8c07f9c2b0d122d0d06bc92ea7000000006c493046022100a9b617843b68c284715d3e02fd120479cd0d96a6c43bf01e697fb0a460a21a3a022100ba0a12fbe8b993d4e7911fa3467615765dbe421ddf5c51b57a9c1ee19dcc00ba012103e633b4fa4ceb705c2da712390767199be8ef2448b3095dc01652e11b2b751505ffffffffc1b37ae964f605978022f94ce2f3f676d66a46d1aef7c2c17d6315b9697f2f75010000006a473044022079bd62ee09621a3be96b760c39e8ef78170101d46313923c6b07ae60a95c90670220238e51ea29fc70b04b65508450523caedbb11cb4dd5aa608c81487de798925ba0121027a759be8df971a6a04fafcb4f6babf75dc811c5cdaa0734cddbe9b942ce75b34ffffffffedd005dc7790ef65c206abd1ab718e75252a40f4b1310e4102cd692eca9cacb0d10000006b48304502207722d6f9038673c86a1019b1c4de2d687ae246477cd4ca7002762be0299de385022100e594a11e3a313942595f7666dcf7078bcb14f1330f4206b95c917e7ec0e82fac012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adcffffffffdf28d6e26fb7a85a1e6a229b972c1bae0edc1c11cb9ca51e4caf5e59fbea35a1000000006b483045022100a63a4788027b79b65c6f9d9e054f68cf3b4eed19efd82a2d53f70dcbe64683390220526f243671425b2bd05745fcf2729361f985cfe84ea80c7cfc817b93d8134374012103a621f08be22d1bbdcbe4e527ee4927006aa555fc65e2aafa767d4ea2fe9dfa52ffffffffae2a2320a1582faa24469eff3024a6b98bfe00eb4f554d8a0b1421ba53bfd6a5010000006c493046022100b200ac6db16842f76dab9abe807ce423c992805879bc50abd46ed8275a59d9cf022100c0d518e85dd345b3c29dd4dc47b9a420d3ce817b18720e94966d2fe23413a408012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adcffffffffb3cc5a12548aa1794b4d2bbf076838cfd7fbafb7716da51ee8221a4ff19c291b000000006b483045022100ededc441c3103a6f2bd6cab7639421af0f6ec5e60503bce1e603cf34f00aee1c02205cb75f3f519a13fb348783b21db3085cb5ec7552c59e394fdbc3e1feea43f967012103a621f08be22d1bbdcbe4e527ee4927006aa555fc65e2aafa767d4ea2fe9dfa52ffffffff85145367313888d2cf2747274a32e20b2df074027bafd6f970003fcbcdf11d07150000006b483045022100d9eed5413d2a4b4b98625aa6e3169edc4fb4663e7862316d69224454e70cd8ca022061e506521d5ced51dd0ea36496e75904d756a4c4f9fb111568555075d5f68d9a012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff8292c11f6d35abab5bac3ebb627a4ff949e8ecd62d33ed137adf7aeb00e512b0090000006b48304502207e84b27139c4c19c828cb1e30c349bba88e4d9b59be97286960793b5ddc0a2af0221008cdc7a951e7f31c20953ed5635fbabf228e80b7047f32faaa0313e7693005177012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff883dcf9a86063db088ad064d0953258d4b0ff3425857402d2f3f839cee0f84581e0000006a4730440220426540dfed9c4ab5812e5f06df705b8bcf307dd7d20f7fa6512298b2a6314f420220064055096e3ca62f6c7352c66a5447767c53f946acdf35025ab3807ddb2fa404012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff6697dbb3ed98afe481b568459fa67e503f8a4254532465a670e54669d19c9fe6720000006a47304402200a5e673996f2fc88e21cc8613611f08a650bc0370338803591d85d0ec5663764022040b6664a0d1ec83a7f01975b8fde5232992b8ca58bf48af6725d2f92a936ab2e012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff023ffc2182517e1d3fa0896c5b0bd7b4d2ef8a1e42655abe2ced54f657125d59670000006c493046022100d93b30219c5735f673be5c3b4688366d96f545561c74cb62c6958c00f6960806022100ec8200adcb028f2184fa2a4f6faac7f8bb57cb4503bb7584ac11051fece31b3d012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adcffffffff16f8c77166b0df3d7cc8b5b2ce825afbea9309ad7acd8e2461a255958f81fc06010000006b483045022100a13934e68d3f5b22b130c4cb33f4da468cffc52323a47fbfbe06b64858162246022047081e0a70ff770e64a2e2d31e5d520d9102268b57a47009a72fe73ec766901801210234b9d9413f247bb78cd3293b7b65a2c38018ba5621ea9ee737f3a6a3523fb4cdffffffff197b96f3c87a3adfaa17f63fddc2a738a690ca665439f9431dbbd655816c41fb000000006c49304602210097f1f35d5bdc1a3a60390a1b015b8e7c4f916aa3847aafd969e04975e15bbe70022100a9052eb25517d481f1fda1b129eb1b534da50ea1a51f3ee012dca3601c11b86a0121027a759be8df971a6a04fafcb4f6babf75dc811c5cdaa0734cddbe9b942ce75b34ffffffff20d9a261ee27aa1bd92e7db2fdca935909a40b648e974cd24a10d63b68b94039dd0000006b483045022012b3138c591bf7154b6fef457f2c4a3c7162225003788ac0024a99355865ff13022100b71b125ae1ffb2e1d1571f580cd3ebc8cd049a2d7a8a41f138ba94aeb982106f012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adcffffffff50f179d5d16cd872f9a63c26c448464ae9bd95cd9421c0476113b5d314571b71010000006b483045022100f834ccc8b22ee72712a3e5e6ef4acb8b2fb791b5385b70e2cd4332674d6667f4022024fbda0a997e0c253503f217501f508a4d56edce2c813ecdd9ad796dbeba907401210234b9d9413f247bb78cd3293b7b65a2c38018ba5621ea9ee737f3a6a3523fb4cdffffffff551b865d1568ac0a305e5f9c5dae6c540982334efbe789074318e0efc5b564631b0000006b48304502203b2fd1e39ae0e469d7a15768f262661b0de41470daf0fe8c4fd0c26542a0870002210081c57e331f9a2d214457d953e3542904727ee412c63028113635d7224da3dccc012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff57503e5a016189d407a721791459280875264f908ca2c5d4862c01386e7fb50b470400006b48304502206947a9c54f0664ece4430fd4ae999891dc50bb6126bc36b6a15a3189f29d25e9022100a86cfc4e2fdd9e39a20e305cfd1b76509c67b3e313e0f118229105caa0e823c9012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff3f16c1fb9d3e1a26d872933e955df85ee7f3f817711062b00b54a2144827349b250000006b483045022100c7128fe10b2d38744ae8177776054c29fc8ec13f07207723e70766ab7164847402201d2cf09009b9596de74c0183d1ab832e5edddb7a9965880bb400097e850850f8012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff4142a69d85b8498af214f0dd427b6ab29c240a0b8577e2944d37a7d8c05c6bb8140000006b48304502203b89a71628a28cc3703d170ca3be77786cff6b867e38a18b719705f8a326578f022100b2a9879e1acf621faa6466c207746a7f3eb4c8514c1482969aba3f2a957f1321012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff36e2feecc0a4bff7480015d42c12121932db389025ed0ac1d344ecee53230a3df20000006c493046022100ef794a8ef7fd6752d2a183c18866ff6e8dc0f5bd889a63e2c21cf303a6302461022100c1b09662d9e92988c3f9fcf17d1bcc79b5403647095d7212b9f8a1278a532d68012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adcffffffff0260f73608000000001976a9148fd139bb39ced713f231c58a4d07bf6954d1c20188ac41420f00000000001976a9146c772e9cf96371bba3da8cb733da70a2fcf2007888ac48d60400" +} diff --git a/src/test/data/txcreate1.json b/src/test/data/txcreate1.json new file mode 100644 index 0000000000..3890dbaf6e --- /dev/null +++ b/src/test/data/txcreate1.json @@ -0,0 +1,63 @@ +{ + "txid": "f70f0d6c71416ed538e37549f430ab3665fee2437a42f10238c1bd490e782231", + "version": 1, + "locktime": 0, + "vin": [ + { + "txid": "5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f", + "vout": 0, + "scriptSig": { + "asm": "", + "hex": "" + }, + "sequence": 4294967295 + }, + { + "txid": "bf829c6bcf84579331337659d31f89dfd138f7f7785802d5501c92333145ca7c", + "vout": 18, + "scriptSig": { + "asm": "", + "hex": "" + }, + "sequence": 4294967295 + }, + { + "txid": "22a6f904655d53ae2ff70e701a0bbd90aa3975c0f40bfc6cc996a9049e31cdfc", + "vout": 1, + "scriptSig": { + "asm": "", + "hex": "" + }, + "sequence": 4294967295 + } + ], + "vout": [ + { + "value": 0.18, + "n": 0, + "scriptPubKey": { + "asm": "OP_DUP OP_HASH160 1fc11f39be1729bf973a7ab6a615ca4729d64574 OP_EQUALVERIFY OP_CHECKSIG", + "hex": "76a9141fc11f39be1729bf973a7ab6a615ca4729d6457488ac", + "reqSigs": 1, + "type": "pubkeyhash", + "addresses": [ + "13tuJJDR2RgArmgfv6JScSdreahzgc4T6o" + ] + } + }, + { + "value": 4.00, + "n": 1, + "scriptPubKey": { + "asm": "OP_DUP OP_HASH160 f2d4db28cad6502226ee484ae24505c2885cb12d OP_EQUALVERIFY OP_CHECKSIG", + "hex": "76a914f2d4db28cad6502226ee484ae24505c2885cb12d88ac", + "reqSigs": 1, + "type": "pubkeyhash", + "addresses": [ + "1P8yWvZW8jVihP1bzHeqfE4aoXNX8AVa46" + ] + } + } + ], + "hex": "01000000031f5c38dfcf6f1a5f5a87c416076d392c87e6d41970d5ad5e477a02d66bde97580000000000ffffffff7cca453133921c50d5025878f7f738d1df891fd359763331935784cf6b9c82bf1200000000fffffffffccd319e04a996c96cfc0bf4c07539aa90bd0b1a700ef72fae535d6504f9a6220100000000ffffffff0280a81201000000001976a9141fc11f39be1729bf973a7ab6a615ca4729d6457488ac0084d717000000001976a914f2d4db28cad6502226ee484ae24505c2885cb12d88ac00000000" +} diff --git a/src/test/data/txcreate2.json b/src/test/data/txcreate2.json new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/src/test/data/txcreate2.json diff --git a/src/test/data/txcreatedata1.json b/src/test/data/txcreatedata1.json new file mode 100644 index 0000000000..2fed228108 --- /dev/null +++ b/src/test/data/txcreatedata1.json @@ -0,0 +1,41 @@ +{ + "txid": "07894b4d12fe7853dd911402db1620920d261b9627c447f931417d330c25f06e", + "version": 1, + "locktime": 0, + "vin": [ + { + "txid": "5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f", + "vout": 0, + "scriptSig": { + "asm": "", + "hex": "" + }, + "sequence": 4294967295 + } + ], + "vout": [ + { + "value": 0.18, + "n": 0, + "scriptPubKey": { + "asm": "OP_DUP OP_HASH160 1fc11f39be1729bf973a7ab6a615ca4729d64574 OP_EQUALVERIFY OP_CHECKSIG", + "hex": "76a9141fc11f39be1729bf973a7ab6a615ca4729d6457488ac", + "reqSigs": 1, + "type": "pubkeyhash", + "addresses": [ + "13tuJJDR2RgArmgfv6JScSdreahzgc4T6o" + ] + } + }, + { + "value": 4.00, + "n": 1, + "scriptPubKey": { + "asm": "OP_RETURN 54686973204f505f52455455524e207472616e73616374696f6e206f7574707574207761732063726561746564206279206d6f646966696564206372656174657261777472616e73616374696f6e2e", + "hex": "6a4c4f54686973204f505f52455455524e207472616e73616374696f6e206f7574707574207761732063726561746564206279206d6f646966696564206372656174657261777472616e73616374696f6e2e", + "type": "nulldata" + } + } + ], + "hex": "01000000011f5c38dfcf6f1a5f5a87c416076d392c87e6d41970d5ad5e477a02d66bde97580000000000ffffffff0280a81201000000001976a9141fc11f39be1729bf973a7ab6a615ca4729d6457488ac0084d71700000000526a4c4f54686973204f505f52455455524e207472616e73616374696f6e206f7574707574207761732063726561746564206279206d6f646966696564206372656174657261777472616e73616374696f6e2e00000000" +} diff --git a/src/test/data/txcreatedata2.json b/src/test/data/txcreatedata2.json new file mode 100644 index 0000000000..3d4d367f37 --- /dev/null +++ b/src/test/data/txcreatedata2.json @@ -0,0 +1,41 @@ +{ + "txid": "4ed17118f5e932ba8c75c461787d171bc02a016d8557cb5bcf34cd416c27bb8b", + "version": 1, + "locktime": 0, + "vin": [ + { + "txid": "5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f", + "vout": 0, + "scriptSig": { + "asm": "", + "hex": "" + }, + "sequence": 4294967295 + } + ], + "vout": [ + { + "value": 0.18, + "n": 0, + "scriptPubKey": { + "asm": "OP_DUP OP_HASH160 1fc11f39be1729bf973a7ab6a615ca4729d64574 OP_EQUALVERIFY OP_CHECKSIG", + "hex": "76a9141fc11f39be1729bf973a7ab6a615ca4729d6457488ac", + "reqSigs": 1, + "type": "pubkeyhash", + "addresses": [ + "13tuJJDR2RgArmgfv6JScSdreahzgc4T6o" + ] + } + }, + { + "value": 0.00, + "n": 1, + "scriptPubKey": { + "asm": "OP_RETURN 54686973204f505f52455455524e207472616e73616374696f6e206f7574707574207761732063726561746564206279206d6f646966696564206372656174657261777472616e73616374696f6e2e", + "hex": "6a4c4f54686973204f505f52455455524e207472616e73616374696f6e206f7574707574207761732063726561746564206279206d6f646966696564206372656174657261777472616e73616374696f6e2e", + "type": "nulldata" + } + } + ], + "hex": "01000000011f5c38dfcf6f1a5f5a87c416076d392c87e6d41970d5ad5e477a02d66bde97580000000000ffffffff0280a81201000000001976a9141fc11f39be1729bf973a7ab6a615ca4729d6457488ac0000000000000000526a4c4f54686973204f505f52455455524e207472616e73616374696f6e206f7574707574207761732063726561746564206279206d6f646966696564206372656174657261777472616e73616374696f6e2e00000000" +} diff --git a/src/test/data/txcreatedata_seq0.json b/src/test/data/txcreatedata_seq0.json new file mode 100644 index 0000000000..f25aa43c2b --- /dev/null +++ b/src/test/data/txcreatedata_seq0.json @@ -0,0 +1,32 @@ +{ + "txid": "71603ccb1cd76d73d76eb6cfd5f0b9df6d65d90d76860ee52cb461c4be7032e8", + "version": 1, + "locktime": 0, + "vin": [ + { + "txid": "5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f", + "vout": 0, + "scriptSig": { + "asm": "", + "hex": "" + }, + "sequence": 4294967293 + } + ], + "vout": [ + { + "value": 0.18, + "n": 0, + "scriptPubKey": { + "asm": "OP_DUP OP_HASH160 1fc11f39be1729bf973a7ab6a615ca4729d64574 OP_EQUALVERIFY OP_CHECKSIG", + "hex": "76a9141fc11f39be1729bf973a7ab6a615ca4729d6457488ac", + "reqSigs": 1, + "type": "pubkeyhash", + "addresses": [ + "13tuJJDR2RgArmgfv6JScSdreahzgc4T6o" + ] + } + } + ], + "hex": "01000000011f5c38dfcf6f1a5f5a87c416076d392c87e6d41970d5ad5e477a02d66bde97580000000000fdffffff0180a81201000000001976a9141fc11f39be1729bf973a7ab6a615ca4729d6457488ac00000000" +} diff --git a/src/test/data/txcreatedata_seq1.json b/src/test/data/txcreatedata_seq1.json new file mode 100644 index 0000000000..33585d6dfa --- /dev/null +++ b/src/test/data/txcreatedata_seq1.json @@ -0,0 +1,41 @@ +{ + "txid": "c4dea671b0d7b48f8ab10bc46650e8329d3c5766931f548f513847a19f5ba75b", + "version": 1, + "locktime": 0, + "vin": [ + { + "txid": "5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f", + "vout": 0, + "scriptSig": { + "asm": "", + "hex": "" + }, + "sequence": 4294967293 + }, + { + "txid": "5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f", + "vout": 0, + "scriptSig": { + "asm": "", + "hex": "" + }, + "sequence": 1 + } + ], + "vout": [ + { + "value": 0.18, + "n": 0, + "scriptPubKey": { + "asm": "OP_DUP OP_HASH160 1fc11f39be1729bf973a7ab6a615ca4729d64574 OP_EQUALVERIFY OP_CHECKSIG", + "hex": "76a9141fc11f39be1729bf973a7ab6a615ca4729d6457488ac", + "reqSigs": 1, + "type": "pubkeyhash", + "addresses": [ + "13tuJJDR2RgArmgfv6JScSdreahzgc4T6o" + ] + } + } + ], + "hex": "01000000021f5c38dfcf6f1a5f5a87c416076d392c87e6d41970d5ad5e477a02d66bde97580000000000fdffffff1f5c38dfcf6f1a5f5a87c416076d392c87e6d41970d5ad5e477a02d66bde97580000000000010000000180a81201000000001976a9141fc11f39be1729bf973a7ab6a615ca4729d6457488ac00000000" +} diff --git a/src/test/data/txcreatesign.json b/src/test/data/txcreatesign.json new file mode 100644 index 0000000000..057fe9b010 --- /dev/null +++ b/src/test/data/txcreatesign.json @@ -0,0 +1,32 @@ +{ + "txid": "977e7cd286cb72cd470d539ba6cb48400f8f387d97451d45cdb8819437a303af", + "version": 1, + "locktime": 0, + "vin": [ + { + "txid": "4d49a71ec9da436f71ec4ee231d04f292a29cd316f598bb7068feccabdc59485", + "vout": 0, + "scriptSig": { + "asm": "304502210096a75056c9e2cc62b7214777b3d2a592cfda7092520126d4ebfcd6d590c99bd8022051bb746359cf98c0603f3004477eac68701132380db8facba19c89dc5ab5c5e2[ALL] 0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8", + "hex": "48304502210096a75056c9e2cc62b7214777b3d2a592cfda7092520126d4ebfcd6d590c99bd8022051bb746359cf98c0603f3004477eac68701132380db8facba19c89dc5ab5c5e201410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8" + }, + "sequence": 4294967295 + } + ], + "vout": [ + { + "value": 0.001, + "n": 0, + "scriptPubKey": { + "asm": "OP_DUP OP_HASH160 5834479edbbe0539b31ffd3a8f8ebadc2165ed01 OP_EQUALVERIFY OP_CHECKSIG", + "hex": "76a9145834479edbbe0539b31ffd3a8f8ebadc2165ed0188ac", + "reqSigs": 1, + "type": "pubkeyhash", + "addresses": [ + "193P6LtvS4nCnkDvM9uXn1gsSRqh4aDAz7" + ] + } + } + ], + "hex": "01000000018594c5bdcaec8f06b78b596f31cd292a294fd031e24eec716f43dac91ea7494d000000008b48304502210096a75056c9e2cc62b7214777b3d2a592cfda7092520126d4ebfcd6d590c99bd8022051bb746359cf98c0603f3004477eac68701132380db8facba19c89dc5ab5c5e201410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ffffffff01a0860100000000001976a9145834479edbbe0539b31ffd3a8f8ebadc2165ed0188ac00000000" +} diff --git a/src/test/net_tests.cpp b/src/test/net_tests.cpp index bc9a98ab04..4a7d6e778f 100644 --- a/src/test/net_tests.cpp +++ b/src/test/net_tests.cpp @@ -62,11 +62,11 @@ public: } }; -CDataStream AddrmanToStream(CAddrManSerializationMock& addrman) +CDataStream AddrmanToStream(CAddrManSerializationMock& _addrman) { CDataStream ssPeersIn(SER_DISK, CLIENT_VERSION); ssPeersIn << FLATDATA(Params().MessageStart()); - ssPeersIn << addrman; + ssPeersIn << _addrman; std::string str = ssPeersIn.str(); vector<unsigned char> vchData(str.begin(), str.end()); return CDataStream(vchData, SER_DISK, CLIENT_VERSION); @@ -164,12 +164,12 @@ BOOST_AUTO_TEST_CASE(cnode_simple_test) bool fInboundIn = false; // Test that fFeeler is false by default. - CNode* pnode1 = new CNode(id++, NODE_NETWORK, height, hSocket, addr, pszDest, fInboundIn); + CNode* pnode1 = new CNode(id++, NODE_NETWORK, height, hSocket, addr, 0, pszDest, fInboundIn); BOOST_CHECK(pnode1->fInbound == false); BOOST_CHECK(pnode1->fFeeler == false); fInboundIn = true; - CNode* pnode2 = new CNode(id++, NODE_NETWORK, height, hSocket, addr, pszDest, fInboundIn); + CNode* pnode2 = new CNode(id++, NODE_NETWORK, height, hSocket, addr, 1, pszDest, fInboundIn); BOOST_CHECK(pnode2->fInbound == true); BOOST_CHECK(pnode2->fFeeler == false); } diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp index 5a9aaf9bc0..7971b5122f 100644 --- a/src/test/script_tests.cpp +++ b/src/test/script_tests.cpp @@ -89,6 +89,8 @@ static ScriptErrorDesc script_errors[]={ {SCRIPT_ERR_SIG_NULLDUMMY, "SIG_NULLDUMMY"}, {SCRIPT_ERR_PUBKEYTYPE, "PUBKEYTYPE"}, {SCRIPT_ERR_CLEANSTACK, "CLEANSTACK"}, + {SCRIPT_ERR_MINIMALIF, "MINIMALIF"}, + {SCRIPT_ERR_SIG_NULLFAIL, "NULLFAIL"}, {SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS, "DISCOURAGE_UPGRADABLE_NOPS"}, {SCRIPT_ERR_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM, "DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM"}, {SCRIPT_ERR_WITNESS_PROGRAM_WRONG_LENGTH, "WITNESS_PROGRAM_WRONG_LENGTH"}, @@ -323,10 +325,10 @@ public: return *this; } - TestBuilder& Add(const CScript& script) + TestBuilder& Add(const CScript& _script) { DoPush(); - spendTx.vin[0].scriptSig += script; + spendTx.vin[0].scriptSig += _script; return *this; } @@ -343,8 +345,8 @@ public: return *this; } - TestBuilder& Push(const CScript& script) { - DoPush(std::vector<unsigned char>(script.begin(), script.end())); + TestBuilder& Push(const CScript& _script) { + DoPush(std::vector<unsigned char>(_script.begin(), _script.end())); return *this; } diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp index b1ceef4f64..02843d8525 100644 --- a/src/test/test_bitcoin.cpp +++ b/src/test/test_bitcoin.cpp @@ -72,7 +72,7 @@ TestingSetup::TestingSetup(const std::string& chainName) : BasicTestingSetup(cha nScriptCheckThreads = 3; for (int i=0; i < nScriptCheckThreads-1; i++) threadGroup.create_thread(&ThreadScriptCheck); - g_connman = std::unique_ptr<CConnman>(new CConnman()); + g_connman = std::unique_ptr<CConnman>(new CConnman(0x1337, 0x1337)); // Deterministic randomness for tests. connman = g_connman.get(); RegisterNodeSignals(GetNodeSignals()); } diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp index b5af400bc5..6163d2f630 100644 --- a/src/test/transaction_tests.cpp +++ b/src/test/transaction_tests.cpp @@ -50,6 +50,8 @@ static std::map<string, unsigned int> mapFlagNames = boost::assign::map_list_of (string("NULLDUMMY"), (unsigned int)SCRIPT_VERIFY_NULLDUMMY) (string("DISCOURAGE_UPGRADABLE_NOPS"), (unsigned int)SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) (string("CLEANSTACK"), (unsigned int)SCRIPT_VERIFY_CLEANSTACK) + (string("MINIMALIF"), (unsigned int)SCRIPT_VERIFY_MINIMALIF) + (string("NULLFAIL"), (unsigned int)SCRIPT_VERIFY_NULLFAIL) (string("CHECKLOCKTIMEVERIFY"), (unsigned int)SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY) (string("CHECKSEQUENCEVERIFY"), (unsigned int)SCRIPT_VERIFY_CHECKSEQUENCEVERIFY) (string("WITNESS"), (unsigned int)SCRIPT_VERIFY_WITNESS) diff --git a/src/torcontrol.cpp b/src/torcontrol.cpp index 99c45d489c..1ca6b46566 100644 --- a/src/torcontrol.cpp +++ b/src/torcontrol.cpp @@ -122,8 +122,8 @@ private: static void eventcb(struct bufferevent *bev, short what, void *ctx); }; -TorControlConnection::TorControlConnection(struct event_base *base): - base(base), b_conn(0) +TorControlConnection::TorControlConnection(struct event_base *_base): + base(_base), b_conn(0) { } @@ -194,7 +194,7 @@ void TorControlConnection::eventcb(struct bufferevent *bev, short what, void *ct } } -bool TorControlConnection::Connect(const std::string &target, const ConnectionCB& connected, const ConnectionCB& disconnected) +bool TorControlConnection::Connect(const std::string &target, const ConnectionCB& _connected, const ConnectionCB& _disconnected) { if (b_conn) Disconnect(); @@ -213,8 +213,8 @@ bool TorControlConnection::Connect(const std::string &target, const ConnectionCB return false; bufferevent_setcb(b_conn, TorControlConnection::readcb, NULL, TorControlConnection::eventcb, this); bufferevent_enable(b_conn, EV_READ|EV_WRITE); - this->connected = connected; - this->disconnected = disconnected; + this->connected = _connected; + this->disconnected = _disconnected; // Finally, connect to target if (bufferevent_socket_connect(b_conn, (struct sockaddr*)&connect_to_addr, connect_to_addrlen) < 0) { @@ -394,18 +394,18 @@ private: static void reconnect_cb(evutil_socket_t fd, short what, void *arg); }; -TorController::TorController(struct event_base* baseIn, const std::string& target): - base(baseIn), - target(target), conn(base), reconnect(true), reconnect_ev(0), +TorController::TorController(struct event_base* _base, const std::string& _target): + base(_base), + target(_target), conn(base), reconnect(true), reconnect_ev(0), reconnect_timeout(RECONNECT_TIMEOUT_START) { reconnect_ev = event_new(base, -1, 0, reconnect_cb, this); if (!reconnect_ev) LogPrintf("tor: Failed to create event for reconnection: out of memory?\n"); // Start connection attempts immediately - if (!conn.Connect(target, boost::bind(&TorController::connected_cb, this, _1), + if (!conn.Connect(_target, boost::bind(&TorController::connected_cb, this, _1), boost::bind(&TorController::disconnected_cb, this, _1) )) { - LogPrintf("tor: Initiating connection to Tor control port %s failed\n", target); + LogPrintf("tor: Initiating connection to Tor control port %s failed\n", _target); } // Read service private key if cached std::pair<bool,std::string> pkf = ReadBinaryFile(GetPrivateKeyFile()); @@ -426,7 +426,7 @@ TorController::~TorController() } } -void TorController::add_onion_cb(TorControlConnection& conn, const TorControlReply& reply) +void TorController::add_onion_cb(TorControlConnection& _conn, const TorControlReply& reply) { if (reply.code == 250) { LogPrint("tor", "tor: ADD_ONION successful\n"); @@ -454,7 +454,7 @@ void TorController::add_onion_cb(TorControlConnection& conn, const TorControlRep } } -void TorController::auth_cb(TorControlConnection& conn, const TorControlReply& reply) +void TorController::auth_cb(TorControlConnection& _conn, const TorControlReply& reply) { if (reply.code == 250) { LogPrint("tor", "tor: Authentication successful\n"); @@ -474,7 +474,7 @@ void TorController::auth_cb(TorControlConnection& conn, const TorControlReply& r // Request hidden service, redirect port. // Note that the 'virtual' port doesn't have to be the same as our internal port, but this is just a convenient // choice. TODO; refactor the shutdown sequence some day. - conn.Command(strprintf("ADD_ONION %s Port=%i,127.0.0.1:%i", private_key, GetListenPort(), GetListenPort()), + _conn.Command(strprintf("ADD_ONION %s Port=%i,127.0.0.1:%i", private_key, GetListenPort(), GetListenPort()), boost::bind(&TorController::add_onion_cb, this, _1, _2)); } else { LogPrintf("tor: Authentication failed\n"); @@ -508,7 +508,7 @@ static std::vector<uint8_t> ComputeResponse(const std::string &key, const std::v return computedHash; } -void TorController::authchallenge_cb(TorControlConnection& conn, const TorControlReply& reply) +void TorController::authchallenge_cb(TorControlConnection& _conn, const TorControlReply& reply) { if (reply.code == 250) { LogPrint("tor", "tor: SAFECOOKIE authentication challenge successful\n"); @@ -530,7 +530,7 @@ void TorController::authchallenge_cb(TorControlConnection& conn, const TorContro } std::vector<uint8_t> computedClientHash = ComputeResponse(TOR_SAFE_CLIENTKEY, cookie, clientNonce, serverNonce); - conn.Command("AUTHENTICATE " + HexStr(computedClientHash), boost::bind(&TorController::auth_cb, this, _1, _2)); + _conn.Command("AUTHENTICATE " + HexStr(computedClientHash), boost::bind(&TorController::auth_cb, this, _1, _2)); } else { LogPrintf("tor: Invalid reply to AUTHCHALLENGE\n"); } @@ -539,7 +539,7 @@ void TorController::authchallenge_cb(TorControlConnection& conn, const TorContro } } -void TorController::protocolinfo_cb(TorControlConnection& conn, const TorControlReply& reply) +void TorController::protocolinfo_cb(TorControlConnection& _conn, const TorControlReply& reply) { if (reply.code == 250) { std::set<std::string> methods; @@ -579,23 +579,23 @@ void TorController::protocolinfo_cb(TorControlConnection& conn, const TorControl if (methods.count("HASHEDPASSWORD")) { LogPrint("tor", "tor: Using HASHEDPASSWORD authentication\n"); boost::replace_all(torpassword, "\"", "\\\""); - conn.Command("AUTHENTICATE \"" + torpassword + "\"", boost::bind(&TorController::auth_cb, this, _1, _2)); + _conn.Command("AUTHENTICATE \"" + torpassword + "\"", boost::bind(&TorController::auth_cb, this, _1, _2)); } else { LogPrintf("tor: Password provided with -torpassword, but HASHEDPASSWORD authentication is not available\n"); } } else if (methods.count("NULL")) { LogPrint("tor", "tor: Using NULL authentication\n"); - conn.Command("AUTHENTICATE", boost::bind(&TorController::auth_cb, this, _1, _2)); + _conn.Command("AUTHENTICATE", boost::bind(&TorController::auth_cb, this, _1, _2)); } else if (methods.count("SAFECOOKIE")) { // Cookie: hexdump -e '32/1 "%02x""\n"' ~/.tor/control_auth_cookie LogPrint("tor", "tor: Using SAFECOOKIE authentication, reading cookie authentication from %s\n", cookiefile); std::pair<bool,std::string> status_cookie = ReadBinaryFile(cookiefile, TOR_COOKIE_SIZE); if (status_cookie.first && status_cookie.second.size() == TOR_COOKIE_SIZE) { - // conn.Command("AUTHENTICATE " + HexStr(status_cookie.second), boost::bind(&TorController::auth_cb, this, _1, _2)); + // _conn.Command("AUTHENTICATE " + HexStr(status_cookie.second), boost::bind(&TorController::auth_cb, this, _1, _2)); cookie = std::vector<uint8_t>(status_cookie.second.begin(), status_cookie.second.end()); clientNonce = std::vector<uint8_t>(TOR_NONCE_SIZE, 0); GetRandBytes(&clientNonce[0], TOR_NONCE_SIZE); - conn.Command("AUTHCHALLENGE SAFECOOKIE " + HexStr(clientNonce), boost::bind(&TorController::authchallenge_cb, this, _1, _2)); + _conn.Command("AUTHCHALLENGE SAFECOOKIE " + HexStr(clientNonce), boost::bind(&TorController::authchallenge_cb, this, _1, _2)); } else { if (status_cookie.first) { LogPrintf("tor: Authentication cookie %s is not exactly %i bytes, as is required by the spec\n", cookiefile, TOR_COOKIE_SIZE); @@ -613,15 +613,15 @@ void TorController::protocolinfo_cb(TorControlConnection& conn, const TorControl } } -void TorController::connected_cb(TorControlConnection& conn) +void TorController::connected_cb(TorControlConnection& _conn) { reconnect_timeout = RECONNECT_TIMEOUT_START; // First send a PROTOCOLINFO command to figure out what authentication is expected - if (!conn.Command("PROTOCOLINFO 1", boost::bind(&TorController::protocolinfo_cb, this, _1, _2))) + if (!_conn.Command("PROTOCOLINFO 1", boost::bind(&TorController::protocolinfo_cb, this, _1, _2))) LogPrintf("tor: Error sending initial protocolinfo command\n"); } -void TorController::disconnected_cb(TorControlConnection& conn) +void TorController::disconnected_cb(TorControlConnection& _conn) { // Stop advertising service when disconnected if (service.IsValid()) diff --git a/src/txmempool.cpp b/src/txmempool.cpp index 0a00d757a2..3586123d3e 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -1116,8 +1116,8 @@ void CTxMemPool::TrimToSize(size_t sizelimit, std::vector<uint256>* pvNoSpendsRe std::vector<CTransaction> txn; if (pvNoSpendsRemaining) { txn.reserve(stage.size()); - BOOST_FOREACH(txiter it, stage) - txn.push_back(it->GetTx()); + BOOST_FOREACH(txiter iter, stage) + txn.push_back(iter->GetTx()); } RemoveStaged(stage, false); if (pvNoSpendsRemaining) { @@ -1125,8 +1125,8 @@ void CTxMemPool::TrimToSize(size_t sizelimit, std::vector<uint256>* pvNoSpendsRe BOOST_FOREACH(const CTxIn& txin, tx.vin) { if (exists(txin.prevout.hash)) continue; - auto it = mapNextTx.lower_bound(COutPoint(txin.prevout.hash, 0)); - if (it == mapNextTx.end() || it->first->hash != txin.prevout.hash) + auto iter = mapNextTx.lower_bound(COutPoint(txin.prevout.hash, 0)); + if (iter == mapNextTx.end() || iter->first->hash != txin.prevout.hash) pvNoSpendsRemaining->push_back(txin.prevout.hash); } } diff --git a/src/txmempool.h b/src/txmempool.h index 2c2127f326..6f67dd91d6 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -328,14 +328,17 @@ struct TxMempoolInfo }; /** - * CTxMemPool stores valid-according-to-the-current-best-chain - * transactions that may be included in the next block. + * CTxMemPool stores valid-according-to-the-current-best-chain transactions + * that may be included in the next block. * - * Transactions are added when they are seen on the network - * (or created by the local node), but not all transactions seen - * are added to the pool: if a new transaction double-spends - * an input of a transaction in the pool, it is dropped, - * as are non-standard transactions. + * Transactions are added when they are seen on the network (or created by the + * local node), but not all transactions seen are added to the pool. For + * example, the following new transactions will not be added to the mempool: + * - a transaction which doesn't make the mimimum fee requirements. + * - a new transaction that double-spends an input of a transaction already in + * the pool where the new transaction does not meet the Replace-By-Fee + * requirements as defined in BIP 125. + * - a non-standard transaction. * * CTxMemPool::mapTx, and CTxMemPoolEntry bookkeeping: * diff --git a/src/ui_interface.cpp b/src/ui_interface.cpp index c778e40a90..74a13e0e05 100644 --- a/src/ui_interface.cpp +++ b/src/ui_interface.cpp @@ -18,6 +18,11 @@ void InitWarning(const std::string& str) uiInterface.ThreadSafeMessageBox(str, "", CClientUIInterface::MSG_WARNING); } +std::string AmountHighWarn(const std::string& optname) +{ + return strprintf(_("%s is set very high!"), optname); +} + std::string AmountErrMsg(const char* const optname, const std::string& strValue) { return strprintf(_("Invalid amount for -%s=<amount>: '%s'"), optname, strValue); diff --git a/src/ui_interface.h b/src/ui_interface.h index 7e6557f8e2..177ff238db 100644 --- a/src/ui_interface.h +++ b/src/ui_interface.h @@ -112,6 +112,8 @@ void InitWarning(const std::string& str); /** Show error message **/ bool InitError(const std::string& str); +std::string AmountHighWarn(const std::string& optname); + std::string AmountErrMsg(const char* const optname, const std::string& strValue); extern CClientUIInterface uiInterface; diff --git a/src/univalue/include/univalue.h b/src/univalue/include/univalue.h index 8428b1c683..e48b905bfb 100644 --- a/src/univalue/include/univalue.h +++ b/src/univalue/include/univalue.h @@ -56,7 +56,7 @@ public: bool setNumStr(const std::string& val); bool setInt(uint64_t val); bool setInt(int64_t val); - bool setInt(int val) { return setInt((int64_t)val); } + bool setInt(int val_) { return setInt((int64_t)val_); } bool setFloat(double val); bool setStr(const std::string& val); bool setArray(); @@ -95,28 +95,28 @@ public: bool push_backV(const std::vector<UniValue>& vec); bool pushKV(const std::string& key, const UniValue& val); - bool pushKV(const std::string& key, const std::string& val) { - UniValue tmpVal(VSTR, val); + bool pushKV(const std::string& key, const std::string& val_) { + UniValue tmpVal(VSTR, val_); return pushKV(key, tmpVal); } bool pushKV(const std::string& key, const char *val_) { - std::string val(val_); - return pushKV(key, val); + std::string _val(val_); + return pushKV(key, _val); } - bool pushKV(const std::string& key, int64_t val) { - UniValue tmpVal(val); + bool pushKV(const std::string& key, int64_t val_) { + UniValue tmpVal(val_); return pushKV(key, tmpVal); } - bool pushKV(const std::string& key, uint64_t val) { - UniValue tmpVal(val); + bool pushKV(const std::string& key, uint64_t val_) { + UniValue tmpVal(val_); return pushKV(key, tmpVal); } - bool pushKV(const std::string& key, int val) { - UniValue tmpVal((int64_t)val); + bool pushKV(const std::string& key, int val_) { + UniValue tmpVal((int64_t)val_); return pushKV(key, tmpVal); } - bool pushKV(const std::string& key, double val) { - UniValue tmpVal(val); + bool pushKV(const std::string& key, double val_) { + UniValue tmpVal(val_); return pushKV(key, tmpVal); } bool pushKVs(const UniValue& obj); diff --git a/src/univalue/lib/univalue.cpp b/src/univalue/lib/univalue.cpp index 0076d6678e..1f8cee6d29 100644 --- a/src/univalue/lib/univalue.cpp +++ b/src/univalue/lib/univalue.cpp @@ -119,32 +119,29 @@ bool UniValue::setNumStr(const string& val_) return true; } -bool UniValue::setInt(uint64_t val) +bool UniValue::setInt(uint64_t val_) { - string s; ostringstream oss; - oss << val; + oss << val_; return setNumStr(oss.str()); } -bool UniValue::setInt(int64_t val) +bool UniValue::setInt(int64_t val_) { - string s; ostringstream oss; - oss << val; + oss << val_; return setNumStr(oss.str()); } -bool UniValue::setFloat(double val) +bool UniValue::setFloat(double val_) { - string s; ostringstream oss; - oss << std::setprecision(16) << val; + oss << std::setprecision(16) << val_; bool ret = setNumStr(oss.str()); typ = VNUM; @@ -173,12 +170,12 @@ bool UniValue::setObject() return true; } -bool UniValue::push_back(const UniValue& val) +bool UniValue::push_back(const UniValue& val_) { if (typ != VARR) return false; - values.push_back(val); + values.push_back(val_); return true; } @@ -192,13 +189,13 @@ bool UniValue::push_backV(const std::vector<UniValue>& vec) return true; } -bool UniValue::pushKV(const std::string& key, const UniValue& val) +bool UniValue::pushKV(const std::string& key, const UniValue& val_) { if (typ != VOBJ) return false; keys.push_back(key); - values.push_back(val); + values.push_back(val_); return true; } @@ -228,7 +225,7 @@ int UniValue::findKey(const std::string& key) const bool UniValue::checkObject(const std::map<std::string,UniValue::VType>& t) { for (std::map<std::string,UniValue::VType>::const_iterator it = t.begin(); - it != t.end(); it++) { + it != t.end(); ++it) { int idx = findKey(it->first); if (idx < 0) return false; diff --git a/src/util.cpp b/src/util.cpp index c7d147a11e..93cc0412b5 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -600,19 +600,19 @@ bool TryCreateDirectory(const boost::filesystem::path& p) return false; } -void FileCommit(FILE *fileout) +void FileCommit(FILE *file) { - fflush(fileout); // harmless if redundantly called + fflush(file); // harmless if redundantly called #ifdef WIN32 - HANDLE hFile = (HANDLE)_get_osfhandle(_fileno(fileout)); + HANDLE hFile = (HANDLE)_get_osfhandle(_fileno(file)); FlushFileBuffers(hFile); #else #if defined(__linux__) || defined(__NetBSD__) - fdatasync(fileno(fileout)); + fdatasync(fileno(file)); #elif defined(__APPLE__) && defined(F_FULLFSYNC) - fcntl(fileno(fileout), F_FULLFSYNC, 0); + fcntl(fileno(file), F_FULLFSYNC, 0); #else - fsync(fileno(fileout)); + fsync(fileno(file)); #endif #endif } diff --git a/src/util.h b/src/util.h index 39328b51ef..45b3658557 100644 --- a/src/util.h +++ b/src/util.h @@ -93,7 +93,7 @@ bool error(const char* fmt, const Args&... args) void PrintExceptionContinue(const std::exception *pex, const char* pszThread); void ParseParameters(int argc, const char*const argv[]); -void FileCommit(FILE *fileout); +void FileCommit(FILE *file); bool TruncateFile(FILE *file, unsigned int length); int RaiseFileDescriptorLimit(int nMinFD); void AllocateFileRange(FILE *file, unsigned int offset, unsigned int length); diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index 42ebdb9b9b..e80fa7dff8 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -344,8 +344,6 @@ UniValue removeprunedfunds(const UniValue& params, bool fHelp) throw JSONRPCError(RPC_INTERNAL_ERROR, "Transaction does not exist in wallet."); } - ThreadFlushWalletDB(pwalletMain->strWalletFile); - return NullUniValue; } diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index a399f8ad9f..3eb7e5d9ba 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -1093,6 +1093,8 @@ UniValue addwitnessaddress(const UniValue& params, bool fHelp) throw JSONRPCError(RPC_WALLET_ERROR, "Public key or redeemscript not known to wallet"); } + pwalletMain->SetAddressBook(w.result, "", "receive"); + return CBitcoinAddress(w.result).ToString(); } @@ -2628,6 +2630,9 @@ static const CRPCCommand commands[] = void RegisterWalletRPCCommands(CRPCTable &t) { + if (GetBoolArg("-disablewallet", false)) + return; + for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++) t.appendCommand(commands[vcidx].name, &commands[vcidx]); } diff --git a/src/wallet/test/accounting_tests.cpp b/src/wallet/test/accounting_tests.cpp index a6cada46a2..a833be13d0 100644 --- a/src/wallet/test/accounting_tests.cpp +++ b/src/wallet/test/accounting_tests.cpp @@ -3,7 +3,6 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "wallet/wallet.h" -#include "wallet/walletdb.h" #include "wallet/test/wallet_test_fixture.h" @@ -17,13 +16,13 @@ extern CWallet* pwalletMain; BOOST_FIXTURE_TEST_SUITE(accounting_tests, WalletTestingSetup) static void -GetResults(CWalletDB& walletdb, std::map<CAmount, CAccountingEntry>& results) +GetResults(std::map<CAmount, CAccountingEntry>& results) { std::list<CAccountingEntry> aes; results.clear(); - BOOST_CHECK(walletdb.ReorderTransactions(pwalletMain) == DB_LOAD_OK); - walletdb.ListAccountCreditDebit("", aes); + BOOST_CHECK(pwalletMain->ReorderTransactions() == DB_LOAD_OK); + pwalletMain->ListAccountCreditDebit("", aes); BOOST_FOREACH(CAccountingEntry& ae, aes) { results[ae.nOrderPos] = ae; @@ -32,7 +31,6 @@ GetResults(CWalletDB& walletdb, std::map<CAmount, CAccountingEntry>& results) BOOST_AUTO_TEST_CASE(acc_orderupgrade) { - CWalletDB walletdb(pwalletMain->strWalletFile); std::vector<CWalletTx*> vpwtx; CWalletTx wtx; CAccountingEntry ae; @@ -45,7 +43,7 @@ BOOST_AUTO_TEST_CASE(acc_orderupgrade) ae.nTime = 1333333333; ae.strOtherAccount = "b"; ae.strComment = ""; - pwalletMain->AddAccountingEntry(ae, walletdb); + pwalletMain->AddAccountingEntry(ae); wtx.mapValue["comment"] = "z"; pwalletMain->AddToWallet(wtx); @@ -55,9 +53,9 @@ BOOST_AUTO_TEST_CASE(acc_orderupgrade) ae.nTime = 1333333336; ae.strOtherAccount = "c"; - pwalletMain->AddAccountingEntry(ae, walletdb); + pwalletMain->AddAccountingEntry(ae); - GetResults(walletdb, results); + GetResults(results); BOOST_CHECK(pwalletMain->nOrderPosNext == 3); BOOST_CHECK(2 == results.size()); @@ -71,9 +69,9 @@ BOOST_AUTO_TEST_CASE(acc_orderupgrade) ae.nTime = 1333333330; ae.strOtherAccount = "d"; ae.nOrderPos = pwalletMain->IncOrderPosNext(); - pwalletMain->AddAccountingEntry(ae, walletdb); + pwalletMain->AddAccountingEntry(ae); - GetResults(walletdb, results); + GetResults(results); BOOST_CHECK(results.size() == 3); BOOST_CHECK(pwalletMain->nOrderPosNext == 4); @@ -105,7 +103,7 @@ BOOST_AUTO_TEST_CASE(acc_orderupgrade) vpwtx[2]->nTimeReceived = (unsigned int)1333333329; vpwtx[2]->nOrderPos = -1; - GetResults(walletdb, results); + GetResults(results); BOOST_CHECK(results.size() == 3); BOOST_CHECK(pwalletMain->nOrderPosNext == 6); @@ -121,9 +119,9 @@ BOOST_AUTO_TEST_CASE(acc_orderupgrade) ae.nTime = 1333333334; ae.strOtherAccount = "e"; ae.nOrderPos = -1; - pwalletMain->AddAccountingEntry(ae, walletdb); + pwalletMain->AddAccountingEntry(ae); - GetResults(walletdb, results); + GetResults(results); BOOST_CHECK(results.size() == 4); BOOST_CHECK(pwalletMain->nOrderPosNext == 7); diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index a8ef6d9511..43e22383f4 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -40,6 +40,7 @@ CFeeRate payTxFee(DEFAULT_TRANSACTION_FEE); unsigned int nTxConfirmTarget = DEFAULT_TX_CONFIRM_TARGET; bool bSpendZeroConfChange = DEFAULT_SPEND_ZEROCONF_CHANGE; bool fSendFreeTransactions = DEFAULT_SEND_FREE_TRANSACTIONS; +bool fWalletRbf = DEFAULT_WALLET_RBF; const char * DEFAULT_WALLET_DAT = "wallet.dat"; const uint32_t BIP32_HARDENED_KEY_LIMIT = 0x80000000; @@ -400,8 +401,8 @@ set<uint256> CWallet::GetConflicts(const uint256& txid) const if (mapTxSpends.count(txin.prevout) <= 1) continue; // No conflict if zero or one spends range = mapTxSpends.equal_range(txin.prevout); - for (TxSpends::const_iterator it = range.first; it != range.second; ++it) - result.insert(it->second); + for (TxSpends::const_iterator _it = range.first; _it != range.second; ++_it) + result.insert(_it->second); } return result; } @@ -413,6 +414,9 @@ void CWallet::Flush(bool shutdown) bool CWallet::Verify() { + if (GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)) + return true; + LogPrintf("Using BerkeleyDB version %s\n", DbEnv::version(0, 0, 0)); std::string walletFile = GetArg("-wallet", DEFAULT_WALLET_DAT); @@ -648,6 +652,12 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase) return true; } +DBErrors CWallet::ReorderTransactions() +{ + CWalletDB walletdb(strWalletFile); + return walletdb.ReorderTransactions(this); +} + int64_t CWallet::IncOrderPosNext(CWalletDB *pwalletdb) { AssertLockHeld(cs_wallet); // nOrderPosNext @@ -676,7 +686,7 @@ bool CWallet::AccountMove(std::string strFrom, std::string strTo, CAmount nAmoun debit.nTime = nNow; debit.strOtherAccount = strTo; debit.strComment = strComment; - AddAccountingEntry(debit, walletdb); + AddAccountingEntry(debit, &walletdb); // Credit CAccountingEntry credit; @@ -686,7 +696,7 @@ bool CWallet::AccountMove(std::string strFrom, std::string strTo, CAmount nAmoun credit.nTime = nNow; credit.strOtherAccount = strFrom; credit.strComment = strComment; - AddAccountingEntry(credit, walletdb); + AddAccountingEntry(credit, &walletdb); if (!walletdb.TxnCommit()) return false; @@ -1271,9 +1281,9 @@ int CWalletTx::GetRequestCount() const // How about the block it's in? if (nRequests == 0 && !hashUnset()) { - map<uint256, int>::const_iterator mi = pwallet->mapRequestCount.find(hashBlock); - if (mi != pwallet->mapRequestCount.end()) - nRequests = (*mi).second; + map<uint256, int>::const_iterator _mi = pwallet->mapRequestCount.find(hashBlock); + if (_mi != pwallet->mapRequestCount.end()) + nRequests = (*_mi).second; else nRequests = 1; // If it's in someone else's block it must have got out } @@ -2362,11 +2372,17 @@ bool CWallet::CreateTransaction(const vector<CRecipient>& vecSend, CWalletTx& wt // Fill vin // - // Note how the sequence number is set to max()-1 so that the - // nLockTime set above actually works. + // Note how the sequence number is set to non-maxint so that + // the nLockTime set above actually works. + // + // BIP125 defines opt-in RBF as any nSequence < maxint-1, so + // we use the highest possible value in that range (maxint-2) + // to avoid conflicting with other possible uses of nSequence, + // and in the spirit of "smallest posible change from prior + // behavior." BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins) txNew.vin.push_back(CTxIn(coin.first->GetHash(),coin.second,CScript(), - std::numeric_limits<unsigned int>::max()-1)); + std::numeric_limits<unsigned int>::max() - (fWalletRbf ? 2 : 1))); // Sign int nIn = 0; @@ -2494,9 +2510,21 @@ bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey, CCon return true; } -bool CWallet::AddAccountingEntry(const CAccountingEntry& acentry, CWalletDB & pwalletdb) +void CWallet::ListAccountCreditDebit(const std::string& strAccount, std::list<CAccountingEntry>& entries) { + CWalletDB walletdb(strWalletFile); + return walletdb.ListAccountCreditDebit(strAccount, entries); +} + +bool CWallet::AddAccountingEntry(const CAccountingEntry& acentry) +{ + CWalletDB walletdb(strWalletFile); + + return AddAccountingEntry(acentry, &walletdb); +} + +bool CWallet::AddAccountingEntry(const CAccountingEntry& acentry, CWalletDB *pwalletdb) { - if (!pwalletdb.WriteAccountingEntry_Backend(acentry)) + if (!pwalletdb->WriteAccountingEntry_Backend(acentry)) return false; laccentries.push_back(acentry); @@ -2910,17 +2938,17 @@ set< set<CTxDestination> > CWallet::GetAddressGroupings() set< set<CTxDestination>* > uniqueGroupings; // a set of pointers to groups of addresses map< CTxDestination, set<CTxDestination>* > setmap; // map addresses to the unique group containing it - BOOST_FOREACH(set<CTxDestination> grouping, groupings) + BOOST_FOREACH(set<CTxDestination> _grouping, groupings) { // make a set of all the groups hit by this new group set< set<CTxDestination>* > hits; map< CTxDestination, set<CTxDestination>* >::iterator it; - BOOST_FOREACH(CTxDestination address, grouping) + BOOST_FOREACH(CTxDestination address, _grouping) if ((it = setmap.find(address)) != setmap.end()) hits.insert((*it).second); // merge all hit groups into a new single group and delete old groups - set<CTxDestination>* merged = new set<CTxDestination>(grouping); + set<CTxDestination>* merged = new set<CTxDestination>(_grouping); BOOST_FOREACH(set<CTxDestination>* hit, hits) { merged->insert(hit->begin(), hit->end()); @@ -3246,6 +3274,7 @@ std::string CWallet::GetWalletHelpString(bool showDebug) strUsage += HelpMessageOpt("-spendzeroconfchange", strprintf(_("Spend unconfirmed change when sending transactions (default: %u)"), DEFAULT_SPEND_ZEROCONF_CHANGE)); strUsage += HelpMessageOpt("-txconfirmtarget=<n>", strprintf(_("If paytxfee is not set, include enough fee so transactions begin confirmation on average within n blocks (default: %u)"), DEFAULT_TX_CONFIRM_TARGET)); strUsage += HelpMessageOpt("-usehd", _("Use hierarchical deterministic key generation (HD) after BIP32. Only has effect during wallet creation/first start") + " " + strprintf(_("(default: %u)"), DEFAULT_USE_HD_WALLET)); + strUsage += HelpMessageOpt("-walletrbf", strprintf(_("Send transactions with full-RBF opt-in enabled (default: %u)"), DEFAULT_WALLET_RBF)); strUsage += HelpMessageOpt("-upgradewallet", _("Upgrade wallet to latest format on startup")); strUsage += HelpMessageOpt("-wallet=<file>", _("Specify wallet file (within data directory)") + " " + strprintf(_("(default: %s)"), DEFAULT_WALLET_DAT)); strUsage += HelpMessageOpt("-walletbroadcast", _("Make the wallet broadcast transactions") + " " + strprintf(_("(default: %u)"), DEFAULT_WALLETBROADCAST)); @@ -3267,6 +3296,12 @@ std::string CWallet::GetWalletHelpString(bool showDebug) bool CWallet::InitLoadWallet() { + if (GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)) { + pwalletMain = NULL; + LogPrintf("Wallet disabled!\n"); + return true; + } + std::string walletFile = GetArg("-wallet", DEFAULT_WALLET_DAT); // needed to restore wallet transaction meta data after -zapwallettxes @@ -3438,13 +3473,31 @@ bool CWallet::InitLoadWallet() bool CWallet::ParameterInteraction() { + if (GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)) + return true; + + if (GetBoolArg("-blocksonly", DEFAULT_BLOCKSONLY) && SoftSetBoolArg("-walletbroadcast", false)) { + LogPrintf("%s: parameter interaction: -blocksonly=1 -> setting -walletbroadcast=0\n", __func__); + } + + if (GetBoolArg("-sysperms", false)) + return InitError("-sysperms is not allowed in combination with enabled wallet functionality"); + if (GetArg("-prune", 0) && GetBoolArg("-rescan", false)) + return InitError(_("Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again.")); + + if (::minRelayTxFee.GetFeePerK() > HIGH_TX_FEE_PER_KB) + InitWarning(AmountHighWarn("-minrelaytxfee") + " " + + _("The wallet will avoid paying less than the minimum relay fee.")); + if (mapArgs.count("-mintxfee")) { CAmount n = 0; - if (ParseMoney(mapArgs["-mintxfee"], n) && n > 0) - CWallet::minTxFee = CFeeRate(n); - else + if (!ParseMoney(mapArgs["-mintxfee"], n) || 0 == n) return InitError(AmountErrMsg("mintxfee", mapArgs["-mintxfee"])); + if (n > HIGH_TX_FEE_PER_KB) + InitWarning(AmountHighWarn("-mintxfee") + " " + + _("This is the minimum transaction fee you pay on every transaction.")); + CWallet::minTxFee = CFeeRate(n); } if (mapArgs.count("-fallbackfee")) { @@ -3452,7 +3505,8 @@ bool CWallet::ParameterInteraction() if (!ParseMoney(mapArgs["-fallbackfee"], nFeePerK)) return InitError(strprintf(_("Invalid amount for -fallbackfee=<amount>: '%s'"), mapArgs["-fallbackfee"])); if (nFeePerK > HIGH_TX_FEE_PER_KB) - InitWarning(_("-fallbackfee is set very high! This is the transaction fee you may pay when fee estimates are not available.")); + InitWarning(AmountHighWarn("-fallbackfee") + " " + + _("This is the transaction fee you may pay when fee estimates are not available.")); CWallet::fallbackFee = CFeeRate(nFeePerK); } if (mapArgs.count("-paytxfee")) @@ -3461,7 +3515,9 @@ bool CWallet::ParameterInteraction() if (!ParseMoney(mapArgs["-paytxfee"], nFeePerK)) return InitError(AmountErrMsg("paytxfee", mapArgs["-paytxfee"])); if (nFeePerK > HIGH_TX_FEE_PER_KB) - InitWarning(_("-paytxfee is set very high! This is the transaction fee you will pay if you send a transaction.")); + InitWarning(AmountHighWarn("-paytxfee") + " " + + _("This is the transaction fee you will pay if you send a transaction.")); + payTxFee = CFeeRate(nFeePerK, 1000); if (payTxFee < ::minRelayTxFee) { @@ -3486,6 +3542,7 @@ bool CWallet::ParameterInteraction() nTxConfirmTarget = GetArg("-txconfirmtarget", DEFAULT_TX_CONFIRM_TARGET); bSpendZeroConfChange = GetBoolArg("-spendzeroconfchange", DEFAULT_SPEND_ZEROCONF_CHANGE); fSendFreeTransactions = GetBoolArg("-sendfreetransactions", DEFAULT_SEND_FREE_TRANSACTIONS); + fWalletRbf = GetBoolArg("-walletrbf", DEFAULT_WALLET_RBF); return true; } diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 016e4a3d74..c700e0ca7c 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -37,6 +37,7 @@ extern CFeeRate payTxFee; extern unsigned int nTxConfirmTarget; extern bool bSpendZeroConfChange; extern bool fSendFreeTransactions; +extern bool fWalletRbf; static const unsigned int DEFAULT_KEYPOOL_SIZE = 100; //! -paytxfee default @@ -53,10 +54,12 @@ static const bool DEFAULT_SPEND_ZEROCONF_CHANGE = true; static const bool DEFAULT_SEND_FREE_TRANSACTIONS = false; //! -txconfirmtarget default static const unsigned int DEFAULT_TX_CONFIRM_TARGET = 2; +//! -walletrbf default +static const bool DEFAULT_WALLET_RBF = false; //! Largest (in bytes) free transaction we're willing to create static const unsigned int MAX_FREE_TRANSACTION_CREATE_SIZE = 1000; static const bool DEFAULT_WALLETBROADCAST = true; - +static const bool DEFAULT_DISABLE_WALLET = false; //! if set, all keys will be derived by using BIP32 static const bool DEFAULT_USE_HD_WALLET = true; @@ -737,6 +740,7 @@ public: * @return next transaction order id */ int64_t IncOrderPosNext(CWalletDB *pwalletdb = NULL); + DBErrors ReorderTransactions(); bool AccountMove(std::string strFrom, std::string strTo, CAmount nAmount, std::string strComment = ""); bool GetAccountPubkey(CPubKey &pubKey, std::string strAccount, bool bForceNew = false); @@ -771,7 +775,9 @@ public: std::string& strFailReason, const CCoinControl *coinControl = NULL, bool sign = true); bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey, CConnman* connman); - bool AddAccountingEntry(const CAccountingEntry&, CWalletDB & pwalletdb); + void ListAccountCreditDebit(const std::string& strAccount, std::list<CAccountingEntry>& entries); + bool AddAccountingEntry(const CAccountingEntry&); + bool AddAccountingEntry(const CAccountingEntry&, CWalletDB *pwalletdb); static CFeeRate minTxFee; static CFeeRate fallbackFee; |