diff options
550 files changed, 9361 insertions, 6827 deletions
diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 811a246df1..55cebc008f 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -1,23 +1,21 @@ -<!--- Remove sections that do not apply --> +<!-- This issue tracker is only for technical issues related to Bitcoin Core. -This issue tracker is only for technical issues related to Bitcoin Core. +General bitcoin questions and/or support requests are best directed to the Bitcoin StackExchange at https://bitcoin.stackexchange.com. -General bitcoin questions and/or support requests are best directed to the [Bitcoin StackExchange](https://bitcoin.stackexchange.com). +For reporting security issues, please read instructions at https://bitcoincore.org/en/contact/. -For reporting security issues, please read instructions at [https://bitcoincore.org/en/contact/](https://bitcoincore.org/en/contact/). +If the node is "stuck" during sync or giving "block checksum mismatch" errors, please ensure your hardware is stable by running memtest and observe CPU temperature with a load-test tool such as linpack before creating an issue! --> -If the node is "stuck" during sync or giving "block checksum mismatch" errors, please ensure your hardware is stable by running memtest and observe CPU temperature with a load-test tool such as linpack before creating an issue! +<!-- Describe the issue --> +<!--- What behavior did you expect? --> -### Describe the issue -#### What behavior did you expect? +<!--- What was the actual behavior (provide screenshots if the issue is GUI-related)? --> -#### What was the actual behavior (provide screenshots if the issue is GUI-related)? +<!--- How reliably can you reproduce the issue, what are the steps to do so? --> -#### How reliably can you reproduce the issue, what are the steps to do so? +<!-- What version of Bitcoin Core are you using, where did you get it (website, self-compiled, etc)? --> -### What version of Bitcoin Core are you using, where did you get it (website, self-compiled, etc)? +<!-- What type of machine are you observing the error on (OS/CPU and disk type)? --> -### What type of machine are you observing the error on (OS/CPU and disk type)? - -### Any extra information that might be useful in the debugging process. -This is normally the contents of a `debug.log` or `config.log` file. Raw text or a link to a pastebin type site are preferred. +<!-- Any extra information that might be useful in the debugging process. --> +<!--- This is normally the contents of a `debug.log` or `config.log` file. Raw text or a link to a pastebin type site are preferred. --> diff --git a/.travis.yml b/.travis.yml index a643d2ff5d..0332a0e204 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,11 +18,10 @@ env: - CCACHE_COMPRESS=1 - BASE_OUTDIR=$TRAVIS_BUILD_DIR/out - SDK_URL=https://bitcoincore.org/depends-sources/sdks - - PYTHON_DEBUG=1 - WINEDEBUG=fixme-all matrix: # ARM - - HOST=arm-linux-gnueabihf PACKAGES="g++-arm-linux-gnueabihf" DEP_OPTS="NO_QT=1" CHECK_DOC=1 GOAL="install" BITCOIN_CONFIG="--enable-glibc-back-compat --enable-reduce-exports" + - HOST=arm-linux-gnueabihf PACKAGES="g++-arm-linux-gnueabihf python3-pip" DEP_OPTS="NO_QT=1" CHECK_DOC=1 GOAL="install" BITCOIN_CONFIG="--enable-glibc-back-compat --enable-reduce-exports" # Win32 - HOST=i686-w64-mingw32 DPKG_ADD_ARCH="i386" DEP_OPTS="NO_QT=1" PACKAGES="python3 nsis g++-mingw-w64-i686 wine1.6" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-reduce-exports" # Qt4 & system libs @@ -44,6 +43,7 @@ install: - if [ -n "$DPKG_ADD_ARCH" ]; then sudo dpkg --add-architecture "$DPKG_ADD_ARCH" ; fi - if [ -n "$PACKAGES" ]; then travis_retry sudo apt-get update; fi - if [ -n "$PACKAGES" ]; then travis_retry sudo apt-get install --no-install-recommends --no-upgrade -qq $PACKAGES; fi + - if [ "$CHECK_DOC" = 1 -a "$TRAVIS_EVENT_TYPE" = "pull_request" ]; then travis_retry pip3 install flake8 --user; fi before_script: - if [ "$CHECK_DOC" = 1 -a "$TRAVIS_EVENT_TYPE" = "pull_request" ]; then contrib/devtools/commit-script-check.sh $TRAVIS_COMMIT_RANGE; fi - if [ "$CHECK_DOC" = 1 ]; then contrib/devtools/git-subtree-check.sh src/crypto/ctaes; fi @@ -78,8 +78,8 @@ script: - make $MAKEJOBS $GOAL || ( echo "Build failure. Verbose build follows." && make $GOAL V=1 ; false ) - export LD_LIBRARY_PATH=$TRAVIS_BUILD_DIR/depends/$HOST/lib - if [ "$RUN_TESTS" = "true" ]; then travis_wait 30 make $MAKEJOBS check VERBOSE=1; fi - - if [ "$TRAVIS_EVENT_TYPE" = "cron" ]; then extended="--extended --exclude pruning,dbcrash"; fi - - if [ "$RUN_TESTS" = "true" ]; then test/functional/test_runner.py --coverage --quiet ${extended}; fi + - if [ "$TRAVIS_EVENT_TYPE" = "cron" ]; then extended="--extended --exclude feature_pruning,feature_dbcrash"; fi + - if [ "$RUN_TESTS" = "true" ]; then test/functional/test_runner.py --combinedlogslen=4000 --coverage --quiet ${extended}; fi after_script: - echo $TRAVIS_COMMIT_RANGE - echo $TRAVIS_COMMIT_LOG diff --git a/.tx/config b/.tx/config index c4eb6d831f..3a7c825a76 100644 --- a/.tx/config +++ b/.tx/config @@ -1,7 +1,7 @@ [main] host = https://www.transifex.com -[bitcoin.qt-translation-014x] +[bitcoin.qt-translation-016x] file_filter = src/qt/locale/bitcoin_<lang>.ts source_file = src/qt/locale/bitcoin_en.ts source_lang = en diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9f95d3f818..8381bd2448 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -186,7 +186,7 @@ In general, all pull requests must: the project (for example refactoring for modularisation); - Be well peer reviewed; - Have unit tests and functional tests where appropriate; - - Follow code style guidelines; + - Follow code style guidelines ([C++](doc/developer-notes.md), [functional tests](test/functional/README.md)); - Not break the existing test suite; - Where bugs are fixed, where possible, there should be unit tests demonstrating the bug and also proving the fix. This helps prevent regression. @@ -1,7 +1,7 @@ The MIT License (MIT) -Copyright (c) 2009-2017 The Bitcoin Core developers -Copyright (c) 2009-2017 Bitcoin Developers +Copyright (c) 2009-2018 The Bitcoin Core developers +Copyright (c) 2009-2018 Bitcoin Developers Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Makefile.am b/Makefile.am index 9b791cc0e8..b24daf9905 100644 --- a/Makefile.am +++ b/Makefile.am @@ -46,7 +46,7 @@ DIST_CONTRIB = $(top_srcdir)/contrib/bitcoin-cli.bash-completion \ $(top_srcdir)/contrib/rpm DIST_SHARE = \ $(top_srcdir)/share/genbuild.sh \ - $(top_srcdir)/share/rpcuser + $(top_srcdir)/share/rpcauth BIN_CHECKS=$(top_srcdir)/contrib/devtools/symbol-check.py \ $(top_srcdir)/contrib/devtools/security-check.py @@ -279,4 +279,4 @@ DISTCHECK_CONFIGURE_FLAGS = --enable-man clean-local: rm -rf coverage_percent.txt test_bitcoin.coverage/ total.coverage/ test/tmp/ cache/ $(OSX_APP) - rm -rf test/functional/__pycache__ + rm -rf test/functional/__pycache__ test/functional/test_framework/__pycache__ test/cache diff --git a/configure.ac b/configure.ac index 8e5561243a..256aed40b2 100644 --- a/configure.ac +++ b/configure.ac @@ -5,7 +5,7 @@ define(_CLIENT_VERSION_MINOR, 15) define(_CLIENT_VERSION_REVISION, 99) define(_CLIENT_VERSION_BUILD, 0) define(_CLIENT_VERSION_IS_RELEASE, false) -define(_COPYRIGHT_YEAR, 2017) +define(_COPYRIGHT_YEAR, 2018) define(_COPYRIGHT_HOLDERS,[The %s developers]) define(_COPYRIGHT_HOLDERS_SUBSTITUTION,[[Bitcoin Core]]) AC_INIT([Bitcoin Core],[_CLIENT_VERSION_MAJOR._CLIENT_VERSION_MINOR._CLIENT_VERSION_REVISION],[https://github.com/bitcoin/bitcoin/issues],[bitcoin],[https://bitcoincore.org/]) @@ -164,7 +164,7 @@ AC_ARG_ENABLE([lcov], [enable lcov testing (default is no)])], [use_lcov=$enableval], [use_lcov=no]) - + AC_ARG_ENABLE([lcov-branch-coverage], [AS_HELP_STRING([--enable-lcov-branch-coverage], [enable lcov testing branch coverage (default is no)])], @@ -659,6 +659,28 @@ AC_LINK_IFELSE([AC_LANG_SOURCE([ ] ) +TEMP_LDFLAGS="$LDFLAGS" +LDFLAGS="$TEMP_LDFLAGS $PTHREAD_CFLAGS" +AC_MSG_CHECKING([for thread_local support]) +AC_LINK_IFELSE([AC_LANG_SOURCE([ + #include <thread> + static thread_local int foo = 0; + static void run_thread() { foo++;} + int main(){ + for(int i = 0; i < 10; i++) { std::thread(run_thread).detach();} + return foo; + } + ])], + [ + AC_DEFINE(HAVE_THREAD_LOCAL,1,[Define if thread_local is supported.]) + AC_MSG_RESULT(yes) + ], + [ + AC_MSG_RESULT(no) + ] +) +LDFLAGS="$TEMP_LDFLAGS" + # Check for different ways of gathering OS randomness AC_MSG_CHECKING(for Linux getrandom syscall) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <unistd.h> @@ -739,6 +761,9 @@ define(MINIMUM_REQUIRED_BOOST, 1.47.0) dnl Check for boost libs AX_BOOST_BASE([MINIMUM_REQUIRED_BOOST]) +if test x$want_boost = xno; then + AC_MSG_ERROR([[only libbitcoinconsensus can be built without boost]]) +fi AX_BOOST_SYSTEM AX_BOOST_FILESYSTEM AX_BOOST_PROGRAM_OPTIONS @@ -1288,7 +1313,7 @@ case ${OS} in ;; esac -echo +echo echo "Options used to compile and link:" echo " with wallet = $enable_wallet" echo " with gui / qt = $bitcoin_enable_qt" @@ -1303,7 +1328,7 @@ echo " with upnp = $use_upnp" echo " use asm = $use_asm" echo " debug enabled = $enable_debug" echo " werror = $enable_werror" -echo +echo echo " target os = $TARGET_OS" echo " build os = $BUILD_OS" echo @@ -1314,4 +1339,4 @@ echo " CXX = $CXX" echo " CXXFLAGS = $CXXFLAGS" echo " LDFLAGS = $LDFLAGS" echo " ARFLAGS = $ARFLAGS" -echo +echo diff --git a/contrib/debian/copyright b/contrib/debian/copyright index 72d64ce62d..c6484157a5 100644 --- a/contrib/debian/copyright +++ b/contrib/debian/copyright @@ -5,7 +5,7 @@ Upstream-Contact: Satoshi Nakamoto <satoshin@gmx.com> Source: https://github.com/bitcoin/bitcoin Files: * -Copyright: 2009-2017, Bitcoin Core Developers +Copyright: 2009-2018, Bitcoin Core Developers License: Expat Comment: The Bitcoin Core Developers encompasses the current developers listed on bitcoin.org, as well as the numerous contributors to the project. @@ -15,6 +15,14 @@ Copyright: 2010-2011, Jonas Smedegaard <dr@jones.dk> 2011, Matt Corallo <matt@bluematt.me> License: GPL-2+ +Files: src/secp256k1/build-aux/m4/ax_jni_include_dir.m4 +Copyright: 2008 Don Anderson <dda@sleepycat.com> +License: GNU-All-permissive-License + +Files: src/secp256k1/build-aux/m4/ax_prog_cc_for_build.m4 +Copyright: 2008 Paolo Bonzini <bonzini@gnu.org> +License: GNU-All-permissive-License + Files: src/qt/res/icons/add.png src/qt/res/icons/address-book.png src/qt/res/icons/chevron.png @@ -106,6 +114,12 @@ License: Expat TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +License: GNU-All-permissive-License + Copying and distribution of this file, with or without modification, are + permitted in any medium without royalty provided the copyright notice + and this notice are preserved. This file is offered as-is, without any + warranty. + License: GPL-2+ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the diff --git a/contrib/debian/examples/bitcoin.conf b/contrib/debian/examples/bitcoin.conf index 14a59fdf6b..4dd73162a2 100644 --- a/contrib/debian/examples/bitcoin.conf +++ b/contrib/debian/examples/bitcoin.conf @@ -77,9 +77,9 @@ #rpcpassword=YourSuperGreatPasswordNumber_DO_NOT_USE_THIS_OR_YOU_WILL_GET_ROBBED_385593 # # The second method `rpcauth` can be added to server startup argument. It is set at initialization time -# using the output from the script in share/rpcuser/rpcuser.py after providing a username: +# using the output from the script in share/rpcauth/rpcauth.py after providing a username: # -# ./share/rpcuser/rpcuser.py alice +# ./share/rpcauth/rpcauth.py alice # String to be appended to bitcoin.conf: # rpcauth=alice:f7efda5c189b999524f151318c0c86$d5b51b3beffbc02b724e5d095828e0bc8b2456e9ac8757ae3211a5d9b16a22ae # Your password: diff --git a/contrib/devtools/check-doc.py b/contrib/devtools/check-doc.py index 10c3bab03b..f164ea9322 100755 --- a/contrib/devtools/check-doc.py +++ b/contrib/devtools/check-doc.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# Copyright (c) 2015-2016 The Bitcoin Core developers +# Copyright (c) 2015-2017 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/contrib/devtools/copyright_header.py b/contrib/devtools/copyright_header.py index 6d801d3ac7..c817e794b9 100755 --- a/contrib/devtools/copyright_header.py +++ b/contrib/devtools/copyright_header.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2016 The Bitcoin Core developers +# Copyright (c) 2016-2017 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -24,8 +24,10 @@ EXCLUDE = [ 'src/secp256k1/src/java/org_bitcoin_NativeSecp256k1.h', 'src/secp256k1/src/java/org_bitcoin_Secp256k1Context.c', 'src/secp256k1/src/java/org_bitcoin_Secp256k1Context.h', - # auto generated: + # univalue: + 'src/univalue/test/object.cpp', 'src/univalue/lib/univalue_escapes.h', + # auto generated: 'src/qt/bitcoinstrings.cpp', 'src/chainparamsseeds.h', # other external copyrights: diff --git a/contrib/devtools/gen-manpages.sh b/contrib/devtools/gen-manpages.sh index 967717e1e0..925d6a6252 100755 --- a/contrib/devtools/gen-manpages.sh +++ b/contrib/devtools/gen-manpages.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash TOPDIR=${TOPDIR:-$(git rev-parse --show-toplevel)} SRCDIR=${SRCDIR:-$TOPDIR/src} diff --git a/contrib/devtools/lint-python.sh b/contrib/devtools/lint-python.sh new file mode 100755 index 0000000000..9303fcc8ef --- /dev/null +++ b/contrib/devtools/lint-python.sh @@ -0,0 +1,10 @@ +#!/bin/sh +# +# Copyright (c) 2017 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# +# Check for specified flake8 warnings in python files. + +# F401: module imported but unused +flake8 --ignore=B,C,E,F,I,N,W --select=F401 . diff --git a/contrib/devtools/optimize-pngs.py b/contrib/devtools/optimize-pngs.py index 9286ab731f..5cb3bb6f75 100755 --- a/contrib/devtools/optimize-pngs.py +++ b/contrib/devtools/optimize-pngs.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# Copyright (c) 2014-2016 The Bitcoin Core developers +# Copyright (c) 2014-2017 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. ''' diff --git a/contrib/devtools/security-check.py b/contrib/devtools/security-check.py index 6eb5667453..1613f704df 100755 --- a/contrib/devtools/security-check.py +++ b/contrib/devtools/security-check.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# Copyright (c) 2015-2016 The Bitcoin Core developers +# Copyright (c) 2015-2017 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. ''' diff --git a/contrib/devtools/test-security-check.py b/contrib/devtools/test-security-check.py index 18f9835faa..22f5ee20f7 100755 --- a/contrib/devtools/test-security-check.py +++ b/contrib/devtools/test-security-check.py @@ -1,5 +1,5 @@ #!/usr/bin/env python2 -# Copyright (c) 2015-2016 The Bitcoin Core developers +# Copyright (c) 2015-2017 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. ''' diff --git a/contrib/gitian-build.sh b/contrib/gitian-build.sh index 511c1a4c48..631fba9089 100755 --- a/contrib/gitian-build.sh +++ b/contrib/gitian-build.sh @@ -105,7 +105,7 @@ while :; do fi shift else - echo 'Error: "--os" requires an argument containing an l (for linux), w (for windows), or x (for Mac OSX)\n' + echo 'Error: "--os" requires an argument containing an l (for linux), w (for windows), or x (for Mac OSX)' exit 1 fi ;; @@ -188,7 +188,7 @@ then fi # Get signer -if [[ -n"$1" ]] +if [[ -n "$1" ]] then SIGNER=$1 shift diff --git a/contrib/install_db4.sh b/contrib/install_db4.sh index 1d33e8d3ba..d315a7d3b7 100755 --- a/contrib/install_db4.sh +++ b/contrib/install_db4.sh @@ -7,7 +7,7 @@ set -e if [ -z "${1}" ]; then echo "Usage: ./install_db4.sh <base-dir> [<extra-bdb-configure-flag> ...]" echo - echo "Must specify a single argument: the directory in which db5 will be built." + echo "Must specify a single argument: the directory in which db4 will be built." echo "This is probably \`pwd\` if you're at the root of the bitcoin repository." exit 1 fi @@ -17,7 +17,6 @@ expand_path() { } BDB_PREFIX="$(expand_path ${1})/db4"; shift; -BDB_EXTRA_CONFIGURE_FLAGS="${@}" BDB_VERSION='db-4.8.30.NC' BDB_HASH='12edc0df75bf9abd7f82f821795bcee50f42cb2e5f76a6a281b85732798364ef' BDB_URL="https://download.oracle.com/berkeley-db/${BDB_VERSION}.tar.gz" @@ -32,7 +31,11 @@ sha256_check() { if check_exists sha256sum; then echo "${1} ${2}" | sha256sum -c elif check_exists sha256; then - echo "${1} ${2}" | sha256 -c + if [ "$(uname)" = "FreeBSD" ]; then + sha256 -c "${1}" "${2}" + else + echo "${1} ${2}" | sha256 -c + fi else echo "${1} ${2}" | shasum -a 256 -c fi @@ -60,21 +63,17 @@ http_get "${BDB_URL}" "${BDB_VERSION}.tar.gz" "${BDB_HASH}" tar -xzvf ${BDB_VERSION}.tar.gz -C "$BDB_PREFIX" cd "${BDB_PREFIX}/${BDB_VERSION}/" -# Apply a patch when building on OS X to make the build work with Xcode. -# -if [ "$(uname)" = "Darwin" ]; then - BDB_OSX_ATOMIC_PATCH_URL='https://raw.githubusercontent.com/narkoleptik/os-x-berkeleydb-patch/0007e2846ae3fc9757849f5277018f4179ad17ef/atomic.patch' - BDB_OSX_ATOMIC_PATCH_HASH='ba0e2b4f53e9cb0ec58f60a979b53b8567b4565f0384886196f1fc1ef111d151' - - http_get "${BDB_OSX_ATOMIC_PATCH_URL}" atomic.patch "${BDB_OSX_ATOMIC_PATCH_HASH}" - patch -p1 < atomic.patch -fi +# Apply a patch necessary when building with clang and c++11 (see https://community.oracle.com/thread/3952592) +CLANG_CXX11_PATCH_URL='https://gist.githubusercontent.com/LnL7/5153b251fd525fe15de69b67e63a6075/raw/7778e9364679093a32dec2908656738e16b6bdcb/clang.patch' +CLANG_CXX11_PATCH_HASH='7a9a47b03fd5fb93a16ef42235fa9512db9b0829cfc3bdf90edd3ec1f44d637c' +http_get "${CLANG_CXX11_PATCH_URL}" clang.patch "${CLANG_CXX11_PATCH_HASH}" +patch -p2 < clang.patch cd build_unix/ "${BDB_PREFIX}/${BDB_VERSION}/dist/configure" \ - --enable-cxx --disable-shared --with-pic --prefix="${BDB_PREFIX}" \ - "${BDB_EXTRA_CONFIGURE_FLAGS}" + --enable-cxx --disable-shared --disable-replication --with-pic --prefix="${BDB_PREFIX}" \ + "${@}" make install @@ -84,4 +83,4 @@ echo echo 'When compiling bitcoind, run `./configure` in the following way:' echo echo " export BDB_PREFIX='${BDB_PREFIX}'" -echo ' ./configure LDFLAGS="-L${BDB_PREFIX}/lib/" CPPFLAGS="-I${BDB_PREFIX}/include/" ...' +echo ' ./configure BDB_LIBS="-L${BDB_PREFIX}/lib -ldb_cxx-4.8" BDB_CFLAGS="-I${BDB_PREFIX}/include" ...' diff --git a/contrib/linearize/linearize-data.py b/contrib/linearize/linearize-data.py index afcec2b60a..4969e96827 100755 --- a/contrib/linearize/linearize-data.py +++ b/contrib/linearize/linearize-data.py @@ -2,7 +2,7 @@ # # linearize-data.py: Construct a linear, no-fork version of the chain. # -# Copyright (c) 2013-2016 The Bitcoin Core developers +# Copyright (c) 2013-2017 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. # diff --git a/contrib/linearize/linearize-hashes.py b/contrib/linearize/linearize-hashes.py index 58fec6dddc..6b69c5b3a3 100755 --- a/contrib/linearize/linearize-hashes.py +++ b/contrib/linearize/linearize-hashes.py @@ -2,7 +2,7 @@ # # linearize-hashes.py: List blocks in a linear, no-fork version of the chain. # -# Copyright (c) 2013-2016 The Bitcoin Core developers +# Copyright (c) 2013-2017 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. # diff --git a/contrib/macdeploy/detached-sig-create.sh b/contrib/macdeploy/detached-sig-create.sh index 7f017bb4f1..3379a4599c 100755 --- a/contrib/macdeploy/detached-sig-create.sh +++ b/contrib/macdeploy/detached-sig-create.sh @@ -40,7 +40,7 @@ grep CodeResources < "${TEMPLIST}" | while read i; do RESOURCE="${TEMPDIR}/${OUTROOT}/${TARGETFILE}" DIRNAME="`dirname "${RESOURCE}"`" mkdir -p "${DIRNAME}" - echo "Adding resource for: "${TARGETFILE}"" + echo "Adding resource for: \"${TARGETFILE}\"" cp "${i}" "${RESOURCE}" done diff --git a/contrib/seeds/README.md b/contrib/seeds/README.md index 139c03181f..6dc277f298 100644 --- a/contrib/seeds/README.md +++ b/contrib/seeds/README.md @@ -4,7 +4,9 @@ Utility to generate the seeds.txt list that is compiled into the client (see [src/chainparamsseeds.h](/src/chainparamsseeds.h) and other utilities in [contrib/seeds](/contrib/seeds)). Be sure to update `PATTERN_AGENT` in `makeseeds.py` to include the current version, -and remove old versions as necessary. +and remove old versions as necessary (at a minimum when GetDesireableServiceFlags +changes its default return value, as those are the services which seeds are added +to addrman with). The seeds compiled into the release are created from sipa's DNS seed data, like this: diff --git a/contrib/seeds/makeseeds.py b/contrib/seeds/makeseeds.py index 877a7836ef..6e253c994d 100755 --- a/contrib/seeds/makeseeds.py +++ b/contrib/seeds/makeseeds.py @@ -30,7 +30,7 @@ import collections PATTERN_IPV4 = re.compile(r"^((\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})):(\d+)$") PATTERN_IPV6 = re.compile(r"^\[([0-9a-z:]+)\]:(\d+)$") PATTERN_ONION = re.compile(r"^([abcdefghijklmnopqrstuvwxyz234567]{16}\.onion):(\d+)$") -PATTERN_AGENT = re.compile(r"^(/Satoshi:0.13.(1|2|99)/|/Satoshi:0.14.(0|1|2|99)/)$") +PATTERN_AGENT = re.compile(r"^(/Satoshi:0.13.(1|2|99)/|/Satoshi:0.14.(0|1|2|99)/|/Satoshi:0.15.(0|1|2|99)/)$") def parseline(line): sline = line.split() diff --git a/contrib/seeds/nodes_main.txt b/contrib/seeds/nodes_main.txt index 60b34216cd..01a386c60e 100644 --- a/contrib/seeds/nodes_main.txt +++ b/contrib/seeds/nodes_main.txt @@ -1,1002 +1,1086 @@ -2.228.70.198:8333 -4.15.180.29:8333 -4.15.180.30:8333 -5.2.67.110:8333 -5.39.224.103:8333 -5.43.124.154:8333 -5.189.165.102:8333 -5.226.149.145:8333 -5.228.7.146:8333 +5.19.5.127:8333 +5.29.139.120:8333 +5.39.64.7:8333 +5.39.174.116:8333 +5.45.69.13:8333 +5.45.75.15:8333 +5.45.108.108:8333 +5.101.140.194:8333 +5.133.13.56:8333 +5.175.24.7:8333 +5.189.133.130:8333 5.228.64.71:8333 -5.249.152.101:8333 -5.254.124.55:8333 -5.255.64.231:8333 -5.255.90.234:8333 +13.80.67.162:8333 14.192.8.27:21301 -18.62.3.86:8333 -18.85.35.80:8333 -23.28.128.65:8333 -23.108.83.12:8333 -23.233.2.238:8333 -24.27.65.168:8333 -24.56.241.219:8333 -24.64.75.132:8333 -24.73.70.26:8333 -24.121.154.140:8333 -24.203.96.72:8333 +23.89.193.201:8333 +23.125.224.84:8333 +23.225.160.26:8333 +23.226.231.122:8333 +23.227.204.78:8333 +23.238.132.188:8333 +23.240.67.204:8333 +24.25.141.186:8333 +24.120.235.185:8333 +24.138.188.60:8333 +24.211.229.7:8333 +24.220.78.161:8333 24.225.34.62:8333 -24.227.69.146:8333 24.232.136.119:8333 -31.16.123.235:8333 -31.19.205.53:8333 -31.132.136.35:8333 -31.184.234.85:8333 -31.211.102.161:8333 +27.68.131.10:8333 +31.28.10.13:8333 +31.31.203.113:8333 +31.145.106.61:8333 +31.211.102.129:62734 37.48.64.140:8333 -37.97.141.116:8333 -37.120.160.12:8333 -37.120.164.16:8333 -37.134.226.181:8333 -37.147.110.43:8333 +37.120.163.181:8333 +37.134.167.91:8333 +37.191.225.174:8333 +37.192.41.32:8333 37.194.10.30:8333 -37.247.22.53:8333 -38.27.65.158:8333 -38.133.141.34:8333 +37.200.34.18:8333 +37.205.8.78:8333 +38.27.100.44:8333 +38.102.69.70:8333 +38.104.225.30:8333 +41.86.104.94:8333 +41.170.64.8:8333 +43.229.76.45:8333 43.248.160.151:8333 -45.32.130.19:8333 -45.32.193.157:8333 -45.46.161.121:8333 -45.56.97.63:8333 -45.116.178.79:8188 -46.16.240.98:8333 -46.20.246.100:8333 -46.21.97.135:8333 -46.59.10.237:8333 -46.59.13.59:8333 -46.148.16.210:8333 -46.166.160.96:8333 -46.188.44.20:8333 -46.229.238.187:8333 -46.231.16.149:8333 -47.88.35.181:8333 -47.88.100.130:8333 -47.184.129.94:8333 -47.199.68.204:8333 -50.30.38.203:8333 -50.63.162.242:8333 -50.97.133.208:8333 -50.114.227.224:8333 +45.32.65.19:8333 +45.62.198.46:8333 +46.19.136.138:8333 +46.20.246.117:8333 +46.28.69.138:8333 +46.28.205.112:8333 +46.160.195.121:8333 +46.163.118.51:8333 +46.166.129.159:8333 +46.183.236.254:8333 +46.227.101.176:8333 +46.229.168.201:8333 +46.238.238.176:8333 +46.242.131.168:8333 +47.20.103.108:8333 +47.94.224.99:8333 +47.187.1.83:8333 +47.223.232.58:8333 +47.254.128.15:8333 +47.254.128.197:8333 +50.2.189.35:8333 +50.28.99.81:8333 +50.31.170.51:8333 +50.126.194.190:8333 51.15.0.17:8333 -51.174.69.239:8333 -52.7.135.69:8333 -52.14.64.82:8333 -52.204.105.25:8333 -54.255.160.87:8333 -61.47.2.20:8333 +52.29.0.37:8333 +52.59.96.11:8333 +52.225.128.191:8333 +54.84.98.69:8333 +54.197.4.92:8333 +54.223.136.62:8333 +58.173.224.98:8333 +58.229.208.166:8333 61.125.131.55:8333 -62.43.130.178:8333 -62.106.16.111:8333 +62.13.193.206:8333 +62.45.0.15:8333 62.107.200.30:8333 -62.109.20.99:8333 -62.133.194.2:8333 62.133.194.156:8333 -62.176.6.94:8333 -62.182.169.222:8333 -62.205.132.245:8333 -62.216.238.133:8333 -63.231.239.212:8333 +62.138.11.10:8333 +62.182.171.116:8333 +62.195.193.35:8333 +62.210.161.249:8333 +63.141.228.18:8333 +63.143.37.46:8333 64.34.231.140:8333 -64.203.102.86:8333 -64.233.245.39:8333 -65.183.76.73:8333 -66.96.199.166:8333 +64.39.234.49:8333 +64.110.25.26:8333 +64.121.35.3:8333 +65.19.155.88:8333 +66.18.172.16:8333 +66.160.128.215:8333 +66.180.64.95:8333 66.194.38.250:8333 -66.194.38.253:8333 -66.196.12.63:8333 -67.215.6.34:8333 -67.221.193.55:8333 -68.66.193.192:8333 -68.69.235.230:8333 -68.111.10.219:8333 -68.119.138.175:8333 -68.132.193.222:8333 -68.194.42.76:8333 -68.235.41.204:8333 -69.11.97.43:8333 -69.41.3.212:8333 +67.68.101.249:8333 +67.128.36.90:8333 +67.148.60.130:8333 +67.210.228.203:8333 +67.225.134.26:8333 +68.12.98.246:8333 +68.199.10.75:8333 +69.39.49.199:8333 69.41.171.35:8333 -69.41.171.36:8333 -69.55.64.216:8333 -69.84.42.56:8333 -70.48.48.250:8333 -70.112.32.29:8333 -70.250.74.20:8333 +69.41.171.224:8333 +69.64.34.1:8333 +69.64.46.27:8333 +69.64.225.2:8333 +69.159.134.58:8333 +69.181.160.80:8333 +69.222.192.88:8333 +70.15.74.72:8333 +70.35.98.12:8333 +70.60.65.62:8333 +70.113.33.131:8333 +71.85.226.76:8333 71.93.161.162:8333 -71.198.0.126:8333 -72.5.167.41:8333 -72.224.11.103:8333 -73.72.160.213:8333 +73.241.192.40:8333 +74.118.192.119:8333 74.122.237.124:8333 -75.86.137.34:8333 -75.165.99.144:8333 -76.64.74.193:8333 -76.76.227.136:8333 -76.173.161.44:8333 -76.178.22.44:8333 -77.47.137.27:8333 -77.77.46.250:8333 -77.91.193.152:8333 +75.159.6.167:8333 +76.10.157.58:8333 +76.92.136.75:8333 77.95.226.194:8333 -77.120.246.254:8333 77.163.136.136:8333 -77.203.13.57:8333 -77.236.37.214:8333 +77.234.50.2:8333 77.239.37.12:8333 -77.247.179.44:8333 -78.34.14.52:8333 +78.31.67.156:8333 78.109.163.153:8333 -78.196.172.45:8333 -79.132.230.144:8333 -79.160.2.105:8333 +78.130.161.78:8333 +78.192.35.130:8333 +78.248.65.34:8333 +79.46.194.163:8333 +79.77.6.136:8333 +79.98.196.89:8333 +79.154.97.168:8333 +79.165.235.119:8333 +79.169.35.235:8333 +79.182.167.137:8333 +80.82.67.182:8333 80.82.77.138:8333 -80.100.203.151:8333 -80.147.68.237:8333 -80.237.240.102:8333 -81.2.246.127:8333 -81.7.7.86:8333 -81.7.10.238:8333 +80.84.54.26:8333 +80.208.224.217:8333 +80.208.227.53:8333 +80.220.43.228:8333 +80.254.188.235:8333 +81.7.10.251:8333 +81.7.13.84:8333 +81.18.224.62:8333 81.27.96.37:8333 -81.83.96.5:8333 +81.108.196.72:8333 +81.186.243.220:8333 81.228.194.187:8333 -82.45.69.216:8333 -82.69.44.183:8333 82.72.198.68:8333 -82.95.204.10:8333 -82.118.236.127:8333 -82.118.242.4:8333 -82.134.66.146:8333 +82.74.224.35:8333 +82.96.64.6:8333 +82.117.166.77:8333 +82.118.236.69:8333 +82.161.109.190:8333 +82.193.102.228:8333 82.193.109.199:8333 -82.197.210.65:8333 82.199.102.10:8333 -82.200.205.30:8333 +82.200.204.119:8333 +82.202.197.224:8333 +82.212.7.242:8333 82.221.108.27:8333 82.221.128.81:8333 -82.221.139.97:8333 -82.232.202.246:8333 -83.60.64.252:8333 -83.61.8.228:8333 -83.128.41.48:8333 -83.128.111.69:8333 +83.50.134.8:8333 +83.78.33.135:8333 83.137.41.10:8333 -83.150.43.17:8333 -83.169.2.43:8333 -83.174.209.87:8333 -83.255.43.163:8333 -84.42.193.6:8333 -84.52.145.231:8333 -84.52.234.70:8333 -84.85.102.113:8333 -84.92.92.247:8333 -84.146.35.123:8333 -84.212.198.222:8333 -84.217.163.135:8333 -84.245.27.185:8333 -84.251.203.5:8333 -85.21.144.226:8333 +83.150.37.94:8333 +83.162.43.154:8333 +83.164.131.242:8333 +83.164.131.243:8333 +83.209.8.140:8333 +83.236.135.251:8333 +83.243.59.41:8333 +83.249.13.223:8333 +83.250.86.108:8333 +84.94.235.161:8333 +84.117.1.27:8333 +84.200.106.128:8333 +84.213.64.21:8333 +84.226.164.161:8333 +84.245.27.130:8333 +84.251.161.205:8333 +85.5.1.72:8333 +85.10.41.41:8333 85.25.194.12:8333 -85.25.194.28:8333 -85.144.119.222:8333 -85.183.140.62:8333 -85.214.228.203:8333 -85.214.234.254:8333 -85.218.150.1:8333 -85.228.196.10:8333 -86.15.2.235:8333 -86.61.6.210:8333 -87.92.115.194:8333 +85.95.241.46:8333 +85.129.0.126:8333 +85.170.232.245:8333 +85.195.232.39:8333 +85.214.68.122:8333 +85.214.235.137:8333 +85.245.167.246:8333 +86.8.35.17:8333 +86.105.5.113:8333 +86.106.131.179:8333 +87.79.68.86:8333 87.120.8.5:8333 -87.120.37.230:8333 -87.233.181.146:8333 -87.239.101.102:8333 -88.87.78.126:8333 +87.239.202.239:8333 88.98.198.130:8333 -88.98.225.214:8333 -88.99.58.194:8333 -88.150.192.17:8333 -88.196.136.31:17556 -88.208.58.193:8333 -88.208.58.194:8333 -89.22.96.132:8333 -89.22.104.48:8333 -89.25.80.98:8333 -89.34.99.41:8333 -89.142.195.112:8333 -89.163.224.187:8333 +88.149.106.236:8333 +88.207.236.175:8333 +89.35.29.3:8333 +89.38.96.70:8333 +89.142.65.151:8333 89.163.224.195:8333 -89.238.79.235:8333 -90.46.240.214:8333 -90.65.232.129:8333 -90.71.117.90:8333 -90.149.38.172:8333 -90.156.97.145:8333 -90.177.48.104:8333 -91.106.194.97:8333 +89.179.240.131:8333 +89.230.96.42:8333 +89.236.101.52:8333 +90.191.203.18:8333 +91.65.7.30:8333 +91.65.192.159:8333 91.135.0.187:8333 -91.150.189.155:8333 -91.185.198.216:8333 -91.196.11.45:8333 -91.197.44.133:8333 +91.154.113.227:8333 +91.195.42.134:8333 +91.202.67.107:8333 +91.221.71.115:8333 91.224.0.227:8333 -91.226.10.90:8333 +91.224.1.17:8333 +91.225.236.145:8333 91.228.45.130:8333 -91.229.77.239:8333 +91.231.229.136:8333 91.238.100.249:8333 -91.240.141.169:8333 -92.27.7.209:8333 -92.54.16.135:8333 -93.89.84.93:8333 -93.100.51.48:8333 -93.100.76.151:8333 -93.104.214.235:8333 -93.115.86.246:8333 -93.123.80.47:8333 -93.174.88.211:8333 -93.188.224.253:8333 -93.190.69.242:8333 -94.74.81.93:8333 +92.27.142.29:8333 +92.62.34.184:8333 +92.177.2.181:8333 +92.249.169.36:8333 +92.255.176.109:8333 +93.75.18.151:8333 +93.79.204.222:10333 +93.95.100.155:8333 +93.113.131.134:8333 +93.170.13.15:8333 +93.179.197.152:8333 +93.190.205.25:8333 +94.59.135.148:8333 94.156.35.8:8333 -94.176.237.241:8333 +94.177.106.189:8333 94.181.44.104:8333 -94.227.43.171:8333 -95.79.102.208:8333 -95.79.102.209:8333 -95.154.237.24:8333 -95.183.48.62:8333 -95.183.48.71:8333 +94.198.97.215:8333 +94.236.198.253:8333 +94.237.64.138:8333 +94.242.232.92:8333 +95.84.134.107:8333 +95.105.183.183:8333 +95.191.130.100:8333 95.213.161.2:8333 -95.213.201.94:8333 +95.226.77.108:8333 96.20.227.39:8333 -96.28.41.91:8333 +96.23.67.85:8333 +96.27.8.242:8333 +98.5.31.251:8333 98.127.130.17:8333 -100.36.48.101:8333 -101.0.81.42:8333 -101.0.81.43:8333 -103.11.64.46:8333 -103.24.244.69:8333 -103.47.210.50:8333 -103.76.41.169:8333 +98.162.209.130:8333 +99.198.237.76:8333 +99.238.3.86:8333 +101.165.34.253:8333 +103.44.162.50:8333 +103.56.136.105:8333 +103.59.166.139:8333 +103.60.97.21:8333 +103.79.107.144:8333 103.80.168.57:8333 -103.203.51.186:8333 -103.224.118.79:8333 +103.85.14.106:8333 +103.100.44.58:8333 103.250.4.74:8333 -104.192.170.202:8333 -104.196.0.99:8333 +103.250.5.74:8333 +104.32.162.149:8333 +104.156.99.240:8333 +104.156.103.72:8333 +104.168.101.207:8333 +104.171.113.52:8333 +104.197.64.3:8333 104.199.192.85:8333 -104.219.251.46:8333 -104.223.108.33:8333 -104.237.2.189:8333 -104.247.230.28:8333 -107.150.45.210:8333 -107.174.34.77:8333 -107.174.34.78:8333 -107.180.71.47:8333 -108.59.12.163:8333 -108.168.37.13:8333 +104.200.67.161:8333 +104.220.16.253:8333 +104.237.4.26:8333 +104.238.198.165:8333 +107.180.85.93:33244 +108.4.11.29:8333 +108.49.194.58:8333 108.175.3.18:8333 -108.234.193.106:8333 -109.9.173.13:8333 -109.101.220.151:8333 +109.61.102.5:8333 +109.106.136.195:8333 +109.110.95.201:8333 109.172.104.119:8333 -109.195.193.138:8333 -109.206.177.21:8333 -109.226.35.28:8333 -109.255.0.107:8333 -113.29.183.143:8333 -114.145.97.73:8333 -115.66.205.171:8333 +110.4.40.147:8333 +112.187.178.116:8333 +113.105.139.42:8333 +115.90.171.158:8333 +116.88.75.110:8333 +116.250.193.234:8333 +117.141.138.240:8333 118.67.201.40:8333 -118.194.226.168:8333 -119.28.70.144:8333 -120.24.166.73:9998 -120.76.244.201:10022 -121.82.4.232:8333 -121.254.173.40:8333 +118.89.229.178:8333 +118.211.167.90:8333 +120.79.64.154:8333 +121.200.5.186:8333 +121.254.173.39:8333 +123.2.128.107:8333 123.203.163.128:8333 -124.171.70.45:8333 -125.63.57.7:8333 -125.128.35.41:8333 -128.208.244.124:8333 -128.230.208.73:8333 +128.1.68.46:8333 +128.125.100.2:8333 +130.89.78.87:8333 +130.204.75.3:8333 131.114.10.233:8333 -131.114.10.235:8333 -132.239.36.105:8333 -134.213.214.233:8333 -136.61.238.121:8333 -136.62.86.140:8333 -136.144.128.49:8333 -137.48.144.52:8333 -137.116.160.176:8333 -137.117.193.113:8333 -138.19.79.208:8333 -138.68.64.19:8333 +131.188.40.191:8333 +132.148.130.51:8333 +134.255.226.233:8333 +135.23.194.98:8333 +136.25.137.220:8333 +136.55.10.249:8333 +136.243.32.38:8333 +136.243.64.23:8333 +137.226.34.46:8333 139.59.96.16:8333 139.162.160.232:8333 -141.136.115.230:8333 -142.59.232.111:8333 -142.111.2.74:8333 -142.162.128.23:8333 -143.107.116.5:8333 -143.229.22.74:8333 -143.229.36.71:8333 -144.2.105.60:8333 -144.76.224.214:8333 -146.185.19.30:8333 -147.32.30.25:8333 -147.229.13.210:8333 -148.103.7.119:8333 -150.101.114.194:8333 +139.199.228.84:8333 +141.134.71.188:8333 +141.138.137.40:8333 +145.129.31.147:8333 +146.71.76.53:8333 +146.71.76.236:8333 +149.210.228.108:8333 150.229.0.143:8333 -154.66.207.126:8333 -158.129.212.236:8333 -158.129.212.251:8333 -160.16.206.31:8333 -162.209.1.233:8333 -162.209.4.125:8333 -162.220.246.225:8333 -163.172.218.186:8333 +150.249.76.102:8333 +153.125.224.44:8333 +155.4.99.150:8333 +155.133.129.97:8333 +157.159.103.161:8333 +158.140.201.35:8333 +158.140.229.62:8333 +158.181.104.132:8333 +158.181.134.193:8333 +160.16.135.187:8333 +162.221.224.63:8333 +165.165.132.68:8333 +165.194.35.203:8333 166.230.70.145:8333 -168.235.74.45:8333 -169.44.34.88:8333 +169.44.34.203:8333 +169.48.163.176:8333 +170.75.162.180:8333 170.75.195.168:8333 -172.112.2.67:8333 -173.94.164.38:8333 -173.183.232.109:8333 -173.208.176.122:8333 -173.212.194.114:8333 -173.232.228.146:8333 -175.126.124.92:8333 -175.145.109.51:8333 -176.24.198.205:8333 -176.36.37.62:8333 -176.36.99.222:8333 -176.106.144.183:8333 -177.33.1.40:8333 -178.162.214.225:8333 -178.164.109.83:8333 -178.170.138.202:8333 -178.175.136.122:8333 -178.218.209.162:8333 -178.254.2.64:8333 +171.25.165.145:8333 +172.96.161.138:8333 +172.98.193.45:8333 +172.103.164.75:8333 +172.110.8.233:8333 +173.209.53.114:8333 +173.212.192.117:8333 +173.243.64.49:8333 +173.255.224.185:8333 +174.100.131.151:8333 +174.113.66.230:8333 +174.138.62.90:8333 +176.10.136.25:8333 +176.23.13.27:8333 +176.24.220.141:8333 +176.106.252.173:8333 +176.126.167.10:8333 +177.52.173.63:8333 +178.78.226.178:8333 +178.132.4.123:8333 +178.175.144.122:8333 +178.221.66.212:8333 +178.236.130.229:8333 +178.254.7.88:8333 178.254.34.144:8333 178.255.41.21:8333 -178.255.144.163:8333 -180.181.208.42:8333 -180.200.128.58:8333 -180.235.50.14:8333 -181.215.148.154:8333 -184.64.13.43:8333 -184.94.164.170:8333 -184.152.107.251:8333 -184.182.233.206:8333 -185.4.24.199:8333 -185.20.99.49:8333 -185.24.97.11:8333 -185.25.48.27:8333 -185.25.48.71:8333 -185.26.196.249:8333 +179.48.251.41:8333 +182.247.238.169:8333 +183.111.29.28:8333 +184.64.12.109:8333 +184.70.33.190:8333 +184.95.38.218:8333 +185.8.172.121:8333 +185.11.82.38:8333 +185.12.7.38:8333 +185.12.236.242:8333 +185.20.226.148:8333 +185.21.216.134:8333 +185.22.232.167:8333 185.28.76.179:8333 -185.35.139.250:8333 -185.41.113.69:8333 -185.50.213.123:8333 -185.50.213.124:8333 -185.50.232.114:8333 -185.51.192.40:8333 -185.53.129.244:8333 -185.71.177.100:8333 +185.31.136.69:8333 +185.35.137.175:8333 +185.35.138.84:8333 +185.35.182.123:8333 +185.47.132.109:8333 +185.53.128.180:8333 +185.63.172.14:8333 +185.64.104.2:8333 +185.70.105.74:8339 +185.77.128.69:8333 185.77.129.176:8333 -185.82.201.51:8333 +185.85.3.137:8333 +185.102.71.6:8333 185.121.173.223:8333 -185.140.252.253:8333 -185.145.129.184:8333 -185.145.130.163:8333 +185.127.17.167:8333 185.154.156.50:8333 -185.162.124.69:8333 -185.170.42.2:8333 -186.149.197.96:8333 -188.65.212.138:8333 -188.65.213.48:8333 -188.93.209.192:8333 -188.113.79.45:8333 -188.113.84.116:8333 -188.113.164.231:8333 -188.122.16.153:8333 -188.165.224.28:8333 -188.175.239.227:8333 +185.162.128.83:8333 +185.183.161.35:8333 +185.189.199.248:8333 +185.215.224.107:8333 +186.5.136.70:8333 +186.31.4.202:8333 +188.27.80.126:8333 +188.65.212.49:8333 +188.116.140.127:8333 +188.134.79.145:8333 188.214.128.18:8333 +188.214.128.175:8333 188.227.64.19:8333 +188.234.241.172:8333 188.253.2.125:8333 -189.45.203.166:8333 +190.10.8.211:8333 +190.145.22.202:8333 190.184.198.34:8333 -192.151.145.250:8333 -192.206.202.6:8333 +190.210.234.38:8333 +192.92.129.5:8333 +192.121.170.180:8333 +192.162.100.156:8333 +192.162.210.91:8333 +192.169.6.127:8333 +192.175.59.140:8333 +192.222.237.16:8333 192.228.101.157:8333 -193.2.76.41:8333 -193.27.209.100:8333 -193.33.237.187:8333 -193.46.83.17:8333 +193.23.181.135:8333 193.49.43.219:8333 -194.24.182.27:8333 -194.28.206.201:8333 -194.63.143.197:8333 -194.71.109.91:8333 -194.79.8.36:8333 -194.135.93.38:8333 +193.106.30.173:8333 +193.138.224.230:8333 +193.224.22.45:8333 +194.15.231.236:8333 +194.106.216.20:8333 194.186.160.253:8333 -195.9.140.134:8333 -195.39.206.29:8333 -195.67.36.89:8333 +194.246.86.32:8333 +195.22.104.23:8333 +195.49.75.233:8333 +195.91.244.138:8333 195.169.99.82:8333 -195.214.214.253:8333 -195.223.71.147:8333 -198.37.118.11:8333 -198.54.113.125:8333 -198.101.12.139:8333 +196.28.98.21:8333 +196.220.67.151:8333 +197.155.6.43:8333 +197.189.236.250:8333 +197.234.69.146:8333 198.143.12.105:8333 -198.251.83.19:8333 +198.187.28.2:8333 +199.68.197.5:8333 199.127.224.50:8333 -200.12.138.146:8333 -200.116.98.185:8333 +199.193.6.14:8333 +199.201.110.146:8333 +200.109.67.71:8333 200.122.128.130:8333 -202.29.6.48:8333 -202.133.115.115:8333 -203.59.17.160:8333 +201.238.223.165:8333 +202.47.225.242:8333 +203.60.2.67:8333 204.15.11.4:8333 -204.111.241.195:8333 -205.251.85.151:8333 -207.244.70.40:8333 -207.254.50.72:8333 -208.76.93.83:8333 -208.107.97.242:8333 -208.110.73.107:8333 +204.15.11.8:8333 +204.138.165.35:8333 +206.123.11.139:8333 +206.253.163.226:8333 +207.188.16.16:8333 +208.77.18.25:8333 +208.86.161.83:8333 +208.100.137.204:8333 +208.107.224.202:8333 208.118.235.190:8333 -209.73.142.226:8333 -209.81.9.223:8333 -209.126.107.166:8333 -209.177.86.19:8333 -209.250.6.190:8333 -210.1.219.155:8333 +209.159.137.146:8333 +209.161.4.164:8333 +209.197.13.62:8333 210.211.109.165:8333 -210.223.3.44:8333 -211.21.129.69:8333 -212.50.98.161:8333 -212.51.140.183:8333 +211.151.38.92:8333 +212.32.229.230:8333 +212.51.14.72:8333 212.56.108.81:8333 -212.83.35.173:8333 -212.90.179.206:8333 -212.93.226.90:8333 212.110.171.118:8333 -213.5.36.58:8333 -213.5.181.205:8333 -213.17.16.251:8333 +212.124.160.199:8333 +212.128.44.49:8333 +212.149.235.185:8333 +212.199.175.30:8333 +212.237.96.98:8333 +213.67.99.142:8333 213.91.205.134:8333 -213.91.211.17:8333 +213.115.224.252:8333 +213.131.12.10:8333 +213.132.76.184:8333 +213.152.161.170:45893 213.155.3.216:8333 -213.168.13.151:8333 -213.186.170.109:8334 -213.222.208.150:8333 -216.32.213.112:8333 -216.59.4.212:8333 -216.126.193.163:8333 -216.197.79.74:8333 -216.218.147.140:8333 -216.227.39.84:8333 -216.245.206.181:8333 -216.249.92.230:8333 -217.12.199.207:8333 -217.23.2.177:8333 -217.23.5.68:8333 -217.28.194.2:8333 -217.35.130.42:8333 -217.64.47.138:8333 -217.101.72.242:8333 -217.145.81.229:8333 -217.168.143.169:8333 +213.156.108.63:8333 +213.219.162.146:8333 +216.36.179.27:8333 +216.184.8.26:8333 +216.245.218.242:8333 +217.12.204.86:8333 +217.20.130.72:8333 217.169.7.111:8333 217.182.192.7:8333 +217.199.99.30:8333 219.88.232.229:8333 -219.113.244.52:8333 220.130.128.58:8333 -220.244.225.239:8333 -221.141.3.12:8333 -222.166.176.99:8333 -223.252.173.147:8333 -[2001:0:4137:9e76:1025:4e5:acb0:22cd]:8333 -[2001:0:4137:9e76:1078:18a6:5d2c:2461]:8333 -[2001:0:4137:9e76:10ec:236a:bd3b:f3c0]:8333 -[2001:0:4137:9e76:186d:3f17:b7ad:95cf]:8333 -[2001:0:4137:9e76:1870:242:ac03:aaf9]:8333 -[2001:0:4137:9e76:18a6:1102:2abf:eb70]:8333 -[2001:0:4137:9e76:1ce5:248c:4ff5:2b1d]:8333 -[2001:0:4137:9e76:200f:156a:bc77:3acd]:8333 -[2001:0:4137:9e76:2418:19d1:cddc:b1af]:8333 -[2001:0:4137:9e76:2857:3d78:aaf8:eb28]:8333 -[2001:0:4137:9e76:28b2:1b84:64fb:2d6a]:8333 -[2001:0:4137:9e76:2c70:d51:d046:1209]:8333 -[2001:0:4137:9e76:2cac:2fcf:46bb:be0d]:8333 -[2001:0:4137:9e76:305e:20ee:a94f:6f69]:8333 -[2001:0:4137:9e76:30cd:849:adfe:6e67]:8333 -[2001:0:4137:9e76:345b:f12:ae1e:2948]:8333 -[2001:0:4137:9e76:3c40:146e:9741:5a3a]:8333 -[2001:0:4137:9e76:3c9e:3c3e:9d6e:7340]:8333 -[2001:0:4137:9e76:499:29a8:d047:7ea1]:8333 -[2001:0:4137:9e76:51:24:81b2:59e3]:8333 -[2001:0:4137:9e76:889:2d7c:b61b:bf0d]:8333 -[2001:0:4137:9e76:c9f:379c:add2:c938]:8333 -[2001:0:4137:9e76:cd6:2eb4:b82b:addb]:8333 -[2001:0:4137:9e76:cf0:2e3a:b29d:6207]:8333 -[2001:0:53aa:64c:1485:fbf9:a798:1ffe]:8333 -[2001:0:53aa:64c:59:617f:a10d:e0]:8333 -[2001:0:5ef5:79fb:1020:2cd0:4750:eb12]:8333 -[2001:0:5ef5:79fb:1036:1d50:3881:6930]:8333 -[2001:0:5ef5:79fb:10a4:27d8:9c0a:cfa9]:8333 -[2001:0:5ef5:79fb:10ae:5a8:524b:dcc4]:8333 -[2001:0:5ef5:79fb:1892:3e3a:3f74:affa]:8333 -[2001:0:5ef5:79fb:1c95:1a60:d1f5:215b]:8333 -[2001:0:5ef5:79fb:200b:16ef:b9cf:9860]:8333 -[2001:0:5ef5:79fb:28e4:fbff:3237:992]:8333 -[2001:0:5ef5:79fb:2ce8:1d9e:b3bf:b53e]:8333 -[2001:0:5ef5:79fb:300a:2e20:4750:eb12]:8333 -[2001:0:5ef5:79fb:30a2:1ad9:5324:836a]:8333 -[2001:0:5ef5:79fb:3409:1996:bcac:241f]:8333 -[2001:0:5ef5:79fb:344b:2bd4:bb3e:e26]:8333 -[2001:0:5ef5:79fb:34b3:11db:e7da:d461]:8333 -[2001:0:5ef5:79fb:3839:2e0c:ba30:288e]:8333 -[2001:0:5ef5:79fb:3880:ef4:b5f0:ee4d]:8333 -[2001:0:5ef5:79fb:389f:52:9c0c:1f41]:8333 -[2001:0:5ef5:79fb:3c73:304a:9d8b:99d5]:8333 -[2001:0:5ef5:79fb:3cac:33e4:39ca:38c]:8333 -[2001:0:5ef5:79fb:6f:3667:5398:538f]:8333 -[2001:0:5ef5:79fb:88c:3e6:9454:3331]:8333 -[2001:0:5ef5:79fb:89:3b55:9fcc:8e66]:8333 -[2001:0:5ef5:79fb:c9b:3d65:bdf4:5d58]:8333 -[2001:0:5ef5:79fb:cb7:8cc:b8ee:6806]:8333 -[2001:0:5ef5:79fd:24f6:37b5:b9d2:2aa7]:8333 -[2001:0:5ef5:79fd:3c63:82e:aabc:bd39]:8333 -[2001:0:5ef5:79fd:3cf5:2eb7:c966:561d]:8333 -[2001:0:5ef5:79fd:cf4:28e2:aabd:b766]:8333 -[2001:0:9d38:6ab8:10f6:453:3ca4:1a8e]:8333 -[2001:0:9d38:6ab8:14dd:298b:431c:bfec]:8333 -[2001:0:9d38:6ab8:3051:1561:b62d:73a5]:8333 -[2001:0:9d38:6ab8:3467:ffa:b612:e9c6]:8333 -[2001:0:9d38:6ab8:8e8:1e26:e8e3:eed7]:8333 -[2001:0:9d38:6ab8:c82:37b3:47ee:3ae2]:8333 -[2001:0:9d38:6abd:1052:3cd8:a89b:e67]:8333 -[2001:0:9d38:6abd:144d:23f3:abcb:8bcb]:8333 -[2001:0:9d38:6abd:1c2e:31df:adf1:e616]:8333 -[2001:0:9d38:6abd:1c41:213b:facc:9c6b]:8333 -[2001:0:9d38:6abd:2093:12b5:8cbf:4f57]:8333 -[2001:0:9d38:6abd:243a:2394:fd91:712c]:8333 -[2001:0:9d38:6abd:2833:9f8:c94c:6881]:8333 -[2001:0:9d38:6abd:2c84:29d3:ae5a:f6f0]:8333 -[2001:0:9d38:6abd:2ce4:d50:cb22:3672]:8333 -[2001:0:9d38:6abd:3824:816:c30d:e9d4]:8333 -[2001:0:9d38:6abd:389a:24e9:cb5c:a1cd]:8333 -[2001:0:9d38:6abd:38bd:88f:2193:4932]:8333 -[2001:0:9d38:6abd:3c4f:cb1:d65b:d775]:8333 -[2001:0:9d38:6abd:3c51:280b:b1e9:ffd]:8333 -[2001:0:9d38:6abd:3c5a:2e2:2193:4932]:8333 -[2001:0:9d38:6abd:3c5e:3ebf:3dc0:703a]:8333 -[2001:0:9d38:6abd:4c9:12fc:d1d9:dc21]:8333 -[2001:0:9d38:6abd:6e:34e7:d0a7:6772]:8333 -[2001:0:9d38:6abd:8de:1f29:2aea:f96f]:8333 -[2001:0:9d38:6abd:c5f:2674:a467:787c]:8333 -[2001:0:9d38:6abd:cc0:23a4:ad7c:c998]:8333 -[2001:0:9d38:78cf:20c0:2097:d188:9c3b]:8333 -[2001:0:9d38:78cf:2420:dda:4ff6:8794]:8333 -[2001:0:9d38:78cf:2892:fcb:26b2:22ac]:8333 -[2001:0:9d38:78cf:3020:1ad7:26b2:22ac]:8333 -[2001:0:9d38:78cf:30ae:211b:e717:7788]:8333 -[2001:0:9d38:78cf:30d0:6edd:a418:a9e9]:8333 -[2001:0:9d38:78cf:30d9:3278:b004:65a7]:8333 -[2001:0:9d38:78cf:387a:17d5:dacb:bdf1]:8333 -[2001:0:9d38:78cf:3c38:c41:433c:7b87]:8333 -[2001:0:9d38:78cf:467:193:a8b0:a122]:8333 -[2001:0:9d38:78cf:c65:fb96:97d2:a9b0]:8333 -[2001:0:9d38:78cf:c9f:2633:d169:9999]:8333 -[2001:0:9d38:78cf:ce2:aba:d120:90db]:8333 -[2001:0:9d38:90d7:105d:26f2:a241:7339]:8333 -[2001:0:9d38:90d7:1062:3f95:e065:fc21]:8333 -[2001:0:9d38:90d7:10a6:19f6:ab95:ebcb]:8333 -[2001:0:9d38:90d7:14e2:22cb:738f:9489]:8333 -[2001:0:9d38:90d7:18fb:3da9:893d:1d57]:8333 -[2001:0:9d38:90d7:1cc3:2534:e020:53fa]:8333 -[2001:0:9d38:90d7:206d:2b34:d0cb:9de8]:8333 -[2001:0:9d38:90d7:20cb:2cb:b9a7:ca5e]:8333 -[2001:0:9d38:90d7:245c:2753:4382:704b]:8333 -[2001:0:9d38:90d7:24d6:225f:793b:bf5]:8333 -[2001:0:9d38:90d7:24da:8f0:bbf9:9c93]:8333 -[2001:0:9d38:90d7:28a2:107b:438e:b08d]:8333 -[2001:0:9d38:90d7:2c16:d58:b381:b61]:8333 -[2001:0:9d38:90d7:2c68:3068:cb59:3be7]:8333 -[2001:0:9d38:90d7:2c90:3855:b94f:c926]:8333 -[2001:0:9d38:90d7:2ca2:3592:c111:dd82]:8333 -[2001:0:9d38:90d7:2cce:1f6e:b381:8605]:8333 -[2001:0:9d38:90d7:3435:3915:2bcc:6cc7]:8333 -[2001:0:9d38:90d7:3438:2b9f:ad57:a721]:8333 +220.191.169.90:8333 +221.127.43.207:8333 +222.239.193.210:8333 +223.17.202.206:8333 +[2001:0:4137:9e76:10f2:2873:970b:2068]:8333 +[2001:0:4137:9e76:10f6:1aa2:ae9d:4286]:8333 +[2001:0:4137:9e76:140a:d05:c1e1:b5c4]:8333 +[2001:0:4137:9e76:142a:1957:b61e:56e]:8333 +[2001:0:4137:9e76:142d:fac:2aaf:e4c2]:8333 +[2001:0:4137:9e76:1471:452:6671:8274]:8333 +[2001:0:4137:9e76:1482:530:b145:7e28]:8333 +[2001:0:4137:9e76:18ac:3954:3901:a257]:8333 +[2001:0:4137:9e76:18d5:3c77:829a:6fe6]:8333 +[2001:0:4137:9e76:2066:164f:b39d:b087]:8333 +[2001:0:4137:9e76:2069:78b:b7d5:5860]:8333 +[2001:0:4137:9e76:20ac:22b1:bb18:1160]:8333 +[2001:0:4137:9e76:20f6:147f:e7e9:ddd1]:8333 +[2001:0:4137:9e76:20fa:3126:97f1:600d]:8333 +[2001:0:4137:9e76:2457:f34:a313:4b99]:8333 +[2001:0:4137:9e76:28f4:2512:bc91:2e53]:8333 +[2001:0:4137:9e76:2c55:fa9:fde5:5d86]:8333 +[2001:0:4137:9e76:2cba:1828:52ae:7501]:8333 +[2001:0:4137:9e76:2cf3:78fc:a138:e6ed]:8333 +[2001:0:4137:9e76:3001:bf6:be62:cce5]:8333 +[2001:0:4137:9e76:30a8:3afb:b6d5:2bd7]:8333 +[2001:0:4137:9e76:30e6:44d:ae7f:749d]:8333 +[2001:0:4137:9e76:3402:daf:b475:daf9]:8333 +[2001:0:4137:9e76:3423:3d03:d771:d501]:8333 +[2001:0:4137:9e76:3424:211:b600:b4cb]:8333 +[2001:0:4137:9e76:342f:1453:cddc:4f03]:8333 +[2001:0:4137:9e76:3457:248d:a0b9:3bc9]:8333 +[2001:0:4137:9e76:386f:3846:b995:188]:8333 +[2001:0:4137:9e76:38a8:318a:e7dc:aee1]:8333 +[2001:0:4137:9e76:38eb:1e88:addb:181c]:8333 +[2001:0:4137:9e76:3c39:27e3:4758:365c]:8333 +[2001:0:4137:9e76:3c7d:3fa4:86ad:4ebb]:8333 +[2001:0:4137:9e76:3cfd:3181:b2c7:5c5e]:8333 +[2001:0:4137:9e76:401:2157:684e:f2d6]:8333 +[2001:0:4137:9e76:43a:1a64:bd14:fb16]:8333 +[2001:0:4137:9e76:47d:bb:ae1e:2948]:8333 +[2001:0:4137:9e76:843:9b9e:cd0a:6655]:8333 +[2001:0:4137:9e76:886:3c19:addd:9a58]:8333 +[2001:0:4137:9e76:8ba:9f8:9ead:f21]:8333 +[2001:0:4137:9e76:c06:124c:a482:a761]:8333 +[2001:0:4137:9e76:cda:b84:8d4c:d1e6]:8333 +[2001:0:53aa:64c:20:a71:858b:83f7]:8333 +[2001:0:53aa:64c:c5:235d:a10d:e0]:8333 +[2001:0:5ef5:79fb:103a:23fb:bb8a:ed5b]:8333 +[2001:0:5ef5:79fb:1064:d3d:51ff:5938]:8333 +[2001:0:5ef5:79fb:10fd:1369:715e:6aa7]:8333 +[2001:0:5ef5:79fb:14d5:1758:b17d:5eb1]:8333 +[2001:0:5ef5:79fb:1817:2634:9fc9:1bc4]:8333 +[2001:0:5ef5:79fb:181a:2717:9441:c1eb]:8333 +[2001:0:5ef5:79fb:1875:bc8:b1c2:1b4]:8333 +[2001:0:5ef5:79fb:18b5:3185:51a2:35d]:8333 +[2001:0:5ef5:79fb:18c3:feb:b471:49d1]:8333 +[2001:0:5ef5:79fb:18dd:3bd5:418f:c1e]:8333 +[2001:0:5ef5:79fb:1c19:3062:bcaa:96b]:8333 +[2001:0:5ef5:79fb:1c53:14bd:b8d9:7aa2]:8333 +[2001:0:5ef5:79fb:1c60:82b:94fd:a452]:8333 +[2001:0:5ef5:79fb:1c85:2e50:ba7d:a1a]:8333 +[2001:0:5ef5:79fb:1cff:2d43:51f9:b889]:8333 +[2001:0:5ef5:79fb:2074:221a:4750:eb12]:8333 +[2001:0:5ef5:79fb:208f:2d83:e0f5:e31f]:8333 +[2001:0:5ef5:79fb:2092:371f:9dfb:98cd]:8333 +[2001:0:5ef5:79fb:20f3:39a2:39ca:38c]:8333 +[2001:0:5ef5:79fb:281c:2085:518d:9c97]:8333 +[2001:0:5ef5:79fb:2851:c:524c:a180]:8333 +[2001:0:5ef5:79fb:2853:3b95:a430:40f3]:8333 +[2001:0:5ef5:79fb:28f6:30a4:30d9:1201]:8333 +[2001:0:5ef5:79fb:2c5f:1ade:718f:609d]:8333 +[2001:0:5ef5:79fb:2cc0:1b38:e7af:ae80]:8333 +[2001:0:5ef5:79fb:3000:3dc4:524d:3ce2]:8333 +[2001:0:5ef5:79fb:3060:2e81:518f:63bc]:8333 +[2001:0:5ef5:79fb:3068:507:bcaf:dbad]:8333 +[2001:0:5ef5:79fb:308f:f3:935d:6a1b]:8333 +[2001:0:5ef5:79fb:30ce:3301:d2d0:9bbc]:8333 +[2001:0:5ef5:79fb:30db:3145:4381:f147]:8333 +[2001:0:5ef5:79fb:34a3:2298:b7cd:22f6]:8333 +[2001:0:5ef5:79fb:41e:160:bc48:791d]:8333 +[2001:0:5ef5:79fb:42:b4fc:3f74:affb]:8333 +[2001:0:5ef5:79fb:47a:16aa:d0c9:30a4]:8333 +[2001:0:5ef5:79fb:89c:3481:d973:5dad]:8333 +[2001:0:5ef5:79fb:8be:314a:26b2:efef]:8333 +[2001:0:5ef5:79fb:8f3:3daf:3f21:bac]:8333 +[2001:0:5ef5:79fb:c1f:20f4:b9ac:99db]:8333 +[2001:0:5ef5:79fb:c70:105c:77de:9f7d]:8333 +[2001:0:5ef5:79fb:ed:200c:b9ac:34db]:8333 +[2001:0:5ef5:79fd:3057:85b:b703:255d]:8333 +[2001:0:5ef5:79fd:8d1:13c6:5d0a:b117]:8333 +[2001:0:9d38:6ab8:1007:395e:cd3a:82f2]:8333 +[2001:0:9d38:6ab8:108b:34b5:e8e3:eed7]:8333 +[2001:0:9d38:6ab8:109c:738:7fb9:785c]:8333 +[2001:0:9d38:6ab8:1401:393:ba7f:c313]:8333 +[2001:0:9d38:6ab8:1449:21d9:a05e:32f5]:8333 +[2001:0:9d38:6ab8:1498:36b6:a29b:12a4]:8333 +[2001:0:9d38:6ab8:183d:3649:b8f5:35d9]:8333 +[2001:0:9d38:6ab8:1857:3293:438b:73de]:8333 +[2001:0:9d38:6ab8:18b0:15d3:431c:bfec]:8333 +[2001:0:9d38:6ab8:18b1:288b:51c9:db37]:8333 +[2001:0:9d38:6ab8:18d5:2a37:6806:9797]:8333 +[2001:0:9d38:6ab8:1c42:3a1c:942f:7f08]:8333 +[2001:0:9d38:6ab8:1c7a:2fb7:e7d5:7ee2]:8333 +[2001:0:9d38:6ab8:1cc6:38c6:438b:73de]:8333 +[2001:0:9d38:6ab8:1cd6:2f48:fa1b:51c1]:8333 +[2001:0:9d38:6ab8:1cda:2fdf:b091:dbe5]:8333 +[2001:0:9d38:6ab8:1cf3:b9e:a14a:41f3]:8333 +[2001:0:9d38:6ab8:2015:473:9d21:cc3c]:8333 +[2001:0:9d38:6ab8:205d:eea3:a3c8:ea79]:8333 +[2001:0:9d38:6ab8:207c:19b1:e758:1c46]:8333 +[2001:0:9d38:6ab8:20cb:6b0:46cc:c27d]:8333 +[2001:0:9d38:6ab8:20cd:1cd9:54e6:5a6e]:8333 +[2001:0:9d38:6ab8:20ef:bc1:95f0:a658]:8333 +[2001:0:9d38:6ab8:2409:2ea4:47ee:3c9d]:8333 +[2001:0:9d38:6ab8:2427:330a:9441:dc2d]:8333 +[2001:0:9d38:6ab8:2436:3c78:431d:d559]:8333 +[2001:0:9d38:6ab8:24dd:2acb:b8a9:5ade]:8333 +[2001:0:9d38:6ab8:2869:2cb3:b57b:311c]:8333 +[2001:0:9d38:6ab8:28bf:33d4:9d29:8edc]:8333 +[2001:0:9d38:6ab8:28e0:142e:3ed6:b182]:8333 +[2001:0:9d38:6ab8:28f3:1675:c3ed:5be7]:8333 +[2001:0:9d38:6ab8:2c4c:21d6:946c:ef01]:8333 +[2001:0:9d38:6ab8:2cd6:3f49:a1ec:736]:8333 +[2001:0:9d38:6ab8:301d:1cd6:ba5a:2935]:8333 +[2001:0:9d38:6ab8:302b:340f:e723:b15e]:8333 +[2001:0:9d38:6ab8:3034:2d96:b57f:b0e6]:8333 +[2001:0:9d38:6ab8:306b:872:b4bc:d79f]:8333 +[2001:0:9d38:6ab8:30a4:1190:4315:e53]:8333 +[2001:0:9d38:6ab8:30c3:1362:521f:52c5]:8333 +[2001:0:9d38:6ab8:30e7:3e5c:da3f:6466]:8333 +[2001:0:9d38:6ab8:3439:223:a04a:fdfd]:8333 +[2001:0:9d38:6ab8:3477:14cd:f7de:dee8]:8333 +[2001:0:9d38:6ab8:3498:1a5:4635:2b50]:8333 +[2001:0:9d38:6ab8:349d:db2:a0e6:29a2]:8333 +[2001:0:9d38:6ab8:34f7:15b2:3012:3a74]:8333 +[2001:0:9d38:6ab8:3809:2941:4344:4838]:8333 +[2001:0:9d38:6ab8:3809:37b7:31b5:8e3d]:8333 +[2001:0:9d38:6ab8:3877:2dac:b691:719c]:8333 +[2001:0:9d38:6ab8:388a:24f3:a141:c194]:8333 +[2001:0:9d38:6ab8:38ba:3b3e:430c:fb74]:8333 +[2001:0:9d38:6ab8:38c4:2f2a:9357:b1ae]:8333 +[2001:0:9d38:6ab8:38e2:23f:b4f6:6ad1]:8333 +[2001:0:9d38:6ab8:3c56:2171:9d80:d360]:8333 +[2001:0:9d38:6ab8:3cab:1421:3ca4:1a8e]:8333 +[2001:0:9d38:6ab8:3f:2441:6806:9797]:8333 +[2001:0:9d38:6ab8:424:321:52b3:5633]:8333 +[2001:0:9d38:6ab8:47c:32ef:a7a8:a2b4]:8333 +[2001:0:9d38:6ab8:4a7:3cdd:9d1b:708]:8333 +[2001:0:9d38:6ab8:4c3:3a54:9d1c:2ad7]:8333 +[2001:0:9d38:6ab8:813:3ae3:bdd2:66d8]:8333 +[2001:0:9d38:6ab8:818:cf4:27f2:b5f5]:8333 +[2001:0:9d38:6ab8:855:33f7:6dbd:53c4]:8333 +[2001:0:9d38:6ab8:868:1baa:b174:b764]:8333 +[2001:0:9d38:6ab8:878:21cf:2b5b:2860]:8333 +[2001:0:9d38:6ab8:8a4:e1d1:79ec:7cee]:8333 +[2001:0:9d38:6ab8:8b3:392c:ab0d:ae6b]:8333 +[2001:0:9d38:6ab8:8ff:352f:b208:5604]:8333 +[2001:0:9d38:6ab8:c2f:1793:fa42:acdc]:8333 +[2001:0:9d38:6ab8:c36:25f:a0d0:e871]:8333 +[2001:0:9d38:6ab8:d3:69e:d0a0:1b73]:8333 +[2001:0:9d38:6abd:109f:379e:aeff:3957]:8333 +[2001:0:9d38:6abd:10a5:2f7d:ab07:9c7b]:8333 +[2001:0:9d38:6abd:1462:3fe1:b2cf:dcf0]:8333 +[2001:0:9d38:6abd:180b:29be:3429:fede]:8333 +[2001:0:9d38:6abd:1857:24c:46f4:7dc9]:8333 +[2001:0:9d38:6abd:18d5:a69:4b4a:6e8b]:8333 +[2001:0:9d38:6abd:1c20:25a2:3f5d:2da4]:8333 +[2001:0:9d38:6abd:1c96:24dc:a753:d6f2]:8333 +[2001:0:9d38:6abd:1ce7:533:26f3:2aab]:8333 +[2001:0:9d38:6abd:2065:3008:76b5:cb06]:8333 +[2001:0:9d38:6abd:20b2:434:4387:f5e1]:8333 +[2001:0:9d38:6abd:20ff:147c:840c:b0db]:8333 +[2001:0:9d38:6abd:2436:3c96:91e9:2de3]:8333 +[2001:0:9d38:6abd:244c:1817:ae9f:8a38]:8333 +[2001:0:9d38:6abd:284c:29ce:88b5:c86f]:8333 +[2001:0:9d38:6abd:285a:5c:c16b:119a]:8333 +[2001:0:9d38:6abd:2c5f:a51:a671:3d90]:8333 +[2001:0:9d38:6abd:3065:3255:4b21:e520]:8333 +[2001:0:9d38:6abd:341d:2dfa:892f:4366]:8333 +[2001:0:9d38:6abd:3450:302f:23b3:a33a]:8333 +[2001:0:9d38:6abd:3456:2308:d0b5:7970]:8333 +[2001:0:9d38:6abd:3470:346d:af23:d41b]:8333 +[2001:0:9d38:6abd:34ba:20c2:9a5a:dd02]:8333 +[2001:0:9d38:6abd:3846:1133:a68c:ea80]:8333 +[2001:0:9d38:6abd:38ef:31ea:6cd1:45db]:8333 +[2001:0:9d38:6abd:3c1f:c35a:cc00:28d3]:8333 +[2001:0:9d38:6abd:3c49:1539:fe22:5b3b]:8333 +[2001:0:9d38:6abd:3c5e:2ecd:88ee:787c]:8333 +[2001:0:9d38:6abd:3c74:194:4f94:e1b]:8333 +[2001:0:9d38:6abd:4c4:3492:4d56:35dd]:8333 +[2001:0:9d38:6abd:4e7:35f2:ae92:cbcd]:8333 +[2001:0:9d38:6abd:850:2b2f:adbf:fa7e]:8333 +[2001:0:9d38:6abd:8ba:f4f:3e75:b00b]:8333 +[2001:0:9d38:6abd:9e:3294:c2b5:67d7]:8333 +[2001:0:9d38:6abd:c74:81b:a2fb:aa90]:8333 +[2001:0:9d38:78cf:146b:2cc2:b2a5:db7]:8333 +[2001:0:9d38:78cf:18d3:1602:2a06:c562]:8333 +[2001:0:9d38:78cf:24a7:ee0:72cc:7f75]:8333 +[2001:0:9d38:78cf:2862:1384:b4b8:406f]:8333 +[2001:0:9d38:78cf:30c4:3698:92a5:3af9]:8333 +[2001:0:9d38:78cf:340b:1270:4d61:857]:8333 +[2001:0:9d38:78cf:3cb3:2773:4da3:d4c]:8333 +[2001:0:9d38:78cf:3cdf:8ab:a331:d75]:8333 +[2001:0:9d38:78cf:4d1:366f:4f91:eafb]:8333 +[2001:0:9d38:78cf:83f:b1c:c1a4:ad71]:8333 +[2001:0:9d38:90d7:1067:13c5:a69c:b099]:8333 +[2001:0:9d38:90d7:10aa:20c7:aa6f:d318]:8333 +[2001:0:9d38:90d7:10df:16c3:b351:e824]:8333 +[2001:0:9d38:90d7:1464:255e:9208:8012]:8333 +[2001:0:9d38:90d7:14e1:1b8:b256:ff4c]:8333 +[2001:0:9d38:90d7:180c:ebf:2a63:93c0]:8333 +[2001:0:9d38:90d7:18fb:9d7:af8d:a5d5]:8333 +[2001:0:9d38:90d7:1ca1:3e8e:ab02:edbe]:8333 +[2001:0:9d38:90d7:1cd7:3fe8:e80f:53f9]:8333 +[2001:0:9d38:90d7:20d8:1062:2684:32c2]:8333 +[2001:0:9d38:90d7:2419:373e:da40:1e51]:8333 +[2001:0:9d38:90d7:242b:1ac2:fdcc:af6a]:8333 +[2001:0:9d38:90d7:2442:2d34:9e97:36a0]:8333 +[2001:0:9d38:90d7:246c:24f1:3c0f:65fc]:8333 +[2001:0:9d38:90d7:24c4:15e7:d0cb:7a52]:8333 +[2001:0:9d38:90d7:2837:324e:d0cb:9f45]:22475 +[2001:0:9d38:90d7:2858:2d7c:bc51:6ee0]:8333 +[2001:0:9d38:90d7:289e:1b03:438e:b517]:8333 +[2001:0:9d38:90d7:289f:30fc:54bc:9685]:8333 +[2001:0:9d38:90d7:28a2:760:a6b3:3139]:8333 +[2001:0:9d38:90d7:28a4:1b25:b8c7:38ff]:8333 +[2001:0:9d38:90d7:28d3:1049:fd91:712c]:8333 +[2001:0:9d38:90d7:2c32:2da7:c111:dd82]:8333 +[2001:0:9d38:90d7:2c91:1e07:5d3d:7eb1]:8333 +[2001:0:9d38:90d7:2ce5:3c7:b736:9128]:8333 +[2001:0:9d38:90d7:2cf4:30d4:e020:53fa]:8333 +[2001:0:9d38:90d7:2cfc:2221:98e5:eed7]:8333 +[2001:0:9d38:90d7:3016:aed:6107:4df]:8333 +[2001:0:9d38:90d7:303e:3e8a:d06a:d137]:8333 +[2001:0:9d38:90d7:30ee:19d6:6e7b:908e]:8333 +[2001:0:9d38:90d7:342c:3ecc:c2a2:1e31]:8333 [2001:0:9d38:90d7:3474:1df1:e732:e5e3]:8333 -[2001:0:9d38:90d7:38c4:37af:ab0a:f5ef]:8333 -[2001:0:9d38:90d7:3a:39fd:a43b:5591]:8333 -[2001:0:9d38:90d7:3c9d:2a45:d537:3bd6]:8333 -[2001:0:9d38:90d7:3cfb:2cf5:5254:4d1e]:8333 -[2001:0:9d38:90d7:43f:337:adb4:6310]:8333 -[2001:0:9d38:90d7:493:995:d2e9:39be]:8333 -[2001:0:9d38:90d7:5b:ce3:b275:92ab]:8333 -[2001:0:9d38:90d7:8a8:59d:d0cb:d585]:8333 -[2001:0:9d38:90d7:c8e:1ba0:c5a9:dace]:8333 -[2001:0:9d38:90d7:cdb:365f:2302:f729]:8333 -[2001:0:9d38:90d7:cf5:222e:893e:716c]:8333 -[2001:0:9d38:90d7:d6:1085:b8dd:41c2]:8333 -[2001:0:9d38:953c:101a:23b3:6b98:f888]:8333 -[2001:0:9d38:953c:1805:f38:3eb2:2121]:8333 -[2001:0:9d38:953c:1858:16f9:3833:da19]:8333 -[2001:0:9d38:953c:18ea:2735:e73d:adc5]:8333 +[2001:0:9d38:90d7:3496:2e2d:cb17:c3bd]:8333 +[2001:0:9d38:90d7:34f3:3584:d0a4:aa5]:8333 +[2001:0:9d38:90d7:38e6:1092:d0cb:7576]:8333 +[2001:0:9d38:90d7:38ec:611:e05f:df3d]:8333 +[2001:0:9d38:90d7:38f5:3938:b454:4717]:8333 +[2001:0:9d38:90d7:38f8:14ce:8809:7786]:8333 +[2001:0:9d38:90d7:3c2c:10a4:bbfa:e09d]:8333 +[2001:0:9d38:90d7:3c35:2a8e:e79f:62fd]:8333 +[2001:0:9d38:90d7:3c40:77b:c2bb:79]:8333 +[2001:0:9d38:90d7:65:2adf:b8de:1781]:8333 +[2001:0:9d38:90d7:7c:129:d0cb:6e8b]:8333 +[2001:0:9d38:90d7:851:10d8:9d58:7059]:8333 +[2001:0:9d38:90d7:85d:102:2aa2:519a]:8333 +[2001:0:9d38:90d7:896:fe0:afc6:2270]:8333 +[2001:0:9d38:90d7:8a0:22cc:a0b3:d9da]:8333 +[2001:0:9d38:90d7:c0d:de2:b94f:774]:8333 +[2001:0:9d38:90d7:cff:c79:aa69:cb82]:8333 +[2001:0:9d38:953c:104e:8af:b3aa:f300]:8333 +[2001:0:9d38:953c:1063:10c4:93fd:77b5]:8333 +[2001:0:9d38:953c:10dd:3d0d:daee:ccda]:8333 +[2001:0:9d38:953c:1883:22e3:af92:33c7]:8333 +[2001:0:9d38:953c:1c0a:1583:9473:5f2e]:8333 [2001:0:9d38:953c:1c44:2b70:9de7:a7cc]:8333 -[2001:0:9d38:953c:200a:3f95:bb7c:c09f]:8333 -[2001:0:9d38:953c:200c:3473:b85d:ddd]:8333 -[2001:0:9d38:953c:200f:5a0:47c6:5507]:8333 -[2001:0:9d38:953c:2097:204a:47c5:5881]:8333 -[2001:0:9d38:953c:248f:24cd:aaf5:dee3]:8333 -[2001:0:9d38:953c:287d:168e:3caf:47af]:8333 -[2001:0:9d38:953c:28c1:58d:b721:94c1]:8333 -[2001:0:9d38:953c:2c31:30a3:39d3:528]:8188 -[2001:0:9d38:953c:2c3d:309b:d2db:8288]:8333 -[2001:0:9d38:953c:2c47:1b36:52c1:3c73]:8333 -[2001:0:9d38:953c:304a:10e1:b739:822a]:8333 -[2001:0:9d38:953c:30a3:29fd:33f6:eaab]:8333 -[2001:0:9d38:953c:3427:859b:b525:1069]:8333 -[2001:0:9d38:953c:3459:2541:3651:d675]:8333 -[2001:0:9d38:953c:4f5:9c88:af91:d3d3]:8333 -[2001:0:9d38:953c:cd1:1d54:b80a:42f4]:8333 -[2001:0:9d38:953c:cfa:37e6:9d8e:7474]:8333 +[2001:0:9d38:953c:1cbb:646:d2cf:fd00]:8333 +[2001:0:9d38:953c:2051:348d:dc5a:c3c2]:8333 +[2001:0:9d38:953c:24f8:198a:d023:6580]:8333 +[2001:0:9d38:953c:2c32:2ea8:b817:2bb0]:8333 +[2001:0:9d38:953c:2c6d:3cef:4386:4937]:8333 +[2001:0:9d38:953c:2cb1:1719:5398:e444]:8333 +[2001:0:9d38:953c:3053:8a5e:25e4:352d]:8333 +[2001:0:9d38:953c:307b:2309:b347:3fdc]:8333 +[2001:0:9d38:953c:3084:1e46:8a72:750f]:8333 +[2001:0:9d38:953c:30a8:2304:9d47:7fdf]:8333 +[2001:0:9d38:953c:30b9:2ea0:e80c:53e5]:8333 +[2001:0:9d38:953c:30cf:3e04:a88b:4fe8]:8333 +[2001:0:9d38:953c:3427:2c62:bd53:f12d]:8333 +[2001:0:9d38:953c:3445:1bcb:b8b5:9653]:8333 +[2001:0:9d38:953c:3874:295f:9de2:cf3c]:8333 +[2001:0:9d38:953c:38bc:3f1:52c4:ea47]:8333 +[2001:0:9d38:953c:38c9:394f:bea2:fd60]:8333 +[2001:0:9d38:953c:38e8:2391:b6b2:90c1]:8333 +[2001:0:9d38:953c:3c43:3f1:b489:f8b8]:8333 +[2001:0:9d38:953c:4c5:2ae2:b643:3866]:8333 +[2001:0:9d38:953c:4db:3a7f:87b0:f876]:8333 +[2001:0:9d38:953c:8be:ce8:b8c5:5212]:8333 +[2001:0:9d38:953c:ac:2eab:2f99:80c4]:8333 +[2001:0:9d38:953c:c0a:1923:52a0:7ab2]:8333 +[2001:0:9d38:953c:c2:1715:b80b:7121]:8333 +[2001:0:9d38:953c:c8c:ee1:5199:bf8a]:8333 +[2001:0:9d38:953c:cbb:3f5:a670:b045]:8333 +[2001:13d8:1c01:1000::8]:8333 [2001:13d8:1c01:2000:2470::1]:8333 -[2001:1470:fffd:202c:225:90ff:fe8f:5f62]:8333 -[2001:14ba:200:0:543c:42ce:a48b:b0d0]:8333 -[2001:14ba:2fc:700:41b2:df51:efd8:f581]:8333 +[2001:14ba:1900::754:f271:151c]:8333 +[2001:1608:10:156:38::265c]:8333 +[2001:1620:923:0:75be:ed92:1a01:641]:8333 +[2001:1680:101:8c::1]:8333 +[2001:1838:2000:413::3]:8333 +[2001:19c0:1:801:801:ff00:46c:2]:8333 +[2001:19f0:0:204f:5400:ff:fe05:2d2e]:8333 [2001:19f0:5000:8c8b:5400:ff:fe1f:c023]:8333 -[2001:19f0:5:749:5400:ff:fe71:c3fc]:8333 -[2001:19f0:5:bc:5400:ff:fe3b:9339]:8333 -[2001:19f0:7402:42c:5400:ff:fe6c:b9b8]:8333 -[2001:1af8:4010:a08f:f811:e5f0:3f63:e753]:8333 -[2001:1af8:4010:a094:3333::8c38]:8333 +[2001:19f0:5:17a7:5400:ff:fe87:cc21]:8333 +[2001:19f0:5c01:63b:5400:1ff:fe47:2ede]:8333 +[2001:19f0:ac01:2fb:5400:ff:fe5b:c3ff]:8333 [2001:1af8:4070:a016:3333::5afb]:8333 [2001:1af8:4700:a071:4444::e26e]:8333 -[2001:1bc8:1a0:590e:2e0:f4ff:fe16:3a39]:8333 -[2001:2040:77::89]:8333 -[2001:288:1001:107:294e:5581:74bd:42f9]:8333 -[2001:3c8:c103:a001::48]:8333 +[2001:1bc0::ffff:aaaa:21]:8333 +[2001:200:0:8801:5054:ff:fef2:1d0]:8333 [2001:4128:6135:10:20c:29ff:fe69:9e81]:8333 [2001:4128:6135:2010:21e:bff:fee8:a3c0]:8333 [2001:4128:6135:e001:5054:ff:fe37:e9eb]:8333 [2001:4178:6:1427:62:116:188:85]:8333 -[2001:41d0:1004:20f0::]:8333 +[2001:41c9:1:424::231]:8333 +[2001:41d0:1000:1e1f::]:8333 +[2001:41d0:1004:1fef::]:8333 +[2001:41d0:1004:24a5::]:8333 +[2001:41d0:1008:1c23::]:8333 [2001:41d0:1008:2752::]:8333 -[2001:41d0:1:4722::1]:8333 -[2001:41d0:1:6f57::1]:8333 -[2001:41d0:1:7353::1]:8333 -[2001:41d0:1:7469::1]:8333 +[2001:41d0:1:45d8::1]:8333 [2001:41d0:1:7d09::1]:8333 +[2001:41d0:1:8113::1]:8333 +[2001:41d0:1:8649::1]:8333 [2001:41d0:1:8b26::1]:8333 -[2001:41d0:1:c129::1]:8333 +[2001:41d0:1:a5b8::1]:8333 +[2001:41d0:1:ab6b::1]:8333 +[2001:41d0:1:afd8::]:8333 +[2001:41d0:1:b421::1]:8333 +[2001:41d0:1:b5ce::1]:8333 [2001:41d0:1:d227::]:8333 +[2001:41d0:1:dabd::1]:8333 [2001:41d0:1:e13b::1]:8333 -[2001:41d0:1:e623::1]:8333 +[2001:41d0:1:f176::1]:8333 +[2001:41d0:203:10bd::]:8333 [2001:41d0:2:16be::1]:8333 -[2001:41d0:2:203c::1]:8333 -[2001:41d0:2:3242::]:8333 -[2001:41d0:2:8a0f::]:8333 +[2001:41d0:2:53df::]:8333 [2001:41d0:2:8c65::]:8333 -[2001:41d0:2:8d13::]:8333 -[2001:41d0:2:9459::]:8333 -[2001:41d0:2:950a:ffff:ffff:0:3]:8333 +[2001:41d0:2:9431::]:8333 [2001:41d0:2:9c94::1]:8333 -[2001:41d0:2:a212::]:8333 -[2001:41d0:2:a232::]:8333 -[2001:41d0:2:ab1c::]:8333 -[2001:41d0:2:bf2a::]:8333 -[2001:41d0:2:c793::]:8333 +[2001:41d0:2:a5a9::]:8333 +[2001:41d0:2:ab38::]:8333 +[2001:41d0:2:c6e::]:8333 +[2001:41d0:2:c9bf::]:8333 [2001:41d0:302:1000::fa25]:8333 +[2001:41d0:303:188::]:8333 [2001:41d0:303:1907::]:8333 +[2001:41d0:303:2505::1a]:8333 +[2001:41d0:303:4140::]:8333 +[2001:41d0:303:d02::]:8333 +[2001:41d0:403:589::]:8333 [2001:41d0:52:d00::6e2]:8333 [2001:41d0:52:d00::6e3]:8333 +[2001:41d0:602:3b::]:8333 +[2001:41d0:602:6ca::]:8333 +[2001:41d0:602:e0::]:8333 +[2001:41d0:604:177::]:8333 +[2001:41d0:700:468::]:8333 +[2001:41d0:700:479::]:8333 +[2001:41d0:800:283::]:8333 [2001:41d0:8:1b29::]:8333 -[2001:41d0:8:3d4b::1]:8333 -[2001:41d0:8:4d4d::1]:8333 +[2001:41d0:8:2556::]:8333 [2001:41d0:8:7a38::1]:8333 +[2001:41d0:8:8007::]:8333 [2001:41d0:8:8f46::1]:8333 -[2001:41d0:8:ba87::1]:8333 -[2001:41d0:8:bd45::1]:8333 +[2001:41d0:8:9c6e::1]:8333 +[2001:41d0:8:b3ad::1]:8333 +[2001:41d0:8:b7d0::1]:8333 [2001:41d0:8:bed3::]:8333 [2001:41d0:8:c67c::]:8333 +[2001:41d0:8:d444::1]:8333 [2001:41d0:8:d844:1337::1017]:8333 +[2001:41d0:8:db78::1]:8333 [2001:41d0:8:ddb::1]:8333 [2001:41d0:8:ddf::1]:8333 -[2001:41d0:8:de3d::1]:8333 [2001:41d0:8:e3e4::1]:8333 -[2001:41d0:a:4e3f::1c7d:6b01]:8333 +[2001:41d0:a:3b5f::1]:8333 +[2001:41d0:a:405c::]:8333 [2001:41d0:a:635b::1]:8333 -[2001:41d0:a:6810::1]:8333 +[2001:41d0:a:6a0d::1]:8333 +[2001:41d0:a:6a1::1]:8333 [2001:41d0:a:6c29::1]:8333 [2001:41d0:a:6fd0::]:8333 -[2001:41d0:a:fac7::1]:8333 -[2001:41d0:d:111c::]:8333 -[2001:41d0:d:2ac8::]:8333 +[2001:41d0:a:755::1]:8333 +[2001:41d0:a:f8d2::1]:8333 +[2001:41d0:a:f915::1]:8333 +[2001:41d0:e:1146::1]:8333 [2001:41d0:e:1388::1]:8333 +[2001:41d0:e:26b::1]:8333 +[2001:41d0:e:9e7::1]:8333 +[2001:41d0:e:ec5::1]:8333 [2001:41f0:61:0:72f3:95ff:fe09:7521]:8333 [2001:41f0:61::7]:8333 -[2001:470:1f07:151c:baac:6fff:feb7:3ba9]:8333 +[2001:4642:e527::beef]:8333 +[2001:470:1d:8a9::]:8333 +[2001:470:1d:8a9::4]:8333 +[2001:470:1f06:15b4::2]:8333 +[2001:470:1f07:803:20c:29ff:fe2d:5879]:8333 +[2001:470:1f09:325::40]:8333 +[2001:470:1f0b:56e:7e5c:f8ff:fe32:5302]:8333 [2001:470:1f0b:8c4::5]:8333 +[2001:470:1f0b:8fe:c4:4338:e528:2713]:8333 [2001:470:1f0b:967::11]:8333 +[2001:470:1f10:776::2]:8333 [2001:470:1f15:11f8::10]:8333 [2001:470:1f15:1b95:2c3e:8a9a:24e1:7084]:8333 -[2001:470:1f15:f28::3]:8333 -[2001:470:1f1a:172::2]:8333 -[2001:470:1f1c:b07::2]:8333 -[2001:470:1f1d:3a9::10]:8333 +[2001:470:1f15:cf7::14]:8333 +[2001:470:1f15:e9b::3ef]:8333 +[2001:470:1f17:22a:8d2:72bf:a564:21fb]:8333 +[2001:470:1f17:b5::10]:8333 +[2001:470:1f1b:5a6:216:3eff:fe24:1162]:8333 +[2001:470:2179:dead:deaf:0:2e70:9d8b]:8333 [2001:470:25:482::2]:8333 -[2001:470:28:365::4]:8333 -[2001:470:754f:42::17a]:8333 +[2001:470:27:483::2]:8333 [2001:470:7:b74::2]:8333 -[2001:470:7dda:1::1]:8333 -[2001:470:8:c70:20c:29ff:fe6a:8fdc]:8333 -[2001:470:8:c70::54]:8333 +[2001:470:8:2e1:44ff:654e:e53e:ad59]:8333 +[2001:470:8:2e1:7058:53f6:5681:5be4]:8333 +[2001:470:8:2e1::43]:8333 +[2001:470:8:7b3::17]:8333 +[2001:470:8a2f:8000::e998]:8333 +[2001:470:a068::2]:8333 +[2001:470:a:88b::2]:8333 [2001:470:a:c13::2]:8333 +[2001:470:b3d5:1:641c:6bff:fe9d:bccf]:8333 +[2001:470:c144:cafe::9]:8333 [2001:470:d00d:0:3664:a9ff:fe9a:5150]:8333 [2001:470:dbf2:aaaa::b17:c01c]:8333 -[2001:470:f457:8000::a6]:8333 -[2001:4801:7819:74:b745:b9d5:ff10:a61a]:8333 -[2001:4801:7819:74:b745:b9d5:ff10:aaec]:8333 -[2001:4801:7828:104:be76:4eff:fe10:1325]:8333 -[2001:4ba0:cafe:13c0::1]:8333 -[2001:4ba0:cafe:418::1]:8333 -[2001:558:6045:23:1830:896c:d901:190d]:8333 -[2001:67c:1220:80c::93e5:dd2]:8333 -[2001:67c:2128:ffff:6062:36ff:fe30:6532]:8333 -[2001:8d8:923:8400::87:ebd]:8333 -[2001:981:4452:1::100]:8333 -[2001:981:46:1:ba27:ebff:fe5b:edee]:8333 -[2001:981:bdbd:1:c506:7d38:4b47:da15]:8333 +[2001:4802:7802:103:be76:4eff:fe21:19f9]:8333 +[2001:48f8:1003::3ba]:8333 +[2001:4b99:1:1:216:3eff:febd:85ba]:8333 +[2001:4ba0:babe:2681::]:8333 +[2001:4ba0:babe:832::]:8333 +[2001:4ba0:cafe:20c::1]:8333 +[2001:579:9284:bc:10be:5df1:f6d2:4194]:8333 +[2001:638:a000:4140::ff10:415]:8333 +[2001:638:a000:4140::ffff:191]:8333 +[2001:67c:2564:520:7800:4817:52ec:d8f]:8333 +[2001:708:150:10::4329]:8333 +[2001:980:231b:1:8e89:a5ff:fee3:f8be]:8333 +[2001:980:ade8:1:14fc:fd6d:608c:f669]:8333 +[2001:984:aec7:1:dcb7:29a:7eda:b9a2]:8333 [2001:985:79af:20::35]:8333 [2001:bc8:225f:10e:505:6573:7573:d0a]:8333 -[2001:bc8:323c:100::53]:8333 -[2001:bc8:323c:100::80:4]:8333 -[2001:bc8:323c:100::cafe]:8333 -[2001:bc8:3680:4242::1]:8333 +[2001:bc8:323c:100::]:8333 [2001:bc8:399f:f000::1]:8333 -[2002:1e2:5587::1e2:5587]:8333 -[2002:1e2:5588::1e2:5588]:8333 -[2002:2a33:21c4::2a33:21c4]:8333 +[2001:bc8:3cbf::5]:8333 +[2001:bc8:4400:2400::480f]:8333 +[2002:261b:642c::261b:642c]:8333 +[2002:2956:685e::2956:685e]:8333 +[2002:2d7b:674f::2d7b:674f]:8333 +[2002:2df9:5e40::2df9:5e40]:8333 [2002:2e04:784b::2e04:784b]:8333 -[2002:2ebc:2c14::16]:8333 +[2002:2f58:fe42::2f58:fe42]:8333 +[2002:2f58:fe62::2f58:fe62]:8333 +[2002:2f59:30f3::2f59:30f3]:8333 [2002:2f5a:3c1c::2f5a:3c1c]:10011 [2002:2f5a:562a::2f5a:562a]:8333 [2002:2f5b:a5f9::2f5b:a5f9]:8333 -[2002:3141:28c::3141:28c]:8333 -[2002:323f:a2f2::323f:a2f2]:8333 -[2002:323f:fbd::323f:fbd]:8333 +[2002:2f5b:b086::2f5b:b086]:8333 +[2002:323f:a61b::323f:a61b]:8333 [2002:33ff:69a0::1]:8333 -[2002:3e6a:106f::3e6a:106f]:8333 -[2002:3e70:bbc::3e70:bbc]:8333 -[2002:3e7a:6727::3e7a:6727]:8333 [2002:3f62:e6bb::3f62:e6bb]:8333 -[2002:4540:4b30::4540:4b30]:8333 -[2002:4e6b:c745::1]:8333 -[2002:5052:4d8a::5052:4d8a]:8333 +[2002:4b63:50b4:1234:4059:bf54:e088:7daa]:8333 +[2002:509:6ac5::509:6ac5]:8333 [2002:51a9:9cc9::51a9:9cc9]:8333 -[2002:54fb:cb05::1]:8333 +[2002:54fb:a1cd::1]:8333 [2002:5bc2:5428::5bc2:5428]:8333 [2002:5bce:1253::5bce:1253]:8333 -[2002:5bdb:19e8::5bdb:19e8]:8333 -[2002:5c3f:3912::5c3f:3912]:8333 +[2002:5d68:d270::5d68:d270]:8333 [2002:5dbd:91a9::5dbd:91a9]:8333 -[2002:5dbe:8cc6::5dbe:8cc6]:8333 [2002:5fd3:8944::5fd3:8944]:8333 -[2002:65c8:a018::65c8:a018]:8333 -[2002:6750:a839::6750:a839]:8333 +[2002:6738:8869::6738:8869]:8333 +[2002:67e9:fe16::67e9:fe16]:8333 +[2002:67fa:44a::67fa:44a]:8333 [2002:67fa:44b::67fa:44b]:8333 +[2002:6825:d425::6825:d425]:8333 [2002:6a0e:3ea8::6a0e:3ea8]:10011 -[2002:6a0f:2497::6a0f:2497]:8333 -[2002:6dec:5ac7::6dec:5ac7]:8333 +[2002:6bb4:475c::6bb4:475c]:41888 +[2002:6bb4:54bc::6bb4:54bc]:8333 +[2002:6c3d:d88a::6c3d:d88a]:8333 [2002:704a:d6d4::704a:d6d4]:9997 +[2002:7169:8b2a::7169:8b2a]:8333 [2002:7237:fcf6::7237:fcf6]:20188 -[2002:76b2:7f40::76b2:7f40]:8333 [2002:7819:7e80::7819:7e80]:7743 -[2002:781b:8db8::781b:8db8]:8333 -[2002:7b38:cd00::7b38:cd00]:8333 -[2002:ac52:b854::ac52:b854]:8333 +[2002:8494:8233::8494:8233]:8333 +[2002:8494:84fc::8494:84fc]:8333 +[2002:9247:4cec::9247:4cec]:8333 +[2002:9538:735d::9538:735d]:8333 +[2002:adcd:b88c::adcd:b88c]:8333 +[2002:b025:5c52::b025:5c52]:8333 +[2002:b07e:a70a::b07e:a70a]:8333 +[2002:b2c9:e6fc:10:3d5c:e3ad:813:9c46]:8333 +[2002:b4b2:3612::b4b2:3612]:8333 [2002:b610:1ca3::b610:1ca3]:8333 +[2002:b85f:26da::b85f:26da]:8333 +[2002:b923:b67b::b923:b67b]:8333 [2002:b946:694a::b946:694a]:8339 -[2002:b994:9167::b994:9167]:8333 -[2002:bc28:6b92::bc28:6b92]:8333 +[2002:b960:5e18::b960:5e18]:8333 +[2002:bc48:d606::bc48:d606]:8333 +[2002:c13a:c4d4::1]:8333 +[2002:c16a:1c08::c16a:1c08]:8333 +[2002:c16a:1d12::c16a:1d12]:8333 [2002:c23f:8fc5::c23f:8fc5]:8333 -[2002:c338:3f0a::c338:3f0a]:8333 -[2002:d1b1:5615::d1b1:5615]:8333 +[2002:c2a5:1021::c2a5:1021]:8333 +[2002:c2a5:10fe::c2a5:10fe]:8333 +[2002:c39a:a4a8::c39a:a4a8]:8333 +[2002:cb82:d02d::cb82:d02d]:8333 +[2002:d035:2734::d035:2734]:8333 [2002:d2d3:6da5::d2d3:6da5]:8333 -[2002:d917:2b1::d917:2b1]:8333 -[2002:db71:f434::db71:f434]:8333 -[2003:a:36f:4f01::1]:8333 -[2003:a:37f:ef4f:dead:babe:b00b:beef]:8333 -[2400:8901::f03c:91ff:fe2c:63d8]:8333 -[2400:8902::f03c:91ff:fed5:9d8d]:8333 -[2401:2500:203:10:153:120:156:83]:8333 -[2401:a400:3200:5600:14ee:f361:4bdc:1f7c]:8333 +[2002:d453:9174::d453:9174]:8333 +[2002:d917:d95::d917:d95]:8333 +[2003:a:1114:1001:6ab5:99ff:feb0:8770]:8333 +[2400:2650:480:bc00:bcaf:7c49:8c9e:7cdf]:8333 +[2400:8901::f03c:91ff:fe1f:ec00]:8333 +[2400:8901::f03c:91ff:fe3e:571b]:8333 +[2400:8901::f03c:91ff:fe3e:57ef]:8333 +[2400:8901::f03c:91ff:feb4:71f1]:8333 +[2400:8902::f03c:91ff:feb9:c59c]:8333 +[2400:dd01:1034:e00:f21f:afff:fedc:164d]:8333 +[2400:dd08:1001:120:f0f7:d9da:8b5b:58d7]:8333 +[2401:1800:7800:102:be76:4eff:fe1c:a7d]:8333 +[2401:1800:7801:101:be76:4eff:fe1c:f4b]:8333 [2402:1f00:8100:36::]:8333 -[2403:4200:403:2::ff]:8333 -[2405:9800:b440:947f:59a5:f379:1876:858c]:8333 +[2404:7a83:94e0:7f00:858f:8a7d:3a8c:26dd]:8333 +[2404:c805:d00:101:716a:cff7:c9ab:a595]:8333 [2405:aa00:2::40]:8333 -[2406:da14:445:5201::4]:8333 -[2406:da18:f7c:4351:1a58:81fe:6ed0:1103]:8333 -[2406:da18:f7c:4351:22aa:2585:fe88:7d58]:8333 -[2406:da18:f7c:4351:2674:33bb:25d6:cbba]:8333 -[2406:da18:f7c:4351:2e19:a8c7:a36a:bde0]:8333 -[2406:da18:f7c:4351:3cc8:43d:fbcc:5067]:8333 -[2406:da18:f7c:4351:5228:2b53:bb9a:edf5]:8333 -[2406:da18:f7c:4351:5729:102:998c:d41a]:8333 -[2406:da18:f7c:4351:591b:4881:3986:3703]:8333 -[2406:da18:f7c:4351:59b9:b50:f47f:b560]:8333 -[2406:da18:f7c:4351:61f2:cfb0:8c45:5fdd]:8333 -[2406:da18:f7c:4351:6356:68e0:73fc:ac0b]:8333 -[2406:da18:f7c:4351:660e:f6bc:3563:ba8e]:8333 -[2406:da18:f7c:4351:691:9e:f2df:227d]:8333 -[2406:da18:f7c:4351:721c:83d2:6765:4300]:8333 -[2406:da18:f7c:4351:7237:9be:4601:bc15]:8333 -[2406:da18:f7c:4351:7a3b:c203:fd11:6c7d]:8333 -[2406:da18:f7c:4351:7a74:a80e:889a:ba42]:8333 -[2406:da18:f7c:4351:7ee3:a181:f25c:fa79]:8333 -[2406:da18:f7c:4351:8a25:9084:140:4549]:8333 -[2406:da18:f7c:4351:8bc0:c6fd:ecfb:f074]:8333 -[2406:da18:f7c:4351:91ce:d0ba:1b9e:c27b]:8333 -[2406:da18:f7c:4351:9336:44e7:84b4:85b9]:8333 -[2406:da18:f7c:4351:936c:c3b9:a1d0:848]:8333 -[2406:da18:f7c:4351:93ef:1eef:65c8:766d]:8333 -[2406:da18:f7c:4351:94e0:5b27:78c2:5111]:8333 -[2406:da18:f7c:4351:9815:a202:18a3:2a36]:8333 -[2406:da18:f7c:4351:9e1b:135c:7472:9d9]:8333 -[2406:da18:f7c:4351:9f84:278:68f5:b8ea]:8333 -[2406:da18:f7c:4351:a062:493f:a6f8:ca75]:8333 -[2406:da18:f7c:4351:a192:b98:3066:8f11]:8333 -[2406:da18:f7c:4351:a1cb:2f19:4a54:38c9]:8333 -[2406:da18:f7c:4351:a4a2:4c9:c43a:98ae]:8333 -[2406:da18:f7c:4351:a7e9:cd48:fa90:46d3]:8333 -[2406:da18:f7c:4351:a88:99:6671:fce4]:8333 -[2406:da18:f7c:4351:abe1:2e48:eb97:2ab5]:8333 -[2406:da18:f7c:4351:acf5:2b21:5d2a:6b31]:8333 -[2406:da18:f7c:4351:b51f:8966:74a5:6c53]:8333 -[2406:da18:f7c:4351:b8e3:f3ca:e412:daa5]:8333 -[2406:da18:f7c:4351:ba7c:6da8:da59:b1b6]:8333 -[2406:da18:f7c:4351:be04:6f8e:8f93:c555]:8333 -[2406:da18:f7c:4351:c82d:2a0b:31a5:e28d]:8333 -[2406:da18:f7c:4351:c993:eb06:bd2c:1e65]:8333 -[2406:da18:f7c:4351:d4b9:bff8:c4d4:1e05]:8333 -[2406:da18:f7c:4351:d70d:a73d:1ddd:439e]:8333 -[2406:da18:f7c:4351:e103:f456:b296:9f29]:8333 -[2406:da18:f7c:4351:ea3b:27ec:7c2:aebc]:8333 -[2406:da18:f7c:4351:f62c:5013:379b:363e]:8333 -[240b:10:ca20:f0:224:e8ff:fe1f:60d9]:8333 -[240b:250:1e0:2400:b9ef:8fe3:a69a:7378]:8333 -[2600:1f14:34a:fe00:13f4:ceb6:a9db:4f47]:8333 -[2600:1f14:34a:fe00:2550:9366:a5d9:78a5]:8333 -[2600:1f14:34a:fe00:27d:6ed:7c8d:7bee]:8333 -[2600:1f14:34a:fe00:2ed6:8a19:4eb:36c1]:8333 -[2600:1f14:34a:fe00:34c7:2e9e:e60e:f823]:8333 -[2600:1f14:34a:fe00:38de:442:72df:6346]:8333 -[2600:1f14:34a:fe00:3a1e:878f:991a:9582]:8333 -[2600:1f14:34a:fe00:3d88:1805:54e3:f4c8]:8333 -[2600:1f14:34a:fe00:3f3e:58bd:ec82:5dac]:8333 -[2600:1f14:34a:fe00:449a:9515:8436:f407]:8333 -[2600:1f14:34a:fe00:4f84:277f:e64d:1f06]:8333 -[2600:1f14:34a:fe00:5229:de84:8226:7257]:8333 -[2600:1f14:34a:fe00:5743:42c3:951b:e97a]:8333 -[2600:1f14:34a:fe00:5a29:85b:86b5:fa0e]:8333 -[2600:1f14:34a:fe00:5de8:81e:6d79:330b]:8333 -[2600:1f14:34a:fe00:5fca:ad1e:5b9c:5265]:8333 -[2600:1f14:34a:fe00:68c4:ca1b:813e:1bce]:8333 -[2600:1f14:34a:fe00:6:de9e:7b5e:a558]:8333 -[2600:1f14:34a:fe00:6c72:1fcd:433:dc97]:8333 -[2600:1f14:34a:fe00:77ee:629f:bc13:fb4f]:8333 -[2600:1f14:34a:fe00:79d0:85d6:516f:3293]:8333 -[2600:1f14:34a:fe00:81:422f:9ef3:4579]:8333 -[2600:1f14:34a:fe00:822b:5f05:ec8d:48c6]:8333 -[2600:1f14:34a:fe00:82a:76a2:fdc9:845e]:8333 -[2600:1f14:34a:fe00:83ca:cef6:e04c:50c0]:8333 -[2600:1f14:34a:fe00:8ba2:a36c:8687:d5aa]:8333 -[2600:1f14:34a:fe00:8c80:5c67:3b47:90b3]:8333 -[2600:1f14:34a:fe00:8eb8:f47f:6d53:e3ae]:8333 -[2600:1f14:34a:fe00:989c:f8f8:a922:1b9a]:8333 -[2600:1f14:34a:fe00:98c9:1eb3:ea12:a8f0]:8333 -[2600:1f14:34a:fe00:9ee5:a8f6:6b2a:866e]:8333 -[2600:1f14:34a:fe00:a46b:7bd5:629f:f75c]:8333 -[2600:1f14:34a:fe00:a627:8299:8784:d439]:8333 -[2600:1f14:34a:fe00:ad0b:955e:b4e5:d97d]:8333 -[2600:1f14:34a:fe00:ae82:7117:9d69:7c86]:8333 -[2600:1f14:34a:fe00:ccee:365a:43f8:b871]:8333 -[2600:1f14:34a:fe00:d5ee:a3e2:2f85:e593]:8333 -[2600:1f14:34a:fe00:d5f0:1fe0:6bd5:18a8]:8333 -[2600:1f14:34a:fe00:e4a7:5aba:af87:4cdb]:8333 -[2600:1f14:34a:fe00:e8e5:2d0:fb6f:2f5]:8333 -[2600:1f14:34a:fe00:e9ef:4690:a5ac:92be]:8333 -[2600:1f14:34a:fe00:efba:2260:6997:fcf7]:8333 -[2600:1f14:34a:fe00:f107:2d08:c67:e5dd]:8333 -[2600:1f14:34a:fe00:f1b9:88fb:f3db:a86e]:8333 -[2600:1f14:34a:fe00:f79c:17b7:6f75:95b7]:8333 +[2409:10:ca20:1df0:224:e8ff:fe1f:60d9]:8333 [2600:1f14:6ae:d900:6550:3fc5:e074:a72c]:8333 -[2600:1f16:625:e00:1243:38b3:caa:d62e]:8333 -[2600:1f16:625:e00:166d:a956:1041:f97d]:8333 -[2600:1f16:625:e00:35f2:2428:fc57:d638]:8333 -[2600:1f16:625:e00:3c75:333e:b7f:8cc0]:8333 -[2600:1f16:625:e00:3fbf:31f:1b57:8b18]:8333 -[2600:1f16:625:e00:5617:7575:379:a8cc]:8333 -[2600:1f16:625:e00:58fa:fce6:30:a5dc]:8333 -[2600:1f16:625:e00:5e74:70dc:af78:6b77]:8333 -[2600:1f16:625:e00:7036:f651:2ee:39cd]:8333 -[2600:1f16:625:e00:7fc:9004:e7be:ffe2]:8333 -[2600:1f16:625:e00:814a:23f6:e996:5e64]:8333 -[2600:1f16:625:e00:822c:a88b:f9c:57e3]:8333 -[2600:1f16:625:e00:8314:b91e:a7ba:702]:8333 -[2600:1f16:625:e00:88bb:ee9a:10de:12]:8333 -[2600:1f16:625:e00:8c30:56f5:a29a:91de]:8333 -[2600:1f16:625:e00:8fdf:6517:7718:8c42]:8333 -[2600:1f16:625:e00:91fd:78b1:62a3:193]:8333 -[2600:1f16:625:e00:930d:93ed:76a6:3285]:8333 -[2600:1f16:625:e00:93c2:615f:a79a:c11f]:8333 -[2600:1f16:625:e00:a780:8bc8:a1f6:d417]:8333 -[2600:1f16:625:e00:a951:e663:4046:8c3a]:8333 -[2600:1f16:625:e00:ab19:5fe3:f155:1371]:8333 -[2600:1f16:625:e00:aefd:9cc7:d3:6e86]:8333 -[2600:1f16:625:e00:b031:e86e:8604:324a]:8333 -[2600:1f16:625:e00:b6e:4399:9dc2:6b45]:8333 -[2600:1f16:625:e00:b7c7:58c6:21a1:fd41]:8333 -[2600:1f16:625:e00:c169:6282:178c:27d6]:8333 -[2600:1f16:625:e00:c94e:58b:bd35:d815]:8333 -[2600:1f16:625:e00:caa5:7369:73a4:5711]:8333 -[2600:1f16:625:e00:cd15:b9f2:6e3e:6fd1]:8333 -[2600:1f16:625:e00:d6f3:775:66b7:3e92]:8333 -[2600:1f16:625:e00:dbec:f7d9:e15:f8e0]:8333 -[2600:1f16:625:e00:dbf4:4d41:594e:bc20]:8333 -[2600:1f16:625:e00:e11b:4589:a0c3:9cc7]:8333 -[2600:1f16:625:e00:ed68:15b0:3a97:be0c]:8333 -[2600:1f16:625:e00:eef3:bce0:84ee:a98b]:8333 -[2600:1f16:625:e00:ef3a:f66e:f059:d03f]:8333 -[2600:1f16:625:e00:f67c:d398:5b6:d34f]:8333 -[2600:1f16:625:e00:fe35:5099:3a8e:d123]:8333 -[2600:1f18:64d9:1603:6f6f:eef9:b595:1958]:8333 -[2600:3c00::f03c:91ff:fe84:d650]:8333 -[2600:3c00::f03c:91ff:fe89:7438]:8333 +[2600:1f14:6d0:2e03:640e:1937:9960:32e9]:8333 +[2600:1f14:6d0:2e03:761:6e21:952c:de5b]:8333 +[2600:1f16:625:e00:269a:3452:2edf:1011]:8333 +[2600:1f16:625:e00:7bc:5879:4463:15dd]:8333 +[2600:1f16:625:e00:a28b:5a16:849c:fe41]:8333 +[2600:1f16:625:e00:a70f:e728:e8e1:2c2e]:8333 +[2600:1f16:b32:3102:440:fab:d8a2:cc59]:8333 +[2600:1f18:3d:4600:699a:d6b3:76e8:9b8d]:48333 +[2600:1f18:3f8:f90f:2b39:201b:e9a4:e882]:8333 +[2600:1f18:609f:da02:b283:b16e:aac4:749f]:8333 +[2600:3c00::f03c:91ff:fe28:9e61]:8333 [2600:3c00::f03c:91ff:fe91:3e49]:8333 -[2600:3c00::f03c:91ff:febb:981e]:8333 -[2600:3c01::f03c:91ff:fe69:89e9]:8333 +[2600:3c00::f03c:91ff:feb9:36fc]:8333 +[2600:3c01::f03c:91ff:fe39:768b]:8333 +[2600:3c01::f03c:91ff:fe8e:8ae1]:8333 [2600:3c01::f03c:91ff:fe91:6a29]:8333 +[2600:3c01::f03c:91ff:fea7:e0f9]:8333 +[2600:3c02::f03c:91ff:fe8e:bcd9]:8333 [2600:3c03::f03c:91ff:fe28:1445]:8333 +[2600:3c03::f03c:91ff:fe7a:1eb2]:8333 +[2600:3c03::f03c:91ff:feb0:5fc4]:8333 [2600:3c03::f03c:91ff:fee0:233e]:8333 -[2600:6c55:7200:24d:cf4:811c:7cb3:f7a7]:8333 -[2600:8805:2400:14e:226:4aff:fe02:2ba4]:8333 -[2601:18d:4600:3cc2:20e7:b3ff:fecf:a99]:8333 -[2601:1c2:1702:5241:47d:4016:ec42:6705]:8333 -[2601:441:4101:70cd:4e3:8e81:3250:1f0b]:8333 -[2601:602:9980:f78:211:11ff:fec5:1ae]:8333 -[2601:646:4103:179f:5809:1bff:fe55:6678]:8333 -[2602:4c:323:b101:35a3:9de8:6984:ef56]:8333 -[2602:ff62:104:ac1:8000::]:8333 -[2602:ffc5:40::1:711e]:8333 -[2602:ffc5::c30:1c75]:8333 -[2604:a880:2:d0::17e9:2001]:8333 +[2600:6c40:7900:319f:8390:e8af:5a2c:9b0b]:8333 +[2600:6c44:467f:f89c:722d:8424:d481:d155]:8333 +[2600:8801:8306:e900:dce8:6a03:9592:a053]:8333 +[2601:186:c100:6bcd:16bd:cea1:235d:1c19]:8333 +[2601:18d:4600:5f32:20e7:b3ff:fecf:a99]:8333 +[2601:1c2:f00:29b0:922b:34ff:fea8:4118]:8333 +[2601:282:8000:20b0:67f8:fa63:e056:dd23]:8333 +[2601:40a:c200:37e8:9528:d453:6358:9f2a]:8333 +[2601:646:4101:1603:5809:1bff:fe55:6678]:8333 +[2601:c0:c100:1880:21f:5bff:fe3c:6e84]:8333 +[2601:c8:4100:770:23e:e1ff:febe:736d]:8333 +[2603:3000:903:c5f1:468a:5bff:fe9e:89dc]:8333 +[2603:3005:3000:5000:bc5a:72ac:36e9:175e]:8333 +[2603:3022:501:7800:495c:728c:ed5d:5d75]:8333 +[2604:180:1:346::684d]:8333 +[2604:67c0:2001::2]:8333 +[2604:8d80:100:0:8065:4c57:667a:b70f]:8333 +[2604:8d80:100::adf3:4031]:8333 [2604:a880:2:d0::22f8:f001]:8333 [2604:a880:2:d0::22f9:1]:8333 +[2604:a880:2:d0::22f9:1001]:8333 [2604:a880:2:d0::22f9:c001]:8333 [2604:a880:2:d0::22f9:d001]:8333 [2604:a880:2:d0::22f9:e001]:8333 +[2604:a880:2:d0::22fa:1001]:8333 [2604:a880:2:d0::22fa:2001]:8333 [2604:a880:2:d0::22fa:3001]:8333 -[2604:a880:400:d0::1684:5001]:8333 +[2604:a880:2:d0::301:8001]:8333 +[2604:a880:2:d0::38:f001]:8333 +[2604:a880:2:d0::46:f001]:8333 +[2604:a880:2:d0::b2:9001]:8333 [2604:a880:400:d0::1ac4:b001]:8333 [2604:a880:400:d0::2004:4001]:8333 [2604:a880:400:d0::2004:5001]:8333 @@ -1006,445 +1090,436 @@ [2604:a880:400:d0::2004:e001]:8333 [2604:a880:400:d0::2004:f001]:8333 [2604:a880:400:d0::2005:1]:8333 +[2604:a880:400:d0::2005:2001]:8333 [2604:a880:400:d0::2005:3001]:8333 [2604:a880:400:d0::261f:6001]:8333 -[2604:a880:400:d0::28b8:5001]:8333 -[2604:a880:400:d0::ad7:e001]:8333 [2605:4d00::50]:8333 -[2605:5d80:2002::245]:8333 -[2605:9880:0:953:225:90ff:fed2:c0b4]:8333 -[2606:c380::215:17ff:feb3:3ec]:8333 -[2607:1c00:a:6:3c1c:1b0d:ba4:8ea9]:8333 -[2607:1c00:a:6::1000]:8333 -[2607:4480:2:2000:250:56ff:fe86:6449]:8333 -[2607:5300:120:671::]:8333 -[2607:5300:120:962::]:8333 +[2605:6000:e8c8:6701:7562:de11:245c:f6ba]:8333 +[2605:9880:0:3::8333]:8333 +[2605:9880:201:17::4b7c]:8333 +[2605:9880:201:6:ec4:7aff:fe6c:a660]:8333 +[2605:a000:f343:b700:5054:ff:fea7:131]:8333 +[2605:ae00:203::203]:8333 +[2605:c000:2a0a:1::102]:8333 +[2605:f700:80:800::3724:81c]:8333 +[2605:f700:80:800::38c1:2b84]:8333 +[2606:df00:7:4:4caa:2c79:b619:27c9]:8333 +[2607:4480:2:1:38:102:69:70]:8333 +[2607:5300:120:b7e::]:8333 [2607:5300:201:2000::1:556]:8333 -[2607:5300:203:118:3733::1414]:8333 +[2607:5300:203:1245::]:8333 +[2607:5300:203:14e7::20f]:8333 +[2607:5300:203:190a::]:8333 +[2607:5300:203:a3::]:8333 [2607:5300:60:10aa::1]:8333 -[2607:5300:60:1e83::]:8333 -[2607:5300:60:1e83::1000]:8333 -[2607:5300:60:1e83::2000]:8333 -[2607:5300:60:2d0::1]:8333 +[2607:5300:60:13bb::1]:8333 +[2607:5300:60:1ba8::1]:8333 +[2607:5300:60:2218::]:8333 +[2607:5300:60:26f::1]:8333 +[2607:5300:60:2827::]:8333 +[2607:5300:60:2c16::]:8333 [2607:5300:60:3ddf::]:8333 -[2607:5300:60:3f3c::]:8333 -[2607:5300:60:5428::]:8333 +[2607:5300:60:9ad::1]:8333 [2607:5300:60:ac0::1]:8333 -[2607:5300:61:f4b::1]:8333 -[2607:9000:0:1:5054:ff:fe5d:264e]:8333 +[2607:5300:61:c50::]:8333 +[2607:5300:61:f5b::]:8333 +[2607:9000:0:6:1:0:36b:5a5]:8333 +[2607:f178:0:8::106]:8333 +[2607:f1c0:823:af00::35:bbd1]:8333 [2607:f1c0:846:9a00::87:d00e]:8333 [2607:f2d8:4005:d:a8a2:eeff:fee0:a859]:8333 -[2607:f948:0:1::1:40]:8333 -[2607:fa18:3a01::50]:8333 -[2607:fea8:3ca0:926::2]:8333 -[2607:fea8:4da0:3b0::2]:8333 -[2607:ff10:c5:502:225:90ff:fe32:d446]:8333 -[2607:ff28:9005:1::2567:57e0]:8333 -[2620:71:4000:0:192:30:120:110]:8333 -[2620:b8:4000:1000::93:1]:8333 -[2800:1a0::9]:8333 -[2801:84:0:1034:76d4:35ff:fe7f:5033]:8333 +[2607:f470:14:a:21d:7dff:fe01:bcee]:8333 +[2607:fa18:0:beef::c012]:8333 +[2607:fd70:4a:babe:b00b:1e5:0:1]:8333 +[2607:fea8:e2df:f87e:4b8e:8a8c:8167:ec0d]:8333 +[2607:fea8:e60:574:fdbc:add5:eabd:4d9e]:8333 +[2610:1a0:103:4a:dead:beaf:0:cafe]:8333 +[2610:1a0:103:4a:dead:beef:1:cafe]:8333 +[2801:80:930::63]:8333 +[2803:1500:1200:c487::1]:8333 [2a00:16d8:c::5b6a:c261]:8333 -[2a00:1768:2001:24::148:218]:8333 -[2a00:19e0:1:1:225:90ff:fea5:fc0]:8333 [2a00:1a48:7810:101:be76:4eff:fe08:c774]:8333 -[2a00:6340:2004:0:5054:ff:fe54:38c]:8333 -[2a00:7b80:477:21::1c8c:83a6]:8333 -[2a00:7c80:0:71::8]:8333 +[2a00:1c48:6:108:a6bf:1ff:fe16:35c1]:8333 +[2a00:1c60:0:12:e2d5:5eff:fe09:257d]:8333 +[2a00:1ca8:37::65e9:f438]:8333 +[2a00:4802:360::ff9]:8333 [2a00:7c80:0:97::7]:8333 -[2a01:238:4363:4900:d85e:c1d9:2b32:61d0]:8333 -[2a01:488:66:1000:53a9:22b:0:1]:8333 -[2a01:488:67:1000:5bfa:5526:0:1]:8333 -[2a01:488:67:1000:b01c:3379:0:1]:8333 +[2a00:8a60:e012:a00::21]:8333 +[2a00:bbe0:0:42:222:64ff:fe9a:e206]:8333 +[2a00:bbe0:cc:0:6651:6ff:fe0e:9418]:8333 +[2a00:c440:10:1c62:1234::1]:8333 +[2a00:c440:40:33b:9d1c:7726:5571:c862]:8333 +[2a00:c70:1:213:246:56:95:1]:8333 +[2a00:ee2:1200:1900:20c:29ff:fe81:a0a3]:8333 +[2a00:f940:2:1:2::1086]:8333 +[2a00:f940:2:1:2::184b]:8333 +[2a01:238:4343:7700:3e6:f65c:5e57:511c]:8333 +[2a01:238:43a6:6500:5e5c:24bb:5e39:d96f]:8333 +[2a01:4240:a21:983b::c0a8:32]:8333 +[2a01:488:66:1000:2ea3:7633:0:1]:8333 [2a01:4d60:3:1:5::1]:8333 +[2a01:4f8:10a:10a8::2]:8333 [2a01:4f8:10a:1d8f::2]:8333 -[2a01:4f8:10a:1e81::2]:8333 -[2a01:4f8:10a:2261::2]:8833 [2a01:4f8:10a:239c::2]:9002 -[2a01:4f8:10a:294a::2]:8333 +[2a01:4f8:10a:2ae0::2]:8333 [2a01:4f8:10a:31d3::2]:8333 -[2a01:4f8:10a:3fe6::2]:8333 -[2a01:4f8:10a:b2e::2]:8333 -[2a01:4f8:10b:12d7::2]:8333 +[2a01:4f8:10a:3718::2]:8333 +[2a01:4f8:10a:3fe4::2]:8333 +[2a01:4f8:10a:41c1::2]:8333 +[2a01:4f8:10b:18c2::2]:8333 +[2a01:4f8:10b:2a9b::2]:8333 +[2a01:4f8:10b:2e18::2]:8333 +[2a01:4f8:10b:2e19::2]:8333 +[2a01:4f8:10b:2e8c::3]:8333 [2a01:4f8:10b:d50::2]:8333 [2a01:4f8:10b:e2d::2]:8333 [2a01:4f8:10b:ee1::2]:8333 -[2a01:4f8:110:5107::2]:8333 -[2a01:4f8:110:5292::2]:8333 -[2a01:4f8:110:536e::2]:8333 -[2a01:4f8:120:43e4::2]:8333 -[2a01:4f8:130:3332::2]:8333 -[2a01:4f8:130:430b::2]:8333 +[2a01:4f8:10b:f04::2]:8333 +[2a01:4f8:10b:f44::2]:8333 +[2a01:4f8:110:411f::2]:8333 +[2a01:4f8:120:1391::2]:8333 +[2a01:4f8:120:62e6::2]:8333 +[2a01:4f8:120:702e::2]:8333 [2a01:4f8:130:618e::2]:8333 [2a01:4f8:130:71d2::2]:8333 [2a01:4f8:130:7422::2]:8333 -[2a01:4f8:131:33ad::2]:8333 -[2a01:4f8:131:33ad:fea1::666]:8333 -[2a01:4f8:131:3428::2]:8333 -[2a01:4f8:140:1326::2]:8333 +[2a01:4f8:13b:271c::2]:8333 +[2a01:4f8:13b:3810::2]:8333 +[2a01:4f8:140:2123::2]:8333 +[2a01:4f8:140:3144::2]:8333 +[2a01:4f8:140:4201::2]:8333 [2a01:4f8:140:524a::2]:8333 -[2a01:4f8:140:6055::2]:8333 -[2a01:4f8:140:7410::2]:8333 +[2a01:4f8:140:5329::102]:8333 +[2a01:4f8:140:624c::2]:8333 +[2a01:4f8:140:7173::2]:8333 +[2a01:4f8:140:82b6::2]:8333 +[2a01:4f8:140:9082::2]:8333 [2a01:4f8:140:931a::2]:8333 -[2a01:4f8:141:2254::2]:8333 +[2a01:4f8:141:13b1::2]:8333 [2a01:4f8:141:22ae::2]:8333 -[2a01:4f8:150:11d4::2]:8333 -[2a01:4f8:150:70a4::2]:8333 -[2a01:4f8:150:726b::2]:8333 +[2a01:4f8:141:2426::2]:8333 +[2a01:4f8:141:5491::2]:8333 +[2a01:4f8:150:32f2::2]:8333 +[2a01:4f8:150:4107::2]:5001 +[2a01:4f8:150:4226::2]:8333 +[2a01:4f8:150:5327::2]:8333 +[2a01:4f8:150:53a4::2]:8333 +[2a01:4f8:150:53a4::4]:8333 +[2a01:4f8:150:728f::2]:8333 [2a01:4f8:150:72ee::4202]:8333 -[2a01:4f8:150:90ca::2]:8333 -[2a01:4f8:151:30c9::2]:8333 -[2a01:4f8:151:334d::3]:8333 -[2a01:4f8:151:7175::2]:8333 +[2a01:4f8:150:7331::2]:8333 +[2a01:4f8:151:82d2::2]:8333 +[2a01:4f8:160:3324::2]:8333 [2a01:4f8:160:41f0::1:33]:8333 +[2a01:4f8:160:542e::2]:8333 [2a01:4f8:160:636e::2]:8333 -[2a01:4f8:161:7026::2]:8333 +[2a01:4f8:160:74b2::2]:8333 +[2a01:4f8:161:2148::2]:8333 +[2a01:4f8:161:22e7::2]:8333 +[2a01:4f8:161:6091::2]:8333 +[2a01:4f8:161:610c::2]:8333 +[2a01:4f8:161:9::2]:8333 +[2a01:4f8:162:128d::2]:8333 +[2a01:4f8:162:14ee::2]:8333 [2a01:4f8:162:2108::2]:8333 -[2a01:4f8:162:3121::50]:8333 +[2a01:4f8:162:33ac::2]:8333 +[2a01:4f8:162:3462::2]:8333 +[2a01:4f8:162:4110::2]:8333 [2a01:4f8:162:424c::2]:8333 -[2a01:4f8:171:1c1b::2]:8333 [2a01:4f8:171:1c3::2]:8333 -[2a01:4f8:171:2258::2]:8333 -[2a01:4f8:171:27d6::2]:8333 -[2a01:4f8:171:2f28::2]:8333 -[2a01:4f8:171:d23::2]:8333 -[2a01:4f8:172:10da::2]:8333 -[2a01:4f8:172:504::2]:8333 +[2a01:4f8:171:3248::2]:8333 +[2a01:4f8:171:d4a::2]:8333 +[2a01:4f8:172:1568::2]:8333 +[2a01:4f8:172:1823::2]:8333 +[2a01:4f8:172:29ef::2]:8333 [2a01:4f8:173:1622::2]:8333 -[2a01:4f8:173:42::2]:8333 +[2a01:4f8:173:1c9c::2]:8333 +[2a01:4f8:173:294f::2]:8333 +[2a01:4f8:173:2d9c::2]:8333 [2a01:4f8:190:24eb::2]:8333 [2a01:4f8:190:528d::2]:8333 -[2a01:4f8:190:61f3::2]:8333 -[2a01:4f8:191:418f::2]:3333 -[2a01:4f8:191:63b4:5000::1]:8333 +[2a01:4f8:191:22ee::2]:8333 +[2a01:4f8:191:3068::2]:8333 +[2a01:4f8:191:40ef::2]:8333 +[2a01:4f8:191:60a5::2]:8333 [2a01:4f8:191:81b7::2]:8333 -[2a01:4f8:191:8328::3]:8333 +[2a01:4f8:192:1b2::2]:8333 +[2a01:4f8:192:34d0::2]:8333 [2a01:4f8:192:4a5::2]:8333 -[2a01:4f8:192:5230::2]:8333 +[2a01:4f8:192:628a::83]:8333 [2a01:4f8:200:1012::2]:8333 +[2a01:4f8:200:24bb::2]:8333 [2a01:4f8:200:32a6::2]:8333 -[2a01:4f8:200:414e::2]:8333 -[2a01:4f8:200:416a::2]:8333 +[2a01:4f8:200:442d::2]:8333 +[2a01:4f8:200:6346::2]:8333 +[2a01:4f8:200:7222::2]:8333 [2a01:4f8:200:90c3::2]:8333 -[2a01:4f8:201:148d::2]:8333 -[2a01:4f8:201:2cc::2]:8333 -[2a01:4f8:201:3e3::2]:8333 -[2a01:4f8:201:53cc::2]:8333 -[2a01:4f8:201:6011::4]:8333 +[2a01:4f8:201:4017::11]:8333 +[2a01:4f8:201:6016::2]:8333 [2a01:4f8:202:3030::2]:8333 -[2a01:4f8:202:31e3::2]:8333 [2a01:4f8:202:32c6::2]:8333 -[2a01:4f8:202:6035::2]:8333 +[2a01:4f8:202:53c3::2]:8333 +[2a01:4f8:202:7227::2]:8333 [2a01:4f8:210:5488::2]:8333 +[2a01:4f8:211:13cf::2]:8333 +[2a01:4f8:211:1643::2]:8333 +[2a01:4f8:211:17c6::2]:8333 [2a01:4f8:211:1e17::2]:8333 -[2a01:4f8:211:1ec5::2]:8333 -[2a01:4f8:212:1826::2]:8333 +[2a01:4f8:211:d99::133]:8333 +[2a01:4f8:211:f08::2]:8333 +[2a01:4f8:212:1e16::2]:8333 +[2a01:4f8:212:311::2]:8333 +[2a01:4f8:221:1384::2311]:8333 +[2a01:4f8:221:3c82:fea1::666]:8333 +[2a01:4f8:221:801::2]:8333 [2a01:4f8:221:f59::2]:8333 -[2a01:4f8:c0c:1026::2]:8333 -[2a01:4f8:c0c:1028::2]:8333 -[2a01:4f8:c0c:1029::2]:8333 -[2a01:4f8:c0c:105f::2]:8333 -[2a01:4f8:c0c:1064::2]:8333 -[2a01:4f8:c0c:106b::2]:8333 -[2a01:4f8:c0c:106d::2]:8333 -[2a01:4f8:c0c:1070::2]:8333 -[2a01:4f8:c0c:1105::2]:8333 -[2a01:4f8:c0c:1106::2]:8333 -[2a01:4f8:c0c:1134::2]:8333 -[2a01:4f8:c0c:1135::2]:8333 -[2a01:4f8:c0c:113c::2]:8333 -[2a01:4f8:c0c:115c::2]:8333 -[2a01:4f8:c0c:115e::2]:8333 -[2a01:4f8:c0c:1170::2]:8333 -[2a01:4f8:c0c:1172::2]:8333 -[2a01:4f8:c0c:117b::2]:8333 -[2a01:4f8:c0c:117c::2]:8333 -[2a01:4f8:c0c:1180::2]:8333 -[2a01:4f8:c0c:1181::2]:8333 -[2a01:4f8:c0c:1185::2]:8333 -[2a01:4f8:c0c:1186::2]:8333 -[2a01:4f8:c0c:1187::2]:8333 -[2a01:4f8:c0c:1188::2]:8333 -[2a01:4f8:c0c:1189::2]:8333 -[2a01:4f8:c0c:121::2]:8333 -[2a01:4f8:c0c:122::2]:8333 -[2a01:4f8:c0c:15a8::2]:8333 -[2a01:4f8:c0c:1da4::2]:8333 +[2a01:4f8:a0:108c::2]:8333 +[2a01:4f8:a0:2232::2]:8333 +[2a01:4f8:a0:4366::2]:8333 +[2a01:4f8:a0:6147::2]:8333 +[2a01:4f8:a0:746a:101:1:1:2]:8333 +[2a01:4f8:a0:828a::2]:8333 +[2a01:4f8:a0:9163::2]:8333 +[2a01:4f8:b10:5009::2]:8333 +[2a01:4f8:c0c:10dc::2]:8333 [2a01:4f8:c0c:1ff7::2]:8333 [2a01:4f8:c0c:2262::2]:8333 -[2a01:4f8:c0c:73d::2]:8333 -[2a01:4f8:c0c:790::2]:8333 -[2a01:4f8:c0c:7a8::2]:8333 -[2a01:4f8:c0c:7a9::2]:8333 -[2a01:4f8:c0c:7e9::2]:8333 -[2a01:4f8:c0c:816::2]:8333 -[2a01:4f8:c0c:817::2]:8333 -[2a01:4f8:c0c:818::2]:8333 -[2a01:4f8:c0c:820::2]:8333 -[2a01:4f8:c0c:821::2]:8333 -[2a01:4f8:c0c:822::2]:8333 -[2a01:4f8:c0c:896::2]:8333 -[2a01:4f8:c0c:8c6::2]:8333 -[2a01:4f8:c0c:8c9::2]:8333 -[2a01:4f8:c0c:8d1::2]:8333 -[2a01:4f8:c0c:8d2::2]:8333 -[2a01:4f8:c0c:8d9::2]:8333 -[2a01:4f8:c0c:8da::2]:8333 -[2a01:4f8:c0c:8dc::2]:8333 -[2a01:4f8:c0c:8f1::2]:8333 -[2a01:4f8:c0c:91e::2]:8333 -[2a01:4f8:c0c:927::2]:8333 -[2a01:4f8:c0c:939::2]:8333 -[2a01:4f8:c0c:944::2]:8333 -[2a01:4f8:c0c:951::2]:8333 -[2a01:4f8:c0c:967::2]:8333 -[2a01:4f8:c0c:96f::2]:8333 -[2a01:4f8:c0c:97d::2]:8333 -[2a01:4f8:c0c:982::2]:8333 -[2a01:4f8:c0c:9fc::2]:8333 -[2a01:4f8:c0c:b35::2]:8333 -[2a01:4f8:c0c:b4c::2]:8333 -[2a01:4f8:c0c:bfe::2]:8333 -[2a01:4f8:c0c:c08::2]:8333 -[2a01:4f8:c0c:c13::2]:8333 -[2a01:4f8:c0c:c14::2]:8333 -[2a01:4f8:c0c:c16::2]:8333 -[2a01:4f8:c0c:c19::2]:8333 -[2a01:4f8:c0c:c32::2]:8333 -[2a01:4f8:c0c:c36::2]:8333 -[2a01:4f8:c0c:c39::2]:8333 -[2a01:4f8:c0c:c58::2]:8333 -[2a01:4f8:c0c:c5e::2]:8333 -[2a01:4f8:c0c:c70::2]:8333 -[2a01:4f8:c0c:c72::2]:8333 -[2a01:4f8:c0c:c79::2]:8333 -[2a01:4f8:c0c:cb1::2]:8333 -[2a01:4f8:c0c:cf5::2]:8333 -[2a01:4f8:c0c:cff::2]:8333 -[2a01:4f8:c0c:d0e::2]:8333 -[2a01:4f8:c0c:d1b::2]:8333 -[2a01:4f8:c0c:d67::2]:8333 -[2a01:4f8:c0c:d68::2]:8333 -[2a01:4f8:c0c:d81::2]:8333 -[2a01:4f8:c0c:e2d::2]:8333 -[2a01:4f8:c0c:e30::2]:8333 -[2a01:4f8:c0c:e4f::2]:8333 -[2a01:4f8:c0c:e5b::2]:8333 -[2a01:4f8:c0c:e88::2]:8333 -[2a01:4f8:c0c:f69::2]:8333 -[2a01:4f8:c0c:f76::2]:8333 -[2a01:4f8:c0c:f77::2]:8333 -[2a01:4f8:c0c:f78::2]:8333 -[2a01:4f8:c0c:f89::2]:8333 -[2a01:4f8:c0c:f8a::2]:8333 -[2a01:4f8:c0c:fd6::2]:8333 -[2a01:4f8:c0c:fea::2]:8333 +[2a01:4f8:c0c:354c::2]:8333 +[2a01:4f8:c0c:4242::2]:8333 +[2a01:4f8:c0c:4816::2]:8333 +[2a01:4f8:c0c:dcc::2]:8333 [2a01:4f8:c17:24ee::2]:8333 -[2a01:4f8:c17:2c16::2]:8333 [2a01:4f8:c17:330f::2]:8333 -[2a01:4f8:c17:34f0::2]:8333 -[2a01:4f8:c17:3986::2]:8333 [2a01:4f8:c17:3b02::2]:8333 -[2a01:4f8:c17:3d85::2]:8333 -[2a01:4f8:c17:4271::2]:8333 [2a01:4f8:c17:5dc0::2]:8333 -[2a01:4f8:c17:63a0::2]:8333 [2a01:4f8:c17:67f8::2]:8333 [2a01:4f8:c17:710b::2]:8333 +[2a01:4f8:c17:714::2]:8333 [2a01:4f8:c17:e00::2]:8333 +[2a01:5c0:10:6eb1:89b8:bb58:25a:6050]:8333 [2a01:680:10:10::1]:8333 [2a01:6f0:ffff:120::8dcb]:8333 -[2a01:79d:b7dd:ffb4:5d86:70b8:fc7f:f253]:8333 [2a01:7a0:2:1374::4]:8333 [2a01:7a0:2:1374::5]:8333 -[2a01:7a0:2:137c::3]:8333 +[2a01:7a0:2:1374::7]:8333 +[2a01:7a7:2:1218:ec4:7aff:fe83:83c4]:8333 +[2a01:7a7:2:1288:ea39:35ff:fef0:c429]:8333 +[2a01:7a7:2:155c:346c:8f5:719f:a6b6]:8333 +[2a01:7a7:2:1565:9484:509b:2a3b:a773]:8333 [2a01:7c8:aaaa:373:5054:ff:feb3:2947]:8333 -[2a01:7c8:aaaa:3a0:5054:ff:fe8c:974c]:8333 -[2a01:7c8:aab0:4b7:910d:625e:a13e:c342]:8333 [2a01:7c8:aab5:3e6:5054:ff:fed7:4e54]:8333 -[2a01:7c8:aab5:41e:5054:ff:fe38:f4fb]:8333 [2a01:7c8:aaba:343::8333]:8333 -[2a01:7c8:aabc:18c:5054:ff:fefd:3b49]:8333 [2a01:7c8:aabd:3d5:5054:ff:fe95:f586]:8333 -[2a01:7e00::f03c:91ff:fe50:94b8]:8333 -[2a01:8e01:b943:3a63:d250:99ff:fe1f:4fb2]:8333 -[2a01:b2e0:2::40]:8333 +[2a01:7c8:aac1:453:c50:fa3a:229:8504]:8333 +[2a01:7c8:aac7:5e:5054:ff:fee9:bdf7]:8333 +[2a01:be00:10:201:0:80:cece:1]:8333 +[2a01:cb00:2ca:b700:2079:b33f:cf5a:5958]:8333 +[2a01:cb00:b3:d300:90fd:e3b1:28de:116c]:8333 +[2a01:cb14:b8:a500:dd9d:80f5:d305:68f9]:8333 [2a01:d0:0:1c::245]:8333 -[2a01:d0:8fc3::2]:8333 -[2a01:e34:ec29:e8d0:25c7:c1ce:b7a3:d238]:8333 -[2a01:e34:ec4a:c2d0:1cf3:40d2:a79f:3901]:8333 -[2a01:e34:eed7:6670:ec1b:bf7c:b012:6069]:8333 +[2a01:e0a:d:6ea0:56:deab:1b2f:300b]:8333 +[2a01:e34:ecfd:1910:58fb:c2ff:feac:571f]:8333 +[2a01:e34:eed7:6670:e150:6bb0:f11b:d6d8]:8333 [2a01:e35:2433:e320:9c8e:6ff0:990f:f06e]:8333 [2a01:e35:2ee5:610:21f:d0ff:fe4e:7460]:8333 -[2a02:1205:5051:a640:d6ae:52ff:fea3:ac]:8333 +[2a01:e35:8be7:53d0:b8d5:de58:95b5:dd16]:8333 +[2a01:e35:8bff:70b0:1e1b:dff:fe0b:236d]:8333 +[2a02:1205:34c3:bae0:baae:edff:feea:9445]:8333 +[2a02:1205:5004:de00:c84:4a1:e760:cf90]:8333 +[2a02:1205:5076:ee00:d6c9:efff:fe65:fbfb]:8333 +[2a02:1205:c6be:84e0:ca2a:14ff:fe0b:803b]:8333 +[2a02:1206:45c3:be80:d4a4:3215:aaf0:85aa]:8333 [2a02:120b:2c2a:5ec0:10dd:31ff:fe42:5079]:8333 -[2a02:168:6273::614]:8333 +[2a02:120b:2c3f:3fc0:10dd:31ff:fe42:5079]:8333 +[2a02:121e:3e87:0:7d3a:fe09:b619:6b4b]:8333 +[2a02:168:420b:a::20]:8333 +[2a02:168:4a01::39]:8333 +[2a02:168:4a35:0:2e44:fdff:fe9a:46dc]:8333 +[2a02:180:1:1::517:10b6]:8333 [2a02:180:6:1::18]:8333 -[2a02:180:6:1::ed]:8333 -[2a02:1811:b707:116:8c1f:c5be:bf3a:54df]:8333 +[2a02:1810:1d13:7200:848b:c4c4:526b:e657]:8333 +[2a02:181f:0:2161:8f0:54b2:222c:b315]:8333 [2a02:20c8:1422:1::a3]:8333 +[2a02:2168:80d:6e8::2]:8333 [2a02:2168:d05:2c00:216:3eff:fef7:a099]:8333 -[2a02:27f8:2012:0:e9f7:268f:c441:6129]:8333 +[2a02:2528:503:2::14]:8333 [2a02:2808:5401:0:225:90ff:fe4e:ee42]:8333 [2a02:390:9000:0:218:7dff:fe10:be33]:8333 [2a02:7aa0:1201::bd4e:1219]:8333 [2a02:7aa0:1619::590:eba2]:8333 -[2a02:7aa0:1619::a7a2:7e86]:8333 +[2a02:7b40:50d0:e0d9::1]:8333 +[2a02:7b40:50d0:e335::1]:8333 +[2a02:7b40:c287:53af::1]:8333 +[2a02:7b40:d418:60c5::1]:8333 +[2a02:7b40:d418:6a84::1]:8333 +[2a02:8108:9c3f:dd18:922b:34ff:fe30:ac42]:8333 +[2a02:8109:9ac0:2a2b:707a:ad1a:70c:84a9]:8333 +[2a02:810d:8a40:36f8:9af2:b3ff:fee8:6d7a]:8333 +[2a02:810d:9840:7e50::227]:8333 +[2a02:930:1:0:250:56ff:fe8e:2819]:8333 +[2a02:c200:1:10:2:4:334:1]:8333 +[2a02:c200:1:10:2:5:227:1]:8333 [2a02:c200:1:10:2:5:800:1]:8333 -[2a02:c205:2002:2550::17]:8333 +[2a02:c205:0:5145::1]:8333 [2a02:c205:2008:272::1]:8333 -[2a02:c205:2010:5484::1]:8333 -[2a02:c205:3001:6710::1]:8333 -[2a02:c205:3001:7714::2]:8333 -[2a02:c205:3002:888::1]:8333 +[2a02:c205:2008:7160::1]:8333 +[2a02:c205:2009:7804::1]:8333 +[2a02:c205:2014:1981::1]:8333 +[2a02:c205:2014:3524::1]:8333 +[2a02:c205:2015:2475::1]:8333 +[2a02:c205:3002:2787::1]:8333 [2a02:c207:2002:9013::1]:8333 -[2a02:c207:2008:3392::1]:8333 -[2a02:c207:2008:8337::1]:8333 +[2a02:c207:2007:4699::1]:8333 +[2a02:c207:2008:6519::1]:8333 [2a02:c207:2009:213::1]:8333 -[2a02:c207:2010:7751::1]:8333 -[2a02:c207:2010:7986::1]:8333 -[2a02:c207:2011:7829::1]:8333 -[2a02:c207:2011:8299::1]:8333 -[2a02:c207:2012:2133::1]:8333 +[2a02:c207:2011:2583::1]:8333 [2a02:c207:2012:263::1]:8333 -[2a02:c207:2012:2682::1]:8333 -[2a02:c207:2012:3635::1]:8333 +[2a02:c207:2012:2917::1]:8333 [2a02:c207:2012:4826::1]:8333 -[2a02:c207:2012:5668::1]:8333 +[2a02:c207:2013:3160::1]:8333 +[2a02:c207:2014:4199::1]:8333 +[2a02:c207:2014:5639::1]:8333 +[2a02:c207:2014:7160::1]:8333 +[2a02:c207:2014:8104::1]:8333 +[2a02:c207:2014:8536::1]:8333 +[2a02:c207:2014:9433::1]:8333 +[2a02:c207:2015:4997::1]:8333 +[2a02:c207:2015:5919::1]:8333 [2a02:c207:3001:5824::1]:8333 +[2a02:c207:3001:7645::1]:8333 [2a02:c207:3001:7776::1]:8333 -[2a02:c207:3002:621::1]:8333 +[2a02:c207:3001:9320::1]:8333 +[2a02:c207:3002:1287::1]:8333 +[2a02:c207:3002:1532::1]:8333 +[2a02:c207:3002:2432::1]:8333 +[2a02:c207:3002:4431::1]:8333 +[2a02:c207:3002:809::1]:8333 +[2a02:c7f:7c2c:a800:428d:5cff:fe74:1455]:8333 +[2a02:c7f:d826:1901:20c:29ff:fe11:9d0e]:8333 [2a02:ce80:0:20::1]:8333 -[2a03:2260:11e:301::8]:8333 -[2a03:2260:11e:302::3]:8333 [2a03:4000:2:496::8]:8333 -[2a03:4000:6:12e7::1]:8333 -[2a03:4000:6:416c::53]:8333 +[2a03:7380:300:16::]:8333 +[2a03:7380:300:7:a19f:eb0b:ae0:6aad]:8333 [2a03:b0c0:3:d0::1219:6001]:8333 -[2a03:b0c0:3:d0::1b99:c001]:8333 -[2a03:b0c0:3:d0::1b99:e001]:8333 -[2a03:b0c0:3:d0::1b9a:3001]:8333 -[2a03:b0c0:3:d0::23f7:1001]:8333 -[2a03:b0c0:3:d0::23f7:2001]:8333 -[2a03:b0c0:3:d0::23f7:4001]:8333 -[2a03:b0c0:3:d0::23f7:5001]:8333 -[2a03:b0c0:3:d0::23f7:7001]:8333 -[2a03:b0c0:3:d0::23f7:9001]:8333 -[2a03:b0c0:3:d0::23fb:1001]:8333 -[2a03:b0c0:3:d0::23fb:2001]:8333 -[2a03:b0c0:3:d0::23fb:3001]:8333 -[2a03:b0c0:3:d0::23fb:5001]:8333 [2a03:b0c0:3:d0::23fb:6001]:8333 -[2a03:b0c0:3:d0::23fb:8001]:8333 -[2a03:b0c0:3:d0::23ff:b001]:8333 -[2a03:b0c0:3:d0::2400:1]:8333 -[2a03:b0c0:3:d0::2400:3001]:8333 -[2a03:b0c0:3:d0::2400:4001]:8333 -[2a03:b0c0:3:d0::2400:e001]:8333 -[2a03:b0c0:3:d0::2400:f001]:8333 -[2a03:b0c0:3:d0::2401:e001]:8333 -[2a03:b0c0:3:d0::2402:1]:8333 -[2a03:b0c0:3:d0::2402:2001]:8333 -[2a03:b0c0:3:d0::2402:8001]:8333 -[2a03:b0c0:3:d0::2402:9001]:8333 -[2a03:b0c0:3:d0::2402:b001]:8333 -[2a03:b0c0:3:d0::2402:d001]:8333 -[2a03:b0c0:3:d0::2402:e001]:8333 -[2a03:b0c0:3:d0::2403:1001]:8333 -[2a03:b0c0:3:d0::2403:2001]:8333 -[2a03:b0c0:3:d0::2403:3001]:8333 -[2a03:b0c0:3:d0::2403:4001]:8333 -[2a03:b0c0:3:d0::2403:6001]:8333 -[2a03:b0c0:3:d0::2403:a001]:8333 -[2a03:b0c0:3:d0::2403:b001]:8333 -[2a03:b0c0:3:d0::2403:e001]:8333 -[2a03:b0c0:3:d0::2403:f001]:8333 -[2a03:b0c0:3:d0::2404:1]:8333 -[2a03:b0c0:3:d0::2404:3001]:8333 -[2a03:b0c0:3:d0::2404:4001]:8333 -[2a03:b0c0:3:d0::2404:6001]:8333 -[2a03:b0c0:3:d0::2404:8001]:8333 -[2a03:b0c0:3:d0::2404:9001]:8333 -[2a03:b0c0:3:d0::2404:b001]:8333 -[2a03:b0c0:3:d0::2405:2001]:8333 -[2a03:b0c0:3:d0::2405:3001]:8333 -[2a03:b0c0:3:d0::2405:8001]:8333 -[2a03:b0c0:3:d0::2405:9001]:8333 -[2a03:b0c0:3:d0::2405:a001]:8333 [2a03:b0c0:3:d0::44b8:9001]:8333 +[2a03:b0c0:3:d0::44b8:a001]:8333 +[2a03:b0c0:3:d0::44b8:b001]:8333 [2a03:b0c0:3:d0::44b8:e001]:8333 [2a03:b0c0:3:d0::44b8:f001]:8333 [2a03:b0c0:3:d0::44b9:1]:8333 [2a03:b0c0:3:d0::44b9:1001]:8333 [2a03:b0c0:3:d0::44b9:2001]:8333 [2a03:b0c0:3:d0::44b9:4001]:8333 +[2a03:b0c0:3:d0::4:1]:8333 +[2a03:b0c0:3:d0::5e48:d001]:8333 +[2a03:b0c0:3:d0::c7:f001]:8333 +[2a03:b0c0:3:d0::e9:f001]:8333 +[2a03:ff40:4ed1:1004:a236:9fff:feb4:f9f8]:8333 [2a04:2180:0:2::94]:8333 -[2a04:3542:1000:910:8492:b8ff:fe91:711d]:8333 -[2a04:52c0:101:122::ba8e]:8333 +[2a04:2180:1:6:f000::14]:8333 +[2a04:52c0:101:122::496d]:8333 +[2a04:dbc3:fffe:0:e61f:13ff:fe95:8401]:8333 [2a05:3580:d400:140d:da6e:826e:e771:4100]:8333 -[2a06:9fc0:2a06:9fc0:2a06:9fc1:67c:e706]:8333 +[2a05:bec0:1:1:216:3eff:fe73:d20a]:8333 +[2a06:3d80:b:1:48b4:bedd:6964:54ac]:8333 +[2a06:3d80:b:1:ae1f:6bff:fe13:c13e]:8333 +[2a06:3d80:b:2:ae1f:6bff:fe13:c13e]:8333 +[2a06:3d80:b:2:ec4:7aff:fe96:b570]:8333 +[2a07:5740:600::14ad:9cec]:8333 +[2a07:5740:600::1b5:3082]:8333 +[2a07:5741:0:d8b::1]:8333 226eupdnaouu4h2v.onion:8333 -2frgxpe5mheghyom.onion:8333 -3ihjnsvwc3x6dp2o.onion:8333 -3w77hrilg6q64opl.onion:8333 -4ls4o6iszcd7mkfw.onion:8333 -4p3abjxqppzxi7qi.onion:8333 +2ej5qoyruoeijadb.onion:8333 +2f4xg7m3g6vtxqcd.onion:8333 +3ig6dutfdd6pkkw4.onion:8333 +3r44ddzjitznyahw.onion:8333 +53tsjt6zq3iasv5q.onion:8333 546esc6botbjfbxb.onion:8333 -5msftytzlsskr4ut.onion:8333 -5ty6rxpgrkmdnk4a.onion:8333 -akmqyuidrf56ip26.onion:8333 +5elzwcg4xysogalo.onion:8333 +5ygszbkbbauzjx7m.onion:8333 +64qrhyxglyjjhkne.onion:8333 +66ehyqkvke6td4fy.onion:8333 +6ruyo3kysvd27dlf.onion:8333 +6tr7cshvx5aymzth.onion:8333 +7nubu2wy3xizgwzu.onion:8333 +7nui6eestaw2f7xm.onion:8333 +7qg6jdmahfxamay5.onion:8333 +ab7ftdfw6qhdx3re.onion:8333 +ajqvsylg5xd5vs3y.onion:8333 alhlegtjkdmbqsvt.onion:8333 -bafk5ioatlgt7dgl.onion:8333 +b5d6etfljm2lje5y.onion:8333 +b7xer7moeiiz56cp.onion:8333 +brwqezn6le54w2bb.onion:8333 bup5n5e3kurvjzf3.onion:8333 -cjygd7pu5lqkky5j.onion:8333 +bvay66ezgxwo7wj4.onion:8333 +cgk4u2lxrvml4jvb.onion:8333 +cpyfqbs4fs3vnbpf.onion:8333 cyvpgt25274i5b7c.onion:8333 +d26tupmbhdjmxzwm.onion:8333 +d6wubsdtr46dd5ki.onion:8333 dekj4wacywpqsad3.onion:8333 dqpxwlpnv3z3hznl.onion:8333 -drarzpycbtxwbcld.onion:8333 -drp4pvejybx2ejdr.onion:8333 +dsrwqwijtsvi4dfk.onion:42434 dxkmtmwiq7ddtgul.onion:8333 -e6j57zkyibu2smad.onion:8333 +e3zbephvcqmzcqkr.onion:8333 +eab5op3z24n7eqd5.onion:8333 ejcqevujcqltqn7d.onion:8333 -eqgbt2ghfvsshbvo.onion:8333 -fgizgkdnndilo6ka.onion:8333 -fqxup4oev33eeidg.onion:8333 -gb5ypqt63du3wfhn.onion:8333 -ggdy2pb2avlbtjwq.onion:8333 +ep2mjzox3kvb6ax4.onion:8333 +f34cshhal2nuljsc.onion:8333 +f3nfioh27j2xlfe5.onion:8333 +f6h7ukyyiczlyvml.onion:8333 +faewczjuzs4wfxhv.onion:8333 +fnk3dioogxals7r4.onion:8333 hahhloezyfqh3hci.onion:8333 -ihdv6bzz2gx72fs7.onion:8333 +ifruqn4x7nbn5pba.onion:8333 +ijmbmziunbszzxtj.onion:8333 +imperialnza3tqgh.onion:8333 in7r5ieo7ogkxbne.onion:8333 +iuenlcarsnsstiix.onion:8333 +jtksnokusbzms7wl.onion:8333 +k6cpe3hatrrxvnz6.onion:8333 +kswfyurnglm65u7b.onion:8333 kvd44sw7skb5folw.onion:8333 -mn744hbioayn3ojs.onion:8333 -ms4ntrrisfxzpvmy.onion:8333 -n5lqwpjabqg62ihx.onion:8333 +l2pruzr3mnhieuug.onion:8333 +l5oddj46pvoddzd4.onion:8333 +lgkvbvro67jomosw.onion:8333 +loflfbxumxm55biq.onion:8333 +m6jrhrqvjbnzla3r.onion:8333 +mvomwfdddqfqg3lq.onion:8333 +o4dfb6tp33ff2lq7.onion:8333 o4sl5na6jeqgi3l6.onion:8333 -omjv24nbck4k5ud6.onion:8333 -po3j2hfkmf7sh36o.onion:8333 -psco6bxjewljrczx.onion:8333 -qi5yr6lvlckzffor.onion:8333 +o72zyzrv77ea2bwu.onion:8333 +omts4ofhwqjdulr6.onion:8333 +pbnlp7m4kujma6iz.onion:8333 +pcfhsdqzs6q63ryu.onion:8333 +pjghcivzkoersesd.onion:8333 +pz2x5nfhjipshaz3.onion:8333 +qaxm5spmx5d2k3up.onion:8333 +qepth54daysmpy5y.onion:8333 +qgw4jb6yikp44ypa.onion:8333 +qj6irqn2i73edff5.onion:8333 qlv6py6hdtzipntn.onion:8333 -qynmpgdbp23xyfnj.onion:8333 -rhtawcs7xak4gi3t.onion:8333 +qv4hq75asyitkmas.onion:8333 +r3dsojfhwcm7x7p6.onion:8333 rjacws757ai66lre.onion:8333 -rjlnp3hwvrsmap6e.onion:8333 -rkdvqcrtfv6yt4oy.onion:8333 -rlafimkctvz63llg.onion:8333 -rlj4ppok4dnsdu5n.onion:8333 seoskudzk6vn6mqz.onion:8333 -tayqi57tfiy7x3vk.onion:8333 +smtmhcewuv6tjynv.onion:8333 +stil3scvqbvhowvb.onion:8333 tchop676j6yppwwm.onion:8333 +toguvy5upyuctudx.onion:8333 +tpx4jan5n2a2cci2.onion:8333 trrtyp3sirmwttyu.onion:8333 -tx4zd7d5exonnblh.onion:8333 -u4ecb7txxi6l3gix.onion:8333 -umcxcmfycvejw264.onion:8333 -v7xqd42ocemalurd.onion:8333 -vb267mt3lnwfdmdb.onion:8333 +u7mpvxotmnqntyn5.onion:8333 +ueo6royc3775ioq7.onion:8333 vev3n5fxfrtqj6e5.onion:8333 visevrizz3quyagj.onion:8333 -vpg6p5e5ln33dqtp.onion:8333 -vr2ruasinafoy3fl.onion:8333 -x6pthvd5x6abyfo7.onion:8333 -xbwbzrspvav7u5ie.onion:8333 -xfcevnql2chnawko.onion:8333 -ycivnom44dmxx4ob.onion:8333 -yzdvlv5daitafekn.onion:8333 +vnzfcobvaqahooun.onion:8333 +w2dtur5kugapw3rp.onion:8333 +wg6vwmbrzyyzapun.onion:8333 +wmxc6ask4a5xyaxh.onion:8333 +xz3bsfhiqucn37gd.onion:8333 +ypzld2xyidu6ymqc.onion:8333 +yyuxafli7fqdizhq.onion:8333 +ziew7smr2dl2hg2q.onion:8333 +zsq5qogtoshzkqad.onion:8333 diff --git a/contrib/testgen/base58.py b/contrib/testgen/base58.py index 0d09692b36..816d40b49c 100644 --- a/contrib/testgen/base58.py +++ b/contrib/testgen/base58.py @@ -1,4 +1,4 @@ -# Copyright (c) 2012-2016 The Bitcoin Core developers +# Copyright (c) 2012-2017 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. ''' diff --git a/contrib/testgen/gen_base58_test_vectors.py b/contrib/testgen/gen_base58_test_vectors.py index 86366eb8e3..8e6a5d5819 100755 --- a/contrib/testgen/gen_base58_test_vectors.py +++ b/contrib/testgen/gen_base58_test_vectors.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# Copyright (c) 2012-2016 The Bitcoin Core developers +# Copyright (c) 2012-2017 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. ''' diff --git a/contrib/tidy_datadir.sh b/contrib/tidy_datadir.sh index 8960f8811d..b845b34e41 100755 --- a/contrib/tidy_datadir.sh +++ b/contrib/tidy_datadir.sh @@ -4,7 +4,7 @@ # file COPYING or http://www.opensource.org/licenses/mit-license.php. if [ -d "$1" ]; then - cd "$1" + cd "$1" || exit 1 else echo "Usage: $0 <datadir>" >&2 echo "Removes obsolete Bitcoin database files" >&2 diff --git a/contrib/verify-commits/gpg.sh b/contrib/verify-commits/gpg.sh index abd8f5fd9f..8f3e4b8063 100755 --- a/contrib/verify-commits/gpg.sh +++ b/contrib/verify-commits/gpg.sh @@ -9,7 +9,7 @@ REVSIG=false IFS=' ' if [ "$BITCOIN_VERIFY_COMMITS_ALLOW_SHA1" = 1 ]; then - GPG_RES="$(echo "$INPUT" | gpg --trust-model always "$@" 2>/dev/null)" + GPG_RES="$(printf '%s\n' "$INPUT" | gpg --trust-model always "$@" 2>/dev/null)" else # Note how we've disabled SHA1 with the --weak-digest option, disabling # signatures - including selfsigs - that use SHA1. While you might think that @@ -24,7 +24,7 @@ else case "$LINE" in "gpg (GnuPG) 1.4.1"*|"gpg (GnuPG) 2.0."*) echo "Please upgrade to at least gpg 2.1.10 to check for weak signatures" > /dev/stderr - GPG_RES="$(echo "$INPUT" | gpg --trust-model always "$@" 2>/dev/null)" + GPG_RES="$(printf '%s\n' "$INPUT" | gpg --trust-model always "$@" 2>/dev/null)" ;; # We assume if you're running 2.1+, you're probably running 2.1.10+ # gpg will fail otherwise @@ -32,7 +32,7 @@ else # gpg will fail otherwise esac done - [ "$GPG_RES" = "" ] && GPG_RES="$(echo "$INPUT" | gpg --trust-model always --weak-digest sha1 "$@" 2>/dev/null)" + [ "$GPG_RES" = "" ] && GPG_RES="$(printf '%s\n' "$INPUT" | gpg --trust-model always --weak-digest sha1 "$@" 2>/dev/null)" fi for LINE in $(echo "$GPG_RES"); do case "$LINE" in @@ -57,8 +57,8 @@ if ! $VALID; then exit 1 fi if $VALID && $REVSIG; then - echo "$INPUT" | gpg --trust-model always "$@" 2>/dev/null | grep "\[GNUPG:\] \(NEWSIG\|SIG_ID\|VALIDSIG\)" + printf '%s\n' "$INPUT" | gpg --trust-model always "$@" 2>/dev/null | grep "\[GNUPG:\] \(NEWSIG\|SIG_ID\|VALIDSIG\)" echo "$GOODREVSIG" else - echo "$INPUT" | gpg --trust-model always "$@" 2>/dev/null + printf '%s\n' "$INPUT" | gpg --trust-model always "$@" 2>/dev/null fi diff --git a/contrib/verify-commits/verify-commits.sh b/contrib/verify-commits/verify-commits.sh index a1ef715fb3..532b97a438 100755 --- a/contrib/verify-commits/verify-commits.sh +++ b/contrib/verify-commits/verify-commits.sh @@ -33,10 +33,11 @@ fi NO_SHA1=1 PREV_COMMIT="" +INITIAL_COMMIT="${CURRENT_COMMIT}" while true; do if [ "$CURRENT_COMMIT" = $VERIFIED_ROOT ]; then - echo "There is a valid path from "$CURRENT_COMMIT" to $VERIFIED_ROOT where all commits are signed!" + echo "There is a valid path from \"$INITIAL_COMMIT\" to $VERIFIED_ROOT where all commits are signed!" exit 0 fi diff --git a/contrib/verifybinaries/verify.sh b/contrib/verifybinaries/verify.sh index 320add64d0..e0266bf08a 100755 --- a/contrib/verifybinaries/verify.sh +++ b/contrib/verifybinaries/verify.sh @@ -33,7 +33,7 @@ if [ ! -d "$WORKINGDIR" ]; then mkdir "$WORKINGDIR" fi -cd "$WORKINGDIR" +cd "$WORKINGDIR" || exit 1 #test if a version number has been passed as an argument if [ -n "$1" ]; then @@ -87,7 +87,7 @@ WGETOUT=$(wget -N "$HOST1$BASEDIR$SIGNATUREFILENAME" 2>&1) #and then see if wget completed successfully if [ $? -ne 0 ]; then echo "Error: couldn't fetch signature file. Have you specified the version number in the following format?" - echo "[$VERSIONPREFIX]<version>-[$RCVERSIONSTRING[0-9]] (example: "$VERSIONPREFIX"0.10.4-"$RCVERSIONSTRING"1)" + echo "[$VERSIONPREFIX]<version>-[$RCVERSIONSTRING[0-9]] (example: ${VERSIONPREFIX}0.10.4-${RCVERSIONSTRING}1)" echo "wget output:" echo "$WGETOUT"|sed 's/^/\t/g' exit 2 diff --git a/contrib/zmq/zmq_sub.py b/contrib/zmq/zmq_sub.py index 5cc19761d4..6e44c56f52 100755 --- a/contrib/zmq/zmq_sub.py +++ b/contrib/zmq/zmq_sub.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2014-2016 The Bitcoin Core developers +# Copyright (c) 2014-2017 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -8,8 +8,8 @@ Bitcoin should be started with the command line arguments: bitcoind -testnet -daemon \ - -zmqpubhashblock=tcp://127.0.0.1:28332 \ -zmqpubrawtx=tcp://127.0.0.1:28332 \ + -zmqpubrawblock=tcp://127.0.0.1:28332 \ -zmqpubhashtx=tcp://127.0.0.1:28332 \ -zmqpubhashblock=tcp://127.0.0.1:28332 diff --git a/contrib/zmq/zmq_sub3.4.py b/contrib/zmq/zmq_sub3.4.py index bfb7ea9eae..536352d5ff 100755 --- a/contrib/zmq/zmq_sub3.4.py +++ b/contrib/zmq/zmq_sub3.4.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2014-2016 The Bitcoin Core developers +# Copyright (c) 2014-2017 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -8,8 +8,8 @@ Bitcoin should be started with the command line arguments: bitcoind -testnet -daemon \ - -zmqpubhashblock=tcp://127.0.0.1:28332 \ -zmqpubrawtx=tcp://127.0.0.1:28332 \ + -zmqpubrawblock=tcp://127.0.0.1:28332 \ -zmqpubhashtx=tcp://127.0.0.1:28332 \ -zmqpubhashblock=tcp://127.0.0.1:28332 diff --git a/depends/README.md b/depends/README.md index 6053c531b4..99eef1952c 100644 --- a/depends/README.md +++ b/depends/README.md @@ -28,6 +28,22 @@ Common `host-platform-triplets` for cross compilation are: No other options are needed, the paths are automatically configured. +Install the required dependencies: Ubuntu & Debian +-------------------------------------------------- + +For macOS cross compilation: + + sudo apt-get install curl librsvg2-bin libtiff-tools bsdmainutils cmake imagemagick libcap-dev libz-dev libbz2-dev python-setuptools + +For Win32/Win64 cross compilation: + +- see [build-windows.md](../doc/build-windows.md#cross-compilation-for-ubuntu-and-windows-subsystem-for-linux) + +For linux (including i386, ARM) cross compilation: + + sudo apt-get install curl g++-aarch64-linux-gnu g++-4.8-aarch64-linux-gnu gcc-4.8-aarch64-linux-gnu binutils-aarch64-linux-gnu g++-arm-linux-gnueabihf g++-4.8-arm-linux-gnueabihf gcc-4.8-arm-linux-gnueabihf binutils-arm-linux-gnueabihf g++-4.8-multilib gcc-4.8-multilib binutils-gold bsdmainutils + + Dependency Options: The following can be set when running make: make FOO=bar diff --git a/depends/packages/zeromq.mk b/depends/packages/zeromq.mk index 01146c26f6..3f97221e10 100644 --- a/depends/packages/zeromq.mk +++ b/depends/packages/zeromq.mk @@ -1,19 +1,18 @@ package=zeromq -$(package)_version=4.1.5 -$(package)_download_path=https://github.com/zeromq/zeromq4-1/releases/download/v$($(package)_version)/ +$(package)_version=4.2.2 +$(package)_download_path=https://github.com/zeromq/libzmq/releases/download/v$($(package)_version)/ $(package)_file_name=$(package)-$($(package)_version).tar.gz -$(package)_sha256_hash=04aac57f081ffa3a2ee5ed04887be9e205df3a7ddade0027460b8042432bdbcf -$(package)_patches=9114d3957725acd34aa8b8d011585812f3369411.patch 9e6745c12e0b100cd38acecc16ce7db02905e27c.patch +$(package)_sha256_hash=5b23f4ca9ef545d5bd3af55d305765e3ee06b986263b31967435d285a3e6df6b +$(package)_patches=0001-fix-build-with-older-mingw64.patch define $(package)_set_vars - $(package)_config_opts=--without-documentation --disable-shared --without-libsodium --disable-curve + $(package)_config_opts=--without-docs --disable-shared --without-libsodium --disable-curve --disable-curve-keygen --disable-perf $(package)_config_opts_linux=--with-pic $(package)_cxxflags=-std=c++11 endef define $(package)_preprocess_cmds - patch -p1 < $($(package)_patch_dir)/9114d3957725acd34aa8b8d011585812f3369411.patch && \ - patch -p1 < $($(package)_patch_dir)/9e6745c12e0b100cd38acecc16ce7db02905e27c.patch && \ + patch -p1 < $($(package)_patch_dir)/0001-fix-build-with-older-mingw64.patch && \ ./autogen.sh endef @@ -22,7 +21,7 @@ define $(package)_config_cmds endef define $(package)_build_cmds - $(MAKE) libzmq.la + $(MAKE) src/libzmq.la endef define $(package)_stage_cmds @@ -30,5 +29,6 @@ define $(package)_stage_cmds endef define $(package)_postprocess_cmds + sed -i.old "s/ -lstdc++//" lib/pkgconfig/libzmq.pc && \ rm -rf bin share endef diff --git a/depends/patches/zeromq/0001-fix-build-with-older-mingw64.patch b/depends/patches/zeromq/0001-fix-build-with-older-mingw64.patch new file mode 100644 index 0000000000..a6c508fb8a --- /dev/null +++ b/depends/patches/zeromq/0001-fix-build-with-older-mingw64.patch @@ -0,0 +1,30 @@ +From 1a159c128c69a42d90819375c06a39994f3fbfc1 Mon Sep 17 00:00:00 2001 +From: Cory Fields <cory-nospam-@coryfields.com> +Date: Tue, 28 Nov 2017 20:33:25 -0500 +Subject: [PATCH] fix build with older mingw64 + +--- + src/windows.hpp | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/src/windows.hpp b/src/windows.hpp +index 99e889d..e69038e 100644 +--- a/src/windows.hpp ++++ b/src/windows.hpp +@@ -55,6 +55,13 @@ + #include <winsock2.h> + #include <windows.h> + #include <mswsock.h> ++ ++#if defined __MINGW64_VERSION_MAJOR && __MINGW64_VERSION_MAJOR < 4 ++// Workaround for mingw-w64 < v4.0 which did not include ws2ipdef.h in iphlpapi.h. ++// Fixed in mingw-w64 by 9bd8fe9148924840d315b4c915dd099955ea89d1. ++#include <ws2def.h> ++#include <ws2ipdef.h> ++#endif + #include <iphlpapi.h> + + #if !defined __MINGW32__ +-- +2.7.4 + diff --git a/depends/patches/zeromq/9114d3957725acd34aa8b8d011585812f3369411.patch b/depends/patches/zeromq/9114d3957725acd34aa8b8d011585812f3369411.patch deleted file mode 100644 index f704b3d94f..0000000000 --- a/depends/patches/zeromq/9114d3957725acd34aa8b8d011585812f3369411.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 9114d3957725acd34aa8b8d011585812f3369411 Mon Sep 17 00:00:00 2001 -From: Jeroen Ooms <jeroenooms@gmail.com> -Date: Tue, 20 Oct 2015 13:10:38 +0200 -Subject: [PATCH] enable static libraries on mingw - ---- - configure.ac | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/configure.ac b/configure.ac -index 393505b..e92131a 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -265,7 +265,7 @@ case "${host_os}" in - libzmq_dso_visibility="no" - - if test "x$enable_static" = "xyes"; then -- AC_MSG_ERROR([Building static libraries is not supported under MinGW32]) -+ CPPFLAGS="-DZMQ_STATIC" - fi - - # Set FD_SETSIZE to 1024
\ No newline at end of file diff --git a/depends/patches/zeromq/9e6745c12e0b100cd38acecc16ce7db02905e27c.patch b/depends/patches/zeromq/9e6745c12e0b100cd38acecc16ce7db02905e27c.patch deleted file mode 100644 index 9aff2c179a..0000000000 --- a/depends/patches/zeromq/9e6745c12e0b100cd38acecc16ce7db02905e27c.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 9e6745c12e0b100cd38acecc16ce7db02905e27c Mon Sep 17 00:00:00 2001 -From: David Millard <dmillard10@gmail.com> -Date: Tue, 10 May 2016 13:53:53 -0700 -Subject: [PATCH] Fix autotools for static MinGW builds - ---- - configure.ac | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/configure.ac b/configure.ac -index 5a0fa14..def6ea7 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -259,7 +259,7 @@ case "${host_os}" in - libzmq_dso_visibility="no" - - if test "x$enable_static" = "xyes"; then -- CPPFLAGS="-DZMQ_STATIC" -+ CPPFLAGS="-DZMQ_STATIC $CPPFLAGS" - fi - - # Set FD_SETSIZE to 1024
\ No newline at end of file diff --git a/doc/benchmarking.md b/doc/benchmarking.md index 0ba75afcda..99d36cb226 100644 --- a/doc/benchmarking.md +++ b/doc/benchmarking.md @@ -4,24 +4,49 @@ Benchmarking Bitcoin Core has an internal benchmarking framework, with benchmarks for cryptographic algorithms such as SHA1, SHA256, SHA512 and RIPEMD160. As well as the rolling bloom filter. +Running +--------------------- After compiling bitcoin-core, the benchmarks can be run with: -`src/bench/bench_bitcoin` + + src/bench/bench_bitcoin The output will look similar to: ``` -#Benchmark,count,min,max,average -RIPEMD160,448,0.001245033173334,0.002638196945190,0.002461894814457 -RollingBloom-refresh,1,0.000635000000000,0.000635000000000,0.000635000000000 -RollingBloom-refresh,1,0.000108000000000,0.000108000000000,0.000108000000000 -RollingBloom-refresh,1,0.000107000000000,0.000107000000000,0.000107000000000 -RollingBloom-refresh,1,0.000204000000000,0.000204000000000,0.000204000000000 -SHA1,640,0.000909024336207,0.001938136418660,0.001843086257577 -SHA256,256,0.002209486499909,0.008500099182129,0.004300644621253 -SHA512,384,0.001319904176016,0.002813005447388,0.002615700786312 -Sleep100ms,10,0.205592155456543,0.210056066513062,0.104166316986084 -Trig,67108864,0.000000014997003,0.000000015448112,0.000000015188842 +# Benchmark, evals, iterations, total, min, max, median +Base58CheckEncode, 5, 320000, 120.772, 7.49351e-05, 7.59374e-05, 7.54759e-05 +Base58Decode, 5, 800000, 122.833, 3.0467e-05, 3.11732e-05, 3.06304e-05 +Base58Encode, 5, 470000, 137.094, 5.81061e-05, 5.85109e-05, 5.84462e-05 +BenchLockedPool, 5, 530, 34.2023, 0.0128247, 0.0129613, 0.0129026 +CCheckQueueSpeedPrevectorJob, 5, 1400, 26.1762, 0.00365048, 0.00388629, 0.00367108 +CCoinsCaching, 5, 170000, 48.1074, 5.60229e-05, 5.72316e-05, 5.66214e-05 +CoinSelection, 5, 650, 34.6426, 0.0105801, 0.0107699, 0.010664 +DeserializeAndCheckBlockTest, 5, 160, 39.2084, 0.0483662, 0.0494199, 0.0490138 +DeserializeBlockTest, 5, 130, 23.8129, 0.0357731, 0.0373763, 0.0365858 +FastRandom_1bit, 5, 440000000, 38.1609, 1.72974e-08, 1.73882e-08, 1.73478e-08 +FastRandom_32bit, 5, 110000000, 72.8237, 1.29992e-07, 1.37014e-07, 1.30115e-07 +MempoolEviction, 5, 41000, 89.8883, 0.000432748, 0.000446857, 0.000438483 +PrevectorClear, 5, 5600, 47.9229, 0.00169952, 0.0017455, 0.00170315 +PrevectorDestructor, 5, 5700, 44.5498, 0.0015561, 0.00156977, 0.00156469 +RIPEMD160, 5, 440, 135.988, 0.0615496, 0.062268, 0.0617779 +RollingBloom, 5, 1500000, 36.5109, 4.80961e-06, 4.97463e-06, 4.85811e-06 +SHA1, 5, 570, 51.808, 0.018065, 0.0182623, 0.0181865 +SHA256, 5, 340, 8.31841, 0.00483231, 0.00499803, 0.00485486 +SHA256_32b, 5, 4700000, 10.469, 4.43441e-07, 4.47611e-07, 4.45223e-07 +SHA512, 5, 330, 33.3408, 0.02017, 0.0202554, 0.0201921 +SipHash_32b, 5, 40000000, 38.7088, 1.91103e-07, 1.96998e-07, 1.93792e-07 +Sleep100ms, 5, 10, 5.01062, 0.100131, 0.100368, 0.100147 +Trig, 5, 12000000, 5.95494, 9.78115e-08, 1.04354e-07, 9.80682e-08 +VerifyScriptBench, 5, 6300, 9.02493, 0.000285566, 0.000288433, 0.000286175 ``` +Help +--------------------- +`-?` will print a list of options and exit: + + src/bench/bench_bitcoin -? + +Notes +--------------------- More benchmarks are needed for, in no particular order: - Script Validation - CCoinDBView caching diff --git a/doc/bips.md b/doc/bips.md index bc8dcb6fb3..e587275f0f 100644 --- a/doc/bips.md +++ b/doc/bips.md @@ -33,3 +33,5 @@ BIPs that are implemented by Bitcoin Core (up-to-date up to **v0.13.0**): * [`BIP 145`](https://github.com/bitcoin/bips/blob/master/bip-0145.mediawiki): getblocktemplate updates for Segregated Witness as of **v0.13.0** ([PR 8149](https://github.com/bitcoin/bitcoin/pull/8149)). * [`BIP 147`](https://github.com/bitcoin/bips/blob/master/bip-0147.mediawiki): NULLDUMMY softfork as of **v0.13.1** ([PR 8636](https://github.com/bitcoin/bitcoin/pull/8636) and [PR 8937](https://github.com/bitcoin/bitcoin/pull/8937)). * [`BIP 152`](https://github.com/bitcoin/bips/blob/master/bip-0152.mediawiki): Compact block transfer and related optimizations are used as of **v0.13.0** ([PR 8068](https://github.com/bitcoin/bitcoin/pull/8068)). +* [`BIP 159`](https://github.com/bitcoin/bips/blob/master/bip-0159.mediawiki): NODE_NETWORK_LIMITED service bit [signaling only] is supported as of **v0.16.0** ([PR 11740](https://github.com/bitcoin/bitcoin/pull/11740)). +* [`BIP 176`](https://github.com/bitcoin/bips/blob/master/bip-0176.mediawiki): Bits Denomination [QT only] is supported as of **v0.16.0** ([PR 12035](https://github.com/bitcoin/bitcoin/pull/12035)). diff --git a/doc/build-openbsd.md b/doc/build-openbsd.md index cd1d217b47..0817821221 100644 --- a/doc/build-openbsd.md +++ b/doc/build-openbsd.md @@ -23,47 +23,31 @@ git clone https://github.com/bitcoin/bitcoin.git See [dependencies.md](dependencies.md) for a complete overview. -GCC -------- - -The default C++ compiler that comes with OpenBSD 6.2 is g++ 4.2.1. This version is old (from 2007), and is not able to compile the current version of Bitcoin Core because it has no C++11 support. We'll install a newer version of GCC: - -```bash - pkg_add g++ - ``` - - This compiler will not overwrite the system compiler, it will be installed as `egcc` and `eg++` in `/usr/local/bin`. +**Important**: From OpenBSD 6.2 onwards a C++11-supporting clang compiler is +part of the base image, and while building it is necessary to make sure that this +compiler is used and not ancient g++ 4.2.1. This is done by appending +`CC=cc CXX=c++` to configuration commands. Mixing different compilers +within the same executable will result in linker errors. ### Building BerkeleyDB -BerkeleyDB is only necessary for the wallet functionality. To skip this, pass `--disable-wallet` to `./configure`. +BerkeleyDB is only necessary for the wallet functionality. To skip this, pass +`--disable-wallet` to `./configure` and skip to the next section. It is recommended to use Berkeley DB 4.8. You cannot use the BerkeleyDB library from ports, for the same reason as boost above (g++/libstd++ incompatibility). If you have to build it yourself, you can use [the installation script included -in contrib/](contrib/install_db4.sh) like so +in contrib/](/contrib/install_db4.sh) like so ```shell -./contrib/install_db4.sh `pwd` CC=egcc CXX=eg++ CPP=ecpp +./contrib/install_db4.sh `pwd` CC=cc CXX=c++ ``` -from the root of the repository. - -### Resource limits - -The standard ulimit restrictions in OpenBSD are very strict: - - data(kbytes) 1572864 +from the root of the repository. Then set `BDB_PREFIX` for the next section: -This, unfortunately, may no longer be enough to compile some `.cpp` files in the project, -at least with GCC 4.9.4 (see issue [#6658](https://github.com/bitcoin/bitcoin/issues/6658)). -If your user is in the `staff` group the limit can be raised with: - - ulimit -d 3000000 - -The change will only affect the current shell and processes spawned by it. To -make the change system-wide, change `datasize-cur` and `datasize-max` in -`/etc/login.conf`, and reboot. +```shell +export BDB_PREFIX="$PWD/db4" +``` ### Building Bitcoin Core @@ -79,13 +63,13 @@ Make sure `BDB_PREFIX` is set to the appropriate path from the above steps. To configure with wallet: ```bash -./configure --with-gui=no CC=egcc CXX=eg++ CPP=ecpp \ +./configure --with-gui=no CC=cc CXX=c++ \ BDB_LIBS="-L${BDB_PREFIX}/lib -ldb_cxx-4.8" BDB_CFLAGS="-I${BDB_PREFIX}/include" ``` To configure without wallet: ```bash -./configure --disable-wallet --with-gui=no CC=egcc CXX=eg++ CPP=ecpp +./configure --disable-wallet --with-gui=no CC=cc CXX=c++ ``` Build and run the tests: @@ -94,13 +78,23 @@ gmake # use -jX here for parallelism gmake check ``` -Clang ------------------------------- +Resource limits +------------------- -```bash -pkg_add llvm +If the build runs into out-of-memory errors, the instructions in this section +might help. + +The standard ulimit restrictions in OpenBSD are very strict: + + data(kbytes) 1572864 + +This, unfortunately, in some cases not enough to compile some `.cpp` files in the project, +(see issue [#6658](https://github.com/bitcoin/bitcoin/issues/6658)). +If your user is in the `staff` group the limit can be raised with: + + ulimit -d 3000000 + +The change will only affect the current shell and processes spawned by it. To +make the change system-wide, change `datasize-cur` and `datasize-max` in +`/etc/login.conf`, and reboot. -./configure --disable-wallet --with-gui=no CC=clang CXX=clang++ -gmake # use -jX here for parallelism -gmake check -``` diff --git a/doc/build-osx.md b/doc/build-osx.md index 6f08562ff8..3e243933c8 100644 --- a/doc/build-osx.md +++ b/doc/build-osx.md @@ -16,7 +16,7 @@ Then install [Homebrew](https://brew.sh). Dependencies ---------------------- - brew install automake berkeley-db4 libtool boost --c++11 miniupnpc openssl pkg-config protobuf python3 qt libevent + brew install automake berkeley-db4 libtool boost miniupnpc openssl pkg-config protobuf python3 qt libevent See [dependencies.md](dependencies.md) for a complete overview. @@ -29,7 +29,7 @@ NOTE: Building with Qt4 is still supported, however, could result in a broken UI Berkeley DB ----------- It is recommended to use Berkeley DB 4.8. If you have to build it yourself, -you can use [the installation script included in contrib/](contrib/install_db4.sh) +you can use [the installation script included in contrib/](/contrib/install_db4.sh) like so ```shell @@ -110,6 +110,6 @@ Uncheck everything except Qt Creator during the installation process. Notes ----- -* Tested on OS X 10.8 through 10.12 on 64-bit Intel processors only. +* Tested on OS X 10.8 through 10.13 on 64-bit Intel processors only. * Building with downloaded Qt binaries is not officially supported. See the notes in [#7714](https://github.com/bitcoin/bitcoin/issues/7714) diff --git a/doc/build-unix.md b/doc/build-unix.md index 5d3329e2cf..af567cadeb 100644 --- a/doc/build-unix.md +++ b/doc/build-unix.md @@ -166,7 +166,7 @@ turned off by default. See the configure options for upnp behavior desired: Berkeley DB ----------- It is recommended to use Berkeley DB 4.8. If you have to build it yourself, -you can use [the installation script included in contrib/](contrib/install_db4.sh) +you can use [the installation script included in contrib/](/contrib/install_db4.sh) like so ```shell @@ -312,17 +312,13 @@ You need to use GNU make (`gmake`) instead of `make`. For the wallet (optional): - pkg install db5 - -This will give a warning "configure: WARNING: Found Berkeley DB other -than 4.8; wallets opened by this build will not be portable!", but as FreeBSD never -had a binary release, this may not matter. If backwards compatibility -with 4.8-built Bitcoin Core is needed follow the steps under "Berkeley DB" above. + ./contrib/install_db4.sh `pwd` + setenv BDB_PREFIX $PWD/db4 Then build using: ./autogen.sh - ./configure --with-incompatible-bdb BDB_CFLAGS="-I/usr/local/include/db5" BDB_LIBS="-L/usr/local/lib -ldb_cxx-5" + ./configure BDB_CFLAGS="-I${BDB_PREFIX}/include" BDB_LIBS="-L${BDB_PREFIX}/lib -ldb_cxx" gmake *Note on debugging*: The version of `gdb` installed by default is [ancient and considered harmful](https://wiki.freebsd.org/GdbRetirement). diff --git a/doc/dependencies.md b/doc/dependencies.md index 964c03ba88..5c5645de97 100644 --- a/doc/dependencies.md +++ b/doc/dependencies.md @@ -13,7 +13,7 @@ These are the dependencies currently used by Bitcoin Core. You can find instruct | Expat | [2.2.1](https://libexpat.github.io/) | | No | Yes | | | fontconfig | [2.12.1](https://www.freedesktop.org/software/fontconfig/release/) | | No | Yes | | | FreeType | [2.7.1](http://download.savannah.gnu.org/releases/freetype) | | No | | | -| GCC | | [4.7+](https://gcc.gnu.org/) | | | | +| GCC | | [4.8+](https://gcc.gnu.org/) | | | | | HarfBuzz-NG | | | | | | | libevent | [2.1.8-stable](https://github.com/libevent/libevent/releases) | 2.0.22 | No | | | | libjpeg | | | | | [Yes](https://github.com/bitcoin/bitcoin/blob/master/depends/packages/qt.mk#L75) | @@ -27,5 +27,5 @@ These are the dependencies currently used by Bitcoin Core. You can find instruct | Qt | [5.7.1](https://download.qt.io/official_releases/qt/) | 4.7+ | No | | | | XCB | | | | | [Yes](https://github.com/bitcoin/bitcoin/blob/master/depends/packages/qt.mk#L94) (Linux only) | | xkbcommon | | | | | [Yes](https://github.com/bitcoin/bitcoin/blob/master/depends/packages/qt.mk#L93) (Linux only) | -| ZeroMQ | [4.1.5](https://github.com/zeromq/libzmq/releases) | | No | | | +| ZeroMQ | [4.2.2](https://github.com/zeromq/libzmq/releases) | | No | | | | zlib | [1.2.11](http://zlib.net/) | | | | No | diff --git a/doc/developer-notes.md b/doc/developer-notes.md index 7f34b07d15..9dc63a1e4b 100644 --- a/doc/developer-notes.md +++ b/doc/developer-notes.md @@ -493,7 +493,7 @@ namespace { - *Rationale*: Avoids confusion about the namespace context - Prefer `#include <primitives/transaction.h>` bracket syntax instead of - `#include "primitives/transactions.h"`` quote syntax when possible. + `#include "primitives/transactions.h"` quote syntax when possible. - *Rationale*: Bracket syntax is less ambiguous because the preprocessor searches a fixed list of include directories without taking location of the diff --git a/doc/files.md b/doc/files.md index 3d603445fb..2eac7ed664 100644 --- a/doc/files.md +++ b/doc/files.md @@ -6,13 +6,16 @@ * blocks/rev000??.dat; block undo data (custom); since 0.8.0 (format changed since pre-0.8) * blocks/index/*; block index (LevelDB); since 0.8.0 * chainstate/*; block chain state database (LevelDB); since 0.8.0 -* database/*: BDB database environment; only used for wallet since 0.8.0 -* db.log: wallet database log file +* database/*: BDB database environment; only used for wallet since 0.8.0; moved to wallets/ directory on new installs since 0.16.0 +* db.log: wallet database log file; moved to wallets/ directory on new installs since 0.16.0 * debug.log: contains debug information and general logging generated by bitcoind or bitcoin-qt * fee_estimates.dat: stores statistics used to estimate minimum transaction fees and priorities required for confirmation; since 0.10.0 * mempool.dat: dump of the mempool's transactions; since 0.14.0. * peers.dat: peer IP address database (custom format); since 0.7.0 -* wallet.dat: personal wallet (BDB) with keys and transactions +* wallet.dat: personal wallet (BDB) with keys and transactions; moved to wallets/ directory on new installs since 0.16.0 +* wallets/database/*: BDB database environment; used for wallets since 0.16.0 +* wallets/db.log: wallet database log file; since 0.16.0 +* wallets/wallet.dat: personal wallet (BDB) with keys and transactions; since 0.16.0 * .cookie: session RPC authentication cookie (written at start when cookie authentication is used, deleted on shutdown): since 0.12.0 * onion_private_key: cached Tor hidden service private key for `-listenonion`: since 0.12.0 * guisettings.ini.bak: backup of former GUI settings after `-resetguisettings` is used diff --git a/doc/release-notes.md b/doc/release-notes.md index 6e4fed0a2d..29377d4a1d 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -20,7 +20,7 @@ How to Upgrade ============== If you are running an older version, shut it down. Wait until it has completely -shut down (which might take a few minutes for older versions), then run the +shut down (which might take a few minutes for older versions), then run the installer (on Windows) or just copy over `/Applications/Bitcoin-Qt` (on Mac) or `bitcoind`/`bitcoin-qt` (on Linux). @@ -56,12 +56,46 @@ frequently tested on them. Notable changes =============== +GCC 4.8.x +-------------- +The minimum version of GCC required to compile Bitcoin Core is now 4.8. No effort will be +made to support older versions of GCC. See discussion in issue #11732 for more information. + HD-wallets by default --------------------- Due to a backward-incompatible change in the wallet database, wallets created with version 0.16.0 will be rejected by previous versions. Also, version 0.16.0 will only create hierarchical deterministic (HD) wallets. +Replace-By-Fee by default in GUI +-------------------------------- +The send screen now uses BIP-125 RBF by default, regardless of `-walletrbf`. +There is a checkbox to mark the transaction as final. + +The RPC default remains unchanged: to use RBF, launch with `-walletrbf=1` or +use the `replaceable` argument for individual transactions. + +Wallets directory configuration (`-walletdir`) +---------------------------------------------- + +Bitcoin Core now has more flexibility in where the wallets directory can be +located. Previously wallet database files were stored at the top level of the +bitcoin data directory. The behavior is now: + +- For new installations (where the data directory doesn't already exist), + wallets will now be stored in a new `wallets/` subdirectory inside the data + directory by default. +- For existing nodes (where the data directory already exists), wallets will be + stored in the data directory root by default. If a `wallets/` subdirectory + already exists in the data directory root, then wallets will be stored in the + `wallets/` subdirectory by default. +- The location of the wallets directory can be overridden by specifying a + `-walletdir=<path>` option where `<path>` can be an absolute path to a + directory or directory symlink. + +Care should be taken when choosing the wallets directory location, as if it +becomes unavailable during operation, funds may be lost. + Low-level RPC changes ---------------------- - The deprecated RPC `getinfo` was removed. It is recommended that the more specific RPCs are used: @@ -70,7 +104,22 @@ Low-level RPC changes * `getwalletinfo` * `getmininginfo` - The wallet RPC `getreceivedbyaddress` will return an error if called with an address not in the wallet. +- The wallet RPC `addwitnessaddress` was deprecated and will be removed in version 0.17, + set the `address_type` argument of `getnewaddress`, or option `-addresstype=[bech32|p2sh-segwit]` instead. + +Changed command-line options +----------------------------- +- `-debuglogfile=<file>` can be used to specify an alternative debug logging file. + +Renamed script for creating JSON-RPC credentials +----------------------------- +The `share/rpcuser/rpcuser.py` script was renamed to `share/rpcauth/rpcauth.py`. This script can be +used to create `rpcauth` credentials for a JSON-RPC user. + +- `dumpwallet` now includes hex-encoded scripts from the wallet in the dumpfile, and + `importwallet` now imports these scripts, but corresponding addresses may not be added + correctly or a manual rescan may be required to find relevant transactions. Credits ======= diff --git a/doc/release-notes/release-notes-0.15.0.md b/doc/release-notes/release-notes-0.15.0.md index 29816cacf7..3d000e94d5 100644 --- a/doc/release-notes/release-notes-0.15.0.md +++ b/doc/release-notes/release-notes-0.15.0.md @@ -151,8 +151,8 @@ Multi-wallet is enabled by using more than one `-wallet` argument when starting Bitcoin Core 0.15.0 contains the following changes to the RPC interface and `bitcoin-cli` for multi-wallet: * When running Bitcoin Core with a single wallet, there are **no** changes to the RPC interface or `bitcoin-cli`. All RPC calls and `bitcoin-cli` commands continue to work as before. -* When running Bitcoin Core with multi-wallet, all *node-level* RPC methods continue to work as before. HTTP RPC requests should be send to the normal `<RPC IP address>:<RPC port>/` endpoint, and `bitcoin-cli` commands should be run as before. A *node-level* RPC method is any method which does not require access to the wallet. -* When running Bitcoin Core with multi-wallet, *wallet-level* RPC methods must specify the wallet for which they're intended in every request. HTTP RPC requests should be send to the `<RPC IP address>:<RPC port>/wallet/<wallet name>/` endpoint, for example `127.0.0.1:8332/wallet/wallet1.dat/`. `bitcoin-cli` commands should be run with a `-rpcwallet` option, for example `bitcoin-cli -rpcwallet=wallet1.dat getbalance`. +* When running Bitcoin Core with multi-wallet, all *node-level* RPC methods continue to work as before. HTTP RPC requests should be send to the normal `<RPC IP address>:<RPC port>` endpoint, and `bitcoin-cli` commands should be run as before. A *node-level* RPC method is any method which does not require access to the wallet. +* When running Bitcoin Core with multi-wallet, *wallet-level* RPC methods must specify the wallet for which they're intended in every request. HTTP RPC requests should be send to the `<RPC IP address>:<RPC port>/wallet/<wallet name>` endpoint, for example `127.0.0.1:8332/wallet/wallet1.dat`. `bitcoin-cli` commands should be run with a `-rpcwallet` option, for example `bitcoin-cli -rpcwallet=wallet1.dat getbalance`. * A new *node-level* `listwallets` RPC method is added to display which wallets are currently loaded. The names returned by this method are the same as those used in the HTTP endpoint and for the `rpcwallet` argument. Note that while multi-wallet is now fully supported, the RPC multi-wallet interface should be considered unstable for version 0.15.0, and there may backwards-incompatible changes in future versions. diff --git a/share/genbuild.sh b/share/genbuild.sh index 32ef2a5755..419e0da0fd 100755 --- a/share/genbuild.sh +++ b/share/genbuild.sh @@ -4,7 +4,7 @@ # file COPYING or http://www.opensource.org/licenses/mit-license.php. if [ $# -gt 1 ]; then - cd "$2" + cd "$2" || exit 1 fi if [ $# -gt 0 ]; then FILE="$1" diff --git a/share/qt/extract_strings_qt.py b/share/qt/extract_strings_qt.py index e3be18205d..fbf3ea3436 100755 --- a/share/qt/extract_strings_qt.py +++ b/share/qt/extract_strings_qt.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# Copyright (c) 2012-2016 The Bitcoin Core developers +# Copyright (c) 2012-2017 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. ''' diff --git a/share/rpcauth/README.md b/share/rpcauth/README.md new file mode 100644 index 0000000000..389278a125 --- /dev/null +++ b/share/rpcauth/README.md @@ -0,0 +1,10 @@ +RPC Tools +--------------------- + +### [RPCAuth](/share/rpcauth) ### + +Create login credentials for a JSON-RPC user. + +Usage: + + ./rpcauth.py <username> diff --git a/share/rpcuser/rpcuser.py b/share/rpcauth/rpcauth.py index 63c69e308a..7baad85582 100755 --- a/share/rpcuser/rpcuser.py +++ b/share/rpcauth/rpcauth.py @@ -1,5 +1,5 @@ -#!/usr/bin/env python2 -# Copyright (c) 2015-2016 The Bitcoin Core developers +#!/usr/bin/env python +# Copyright (c) 2015-2017 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/share/rpcuser/README.md b/share/rpcuser/README.md deleted file mode 100644 index 12a8e6fb0c..0000000000 --- a/share/rpcuser/README.md +++ /dev/null @@ -1,10 +0,0 @@ -RPC Tools ---------------------- - -### [RPCUser](/share/rpcuser) ### - -Create an RPC user login credential. - -Usage: - - ./rpcuser.py <username> diff --git a/src/Makefile.am b/src/Makefile.am index 29e4ae56d0..4fbd605d9e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -133,6 +133,7 @@ BITCOIN_CORE_H = \ rpc/safemode.h \ rpc/server.h \ rpc/register.h \ + rpc/util.h \ scheduler.h \ script/sigcache.h \ script/sign.h \ @@ -168,6 +169,7 @@ BITCOIN_CORE_H = \ wallet/rpcwallet.h \ wallet/wallet.h \ wallet/walletdb.h \ + wallet/walletutil.h \ warnings.h \ zmq/zmqabstractnotifier.h \ zmq/zmqconfig.h\ @@ -249,6 +251,7 @@ libbitcoin_wallet_a_SOURCES = \ wallet/rpcwallet.cpp \ wallet/wallet.cpp \ wallet/walletdb.cpp \ + wallet/walletutil.cpp \ $(BITCOIN_CORE_H) # crypto primitives library @@ -350,6 +353,7 @@ libbitcoin_util_a_SOURCES = \ fs.cpp \ random.cpp \ rpc/protocol.cpp \ + rpc/util.cpp \ support/cleanse.cpp \ sync.cpp \ threadinterrupt.cpp \ diff --git a/src/Makefile.test.include b/src/Makefile.test.include index f037705aaf..d4d972b2bb 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -33,6 +33,7 @@ BITCOIN_TESTS =\ test/base64_tests.cpp \ test/bech32_tests.cpp \ test/bip32_tests.cpp \ + test/blockchain_tests.cpp \ test/blockencodings_tests.cpp \ test/bloom_tests.cpp \ test/bswap_tests.cpp \ @@ -80,10 +81,10 @@ BITCOIN_TESTS =\ test/timedata_tests.cpp \ test/torcontrol_tests.cpp \ test/transaction_tests.cpp \ + test/txvalidation_tests.cpp \ test/txvalidationcache_tests.cpp \ test/versionbits_tests.cpp \ test/uint256_tests.cpp \ - test/univalue_tests.cpp \ test/util_tests.cpp if ENABLE_WALLET diff --git a/src/addrdb.cpp b/src/addrdb.cpp index 0f9ccf1e9a..675f3c28af 100644 --- a/src/addrdb.cpp +++ b/src/addrdb.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -8,7 +8,6 @@ #include <addrman.h> #include <chainparams.h> #include <clientversion.h> -#include <fs.h> #include <hash.h> #include <random.h> #include <streams.h> diff --git a/src/addrdb.h b/src/addrdb.h index 098da4240e..e39bd6f5ae 100644 --- a/src/addrdb.h +++ b/src/addrdb.h @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/addrman.cpp b/src/addrman.cpp index ddcdf4c2f4..9eefffb45b 100644 --- a/src/addrman.cpp +++ b/src/addrman.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2012 Pieter Wuille -// Copyright (c) 2012-2016 The Bitcoin Core developers +// Copyright (c) 2012-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -387,12 +387,12 @@ int CAddrMan::Check_() std::set<int> setTried; std::map<int, int> mapNew; - if (vRandom.size() != nTried + nNew) + if (vRandom.size() != (size_t)(nTried + nNew)) return -7; - for (std::map<int, CAddrInfo>::iterator it = mapInfo.begin(); it != mapInfo.end(); it++) { - int n = (*it).first; - CAddrInfo& info = (*it).second; + for (const auto& entry : mapInfo) { + int n = entry.first; + const CAddrInfo& info = entry.second; if (info.fInTried) { if (!info.nLastSuccess) return -1; @@ -408,7 +408,7 @@ int CAddrMan::Check_() } if (mapAddr[info] != n) return -5; - if (info.nRandomPos < 0 || info.nRandomPos >= vRandom.size() || vRandom[info.nRandomPos] != n) + if (info.nRandomPos < 0 || (size_t)info.nRandomPos >= vRandom.size() || vRandom[info.nRandomPos] != n) return -14; if (info.nLastTry < 0) return -6; @@ -416,9 +416,9 @@ int CAddrMan::Check_() return -8; } - if (setTried.size() != nTried) + if (setTried.size() != (size_t)nTried) return -9; - if (mapNew.size() != nNew) + if (mapNew.size() != (size_t)nNew) return -10; for (int n = 0; n < ADDRMAN_TRIED_BUCKET_COUNT; n++) { diff --git a/src/addrman.h b/src/addrman.h index b06b272962..172cb5f45b 100644 --- a/src/addrman.h +++ b/src/addrman.h @@ -1,5 +1,5 @@ // Copyright (c) 2012 Pieter Wuille -// Copyright (c) 2012-2016 The Bitcoin Core developers +// Copyright (c) 2012-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -313,9 +313,9 @@ public: s << nUBuckets; std::map<int, int> mapUnkIds; int nIds = 0; - for (std::map<int, CAddrInfo>::const_iterator it = mapInfo.begin(); it != mapInfo.end(); it++) { - mapUnkIds[(*it).first] = nIds; - const CAddrInfo &info = (*it).second; + for (const auto& entry : mapInfo) { + mapUnkIds[entry.first] = nIds; + const CAddrInfo &info = entry.second; if (info.nRefCount) { assert(nIds != nNew); // this means nNew was wrong, oh ow s << info; @@ -323,8 +323,8 @@ public: } } nIds = 0; - for (std::map<int, CAddrInfo>::const_iterator it = mapInfo.begin(); it != mapInfo.end(); it++) { - const CAddrInfo &info = (*it).second; + for (const auto& entry : mapInfo) { + const CAddrInfo &info = entry.second; if (info.fInTried) { assert(nIds != nTried); // this means nTried was wrong, oh ow s << info; diff --git a/src/arith_uint256.cpp b/src/arith_uint256.cpp index 738224fb70..65de632306 100644 --- a/src/arith_uint256.cpp +++ b/src/arith_uint256.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/arith_uint256.h b/src/arith_uint256.h index 1009fe1cc8..dc2627592e 100644 --- a/src/arith_uint256.h +++ b/src/arith_uint256.h @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/base58.cpp b/src/base58.cpp index cd087e7997..499afbe382 100644 --- a/src/base58.cpp +++ b/src/base58.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2016 The Bitcoin Core developers +// Copyright (c) 2014-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/base58.h b/src/base58.h index fee79f02bf..39eb4eacc2 100644 --- a/src/base58.h +++ b/src/base58.h @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2015 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/bench/Examples.cpp b/src/bench/Examples.cpp index 536e450940..b68c9cd156 100644 --- a/src/bench/Examples.cpp +++ b/src/bench/Examples.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2016 The Bitcoin Core developers +// Copyright (c) 2015-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -15,7 +15,7 @@ static void Sleep100ms(benchmark::State& state) } } -BENCHMARK(Sleep100ms); +BENCHMARK(Sleep100ms, 10); // Extremely fast-running benchmark: #include <math.h> @@ -31,4 +31,4 @@ static void Trig(benchmark::State& state) } } -BENCHMARK(Trig); +BENCHMARK(Trig, 12 * 1000 * 1000); diff --git a/src/bench/base58.cpp b/src/bench/base58.cpp index 8f6d07ac16..70bfd7d0bf 100644 --- a/src/bench/base58.cpp +++ b/src/bench/base58.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2016 The Bitcoin Core developers +// Copyright (c) 2016-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -22,7 +22,7 @@ static void Base58Encode(benchmark::State& state) } }; while (state.KeepRunning()) { - EncodeBase58(buff.begin(), buff.end()); + EncodeBase58(buff.data(), buff.data() + buff.size()); } } @@ -54,6 +54,6 @@ static void Base58Decode(benchmark::State& state) } -BENCHMARK(Base58Encode); -BENCHMARK(Base58CheckEncode); -BENCHMARK(Base58Decode); +BENCHMARK(Base58Encode, 470 * 1000); +BENCHMARK(Base58CheckEncode, 320 * 1000); +BENCHMARK(Base58Decode, 800 * 1000); diff --git a/src/bench/bench.cpp b/src/bench/bench.cpp index 1482452814..21329a5151 100644 --- a/src/bench/bench.cpp +++ b/src/bench/bench.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2016 The Bitcoin Core developers +// Copyright (c) 2015-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -8,98 +8,139 @@ #include <assert.h> #include <iostream> #include <iomanip> +#include <algorithm> +#include <regex> +#include <numeric> -benchmark::BenchRunner::BenchmarkMap &benchmark::BenchRunner::benchmarks() { - static std::map<std::string, benchmark::BenchFunction> benchmarks_map; - return benchmarks_map; +void benchmark::ConsolePrinter::header() +{ + std::cout << "# Benchmark, evals, iterations, total, min, max, median" << std::endl; } -benchmark::BenchRunner::BenchRunner(std::string name, benchmark::BenchFunction func) +void benchmark::ConsolePrinter::result(const State& state) { - benchmarks().insert(std::make_pair(name, func)); + auto results = state.m_elapsed_results; + std::sort(results.begin(), results.end()); + + double total = state.m_num_iters * std::accumulate(results.begin(), results.end(), 0.0); + + double front = 0; + double back = 0; + double median = 0; + + if (!results.empty()) { + front = results.front(); + back = results.back(); + + size_t mid = results.size() / 2; + median = results[mid]; + if (0 == results.size() % 2) { + median = (results[mid] + results[mid + 1]) / 2; + } + } + + std::cout << std::setprecision(6); + std::cout << state.m_name << ", " << state.m_num_evals << ", " << state.m_num_iters << ", " << total << ", " << front << ", " << back << ", " << median << std::endl; } -void -benchmark::BenchRunner::RunAll(benchmark::duration elapsedTimeForOne) +void benchmark::ConsolePrinter::footer() {} +benchmark::PlotlyPrinter::PlotlyPrinter(std::string plotly_url, int64_t width, int64_t height) + : m_plotly_url(plotly_url), m_width(width), m_height(height) { - perf_init(); - if (std::ratio_less_equal<benchmark::clock::period, std::micro>::value) { - std::cerr << "WARNING: Clock precision is worse than microsecond - benchmarks may be less accurate!\n"; - } - std::cout << "#Benchmark" << "," << "count" << "," << "min(ns)" << "," << "max(ns)" << "," << "average(ns)" << "," - << "min_cycles" << "," << "max_cycles" << "," << "average_cycles" << "\n"; +} - for (const auto &p: benchmarks()) { - State state(p.first, elapsedTimeForOne); - p.second(state); - } - perf_fini(); +void benchmark::PlotlyPrinter::header() +{ + std::cout << "<html><head>" + << "<script src=\"" << m_plotly_url << "\"></script>" + << "</head><body><div id=\"myDiv\" style=\"width:" << m_width << "px; height:" << m_height << "px\"></div>" + << "<script> var data = [" + << std::endl; } -bool benchmark::State::KeepRunning() +void benchmark::PlotlyPrinter::result(const State& state) { - if (count & countMask) { - ++count; - return true; + std::cout << "{ " << std::endl + << " name: '" << state.m_name << "', " << std::endl + << " y: ["; + + const char* prefix = ""; + for (const auto& e : state.m_elapsed_results) { + std::cout << prefix << std::setprecision(6) << e; + prefix = ", "; } - time_point now; + std::cout << "]," << std::endl + << " boxpoints: 'all', jitter: 0.3, pointpos: 0, type: 'box'," + << std::endl + << "}," << std::endl; +} + +void benchmark::PlotlyPrinter::footer() +{ + std::cout << "]; var layout = { showlegend: false, yaxis: { rangemode: 'tozero', autorange: true } };" + << "Plotly.newPlot('myDiv', data, layout);" + << "</script></body></html>"; +} - uint64_t nowCycles; - if (count == 0) { - lastTime = beginTime = now = clock::now(); - lastCycles = beginCycles = nowCycles = perf_cpucycles(); + +benchmark::BenchRunner::BenchmarkMap& benchmark::BenchRunner::benchmarks() +{ + static std::map<std::string, Bench> benchmarks_map; + return benchmarks_map; +} + +benchmark::BenchRunner::BenchRunner(std::string name, benchmark::BenchFunction func, uint64_t num_iters_for_one_second) +{ + benchmarks().insert(std::make_pair(name, Bench{func, num_iters_for_one_second})); +} + +void benchmark::BenchRunner::RunAll(Printer& printer, uint64_t num_evals, double scaling, const std::string& filter, bool is_list_only) +{ + perf_init(); + if (!std::ratio_less_equal<benchmark::clock::period, std::micro>::value) { + std::cerr << "WARNING: Clock precision is worse than microsecond - benchmarks may be less accurate!\n"; } - else { - now = clock::now(); - auto elapsed = now - lastTime; - auto elapsedOne = elapsed / (countMask + 1); - if (elapsedOne < minTime) minTime = elapsedOne; - if (elapsedOne > maxTime) maxTime = elapsedOne; - - // We only use relative values, so don't have to handle 64-bit wrap-around specially - nowCycles = perf_cpucycles(); - uint64_t elapsedOneCycles = (nowCycles - lastCycles) / (countMask + 1); - if (elapsedOneCycles < minCycles) minCycles = elapsedOneCycles; - if (elapsedOneCycles > maxCycles) maxCycles = elapsedOneCycles; - - if (elapsed*128 < maxElapsed) { - // If the execution was much too fast (1/128th of maxElapsed), increase the count mask by 8x and restart timing. - // The restart avoids including the overhead of this code in the measurement. - countMask = ((countMask<<3)|7) & ((1LL<<60)-1); - count = 0; - minTime = duration::max(); - maxTime = duration::zero(); - minCycles = std::numeric_limits<uint64_t>::max(); - maxCycles = std::numeric_limits<uint64_t>::min(); - return true; +#ifdef DEBUG + std::cerr << "WARNING: This is a debug build - may result in slower benchmarks.\n"; +#endif + + std::regex reFilter(filter); + std::smatch baseMatch; + + printer.header(); + + for (const auto& p : benchmarks()) { + if (!std::regex_match(p.first, baseMatch, reFilter)) { + continue; + } + + uint64_t num_iters = static_cast<uint64_t>(p.second.num_iters_for_one_second * scaling); + if (0 == num_iters) { + num_iters = 1; } - if (elapsed*16 < maxElapsed) { - uint64_t newCountMask = ((countMask<<1)|1) & ((1LL<<60)-1); - if ((count & newCountMask)==0) { - countMask = newCountMask; - } + State state(p.first, num_evals, num_iters, printer); + if (!is_list_only) { + p.second.func(state); } + printer.result(state); } - lastTime = now; - lastCycles = nowCycles; - ++count; - if (now - beginTime < maxElapsed) return true; // Keep going + printer.footer(); - --count; + perf_fini(); +} - assert(count != 0 && "count == 0 => (now == 0 && beginTime == 0) => return above"); +bool benchmark::State::UpdateTimer(const benchmark::time_point current_time) +{ + if (m_start_time != time_point()) { + std::chrono::duration<double> diff = current_time - m_start_time; + m_elapsed_results.push_back(diff.count() / m_num_iters); - // Output results - // Duration casts are only necessary here because hardware with sub-nanosecond clocks - // will lose precision. - int64_t min_elapsed = std::chrono::duration_cast<std::chrono::nanoseconds>(minTime).count(); - int64_t max_elapsed = std::chrono::duration_cast<std::chrono::nanoseconds>(maxTime).count(); - int64_t avg_elapsed = std::chrono::duration_cast<std::chrono::nanoseconds>((now-beginTime)/count).count(); - int64_t averageCycles = (nowCycles-beginCycles)/count; - std::cout << std::fixed << std::setprecision(15) << name << "," << count << "," << min_elapsed << "," << max_elapsed << "," << avg_elapsed << "," - << minCycles << "," << maxCycles << "," << averageCycles << "\n"; - std::cout.copyfmt(std::ios(nullptr)); + if (m_elapsed_results.size() == m_num_evals) { + return false; + } + } - return false; + m_num_iters_left = m_num_iters - 1; + return true; } diff --git a/src/bench/bench.h b/src/bench/bench.h index 071a5dc9c7..e15cb81869 100644 --- a/src/bench/bench.h +++ b/src/bench/bench.h @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2016 The Bitcoin Core developers +// Copyright (c) 2015-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -9,6 +9,7 @@ #include <limits> #include <map> #include <string> +#include <vector> #include <chrono> #include <boost/preprocessor/cat.hpp> @@ -32,64 +33,110 @@ static void CODE_TO_TIME(benchmark::State& state) ... do any cleanup needed... } -BENCHMARK(CODE_TO_TIME); +// default to running benchmark for 5000 iterations +BENCHMARK(CODE_TO_TIME, 5000); */ - + namespace benchmark { - // In case high_resolution_clock is steady, prefer that, otherwise use steady_clock. - struct best_clock { - using hi_res_clock = std::chrono::high_resolution_clock; - using steady_clock = std::chrono::steady_clock; - using type = std::conditional<hi_res_clock::is_steady, hi_res_clock, steady_clock>::type; - }; - using clock = best_clock::type; - using time_point = clock::time_point; - using duration = clock::duration; - - class State { - std::string name; - duration maxElapsed; - time_point beginTime, lastTime; - duration minTime, maxTime; - uint64_t count; - uint64_t countMask; - uint64_t beginCycles; - uint64_t lastCycles; - uint64_t minCycles; - uint64_t maxCycles; - public: - State(std::string _name, duration _maxElapsed) : - name(_name), - maxElapsed(_maxElapsed), - minTime(duration::max()), - maxTime(duration::zero()), - count(0), - countMask(1), - beginCycles(0), - lastCycles(0), - minCycles(std::numeric_limits<uint64_t>::max()), - maxCycles(std::numeric_limits<uint64_t>::min()) { - } - bool KeepRunning(); - }; +// In case high_resolution_clock is steady, prefer that, otherwise use steady_clock. +struct best_clock { + using hi_res_clock = std::chrono::high_resolution_clock; + using steady_clock = std::chrono::steady_clock; + using type = std::conditional<hi_res_clock::is_steady, hi_res_clock, steady_clock>::type; +}; +using clock = best_clock::type; +using time_point = clock::time_point; +using duration = clock::duration; + +class Printer; + +class State +{ +public: + std::string m_name; + uint64_t m_num_iters_left; + const uint64_t m_num_iters; + const uint64_t m_num_evals; + std::vector<double> m_elapsed_results; + time_point m_start_time; + + bool UpdateTimer(time_point finish_time); - typedef std::function<void(State&)> BenchFunction; + State(std::string name, uint64_t num_evals, double num_iters, Printer& printer) : m_name(name), m_num_iters_left(0), m_num_iters(num_iters), m_num_evals(num_evals) + { + } - class BenchRunner + inline bool KeepRunning() { - typedef std::map<std::string, BenchFunction> BenchmarkMap; - static BenchmarkMap &benchmarks(); + if (m_num_iters_left--) { + return true; + } + + bool result = UpdateTimer(clock::now()); + // measure again so runtime of UpdateTimer is not included + m_start_time = clock::now(); + return result; + } +}; - public: - BenchRunner(std::string name, BenchFunction func); +typedef std::function<void(State&)> BenchFunction; - static void RunAll(duration elapsedTimeForOne = std::chrono::seconds(1)); +class BenchRunner +{ + struct Bench { + BenchFunction func; + uint64_t num_iters_for_one_second; }; + typedef std::map<std::string, Bench> BenchmarkMap; + static BenchmarkMap& benchmarks(); + +public: + BenchRunner(std::string name, BenchFunction func, uint64_t num_iters_for_one_second); + + static void RunAll(Printer& printer, uint64_t num_evals, double scaling, const std::string& filter, bool is_list_only); +}; + +// interface to output benchmark results. +class Printer +{ +public: + virtual ~Printer() {} + virtual void header() = 0; + virtual void result(const State& state) = 0; + virtual void footer() = 0; +}; + +// default printer to console, shows min, max, median. +class ConsolePrinter : public Printer +{ +public: + void header(); + void result(const State& state); + void footer(); +}; + +// creates box plot with plotly.js +class PlotlyPrinter : public Printer +{ +public: + PlotlyPrinter(std::string plotly_url, int64_t width, int64_t height); + void header(); + void result(const State& state); + void footer(); + +private: + std::string m_plotly_url; + int64_t m_width; + int64_t m_height; +}; } -// BENCHMARK(foo) expands to: benchmark::BenchRunner bench_11foo("foo", foo); -#define BENCHMARK(n) \ - benchmark::BenchRunner BOOST_PP_CAT(bench_, BOOST_PP_CAT(__LINE__, n))(BOOST_PP_STRINGIZE(n), n); + +// BENCHMARK(foo, num_iters_for_one_second) expands to: benchmark::BenchRunner bench_11foo("foo", num_iterations); +// Choose a num_iters_for_one_second that takes roughly 1 second. The goal is that all benchmarks should take approximately +// the same time, and scaling factor can be used that the total time is appropriate for your system. +#define BENCHMARK(n, num_iters_for_one_second) \ + benchmark::BenchRunner BOOST_PP_CAT(bench_, BOOST_PP_CAT(__LINE__, n))(BOOST_PP_STRINGIZE(n), n, (num_iters_for_one_second)); #endif // BITCOIN_BENCH_BENCH_H diff --git a/src/bench/bench_bitcoin.cpp b/src/bench/bench_bitcoin.cpp index 84e51d809a..fc92a46c0f 100644 --- a/src/bench/bench_bitcoin.cpp +++ b/src/bench/bench_bitcoin.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2016 The Bitcoin Core developers +// Copyright (c) 2015-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -10,16 +10,62 @@ #include <util.h> #include <random.h> +#include <boost/lexical_cast.hpp> + +#include <memory> + +static const int64_t DEFAULT_BENCH_EVALUATIONS = 5; +static const char* DEFAULT_BENCH_FILTER = ".*"; +static const char* DEFAULT_BENCH_SCALING = "1.0"; +static const char* DEFAULT_BENCH_PRINTER = "console"; +static const char* DEFAULT_PLOT_PLOTLYURL = "https://cdn.plot.ly/plotly-latest.min.js"; +static const int64_t DEFAULT_PLOT_WIDTH = 1024; +static const int64_t DEFAULT_PLOT_HEIGHT = 768; + int main(int argc, char** argv) { + gArgs.ParseParameters(argc, argv); + + if (gArgs.IsArgSet("-?") || gArgs.IsArgSet("-h") || gArgs.IsArgSet("-help")) { + std::cout << HelpMessageGroup(_("Options:")) + << HelpMessageOpt("-?", _("Print this help message and exit")) + << HelpMessageOpt("-list", _("List benchmarks without executing them. Can be combined with -scaling and -filter")) + << HelpMessageOpt("-evals=<n>", strprintf(_("Number of measurement evaluations to perform. (default: %u)"), DEFAULT_BENCH_EVALUATIONS)) + << HelpMessageOpt("-filter=<regex>", strprintf(_("Regular expression filter to select benchmark by name (default: %s)"), DEFAULT_BENCH_FILTER)) + << HelpMessageOpt("-scaling=<n>", strprintf(_("Scaling factor for benchmark's runtime (default: %u)"), DEFAULT_BENCH_SCALING)) + << HelpMessageOpt("-printer=(console|plot)", strprintf(_("Choose printer format. console: print data to console. plot: Print results as HTML graph (default: %s)"), DEFAULT_BENCH_PRINTER)) + << HelpMessageOpt("-plot-plotlyurl=<uri>", strprintf(_("URL to use for plotly.js (default: %s)"), DEFAULT_PLOT_PLOTLYURL)) + << HelpMessageOpt("-plot-width=<x>", strprintf(_("Plot width in pixel (default: %u)"), DEFAULT_PLOT_WIDTH)) + << HelpMessageOpt("-plot-height=<x>", strprintf(_("Plot height in pixel (default: %u)"), DEFAULT_PLOT_HEIGHT)); + + return 0; + } + SHA256AutoDetect(); RandomInit(); ECC_Start(); SetupEnvironment(); fPrintToDebugLog = false; // don't want to write to debug.log file - benchmark::BenchRunner::RunAll(); + int64_t evaluations = gArgs.GetArg("-evals", DEFAULT_BENCH_EVALUATIONS); + std::string regex_filter = gArgs.GetArg("-filter", DEFAULT_BENCH_FILTER); + std::string scaling_str = gArgs.GetArg("-scaling", DEFAULT_BENCH_SCALING); + bool is_list_only = gArgs.GetBoolArg("-list", false); + + double scaling_factor = boost::lexical_cast<double>(scaling_str); + + + std::unique_ptr<benchmark::Printer> printer(new benchmark::ConsolePrinter()); + std::string printer_arg = gArgs.GetArg("-printer", DEFAULT_BENCH_PRINTER); + if ("plot" == printer_arg) { + printer.reset(new benchmark::PlotlyPrinter( + gArgs.GetArg("-plot-plotlyurl", DEFAULT_PLOT_PLOTLYURL), + gArgs.GetArg("-plot-width", DEFAULT_PLOT_WIDTH), + gArgs.GetArg("-plot-height", DEFAULT_PLOT_HEIGHT))); + } + + benchmark::BenchRunner::RunAll(*printer, evaluations, scaling_factor, regex_filter, is_list_only); ECC_Stop(); } diff --git a/src/bench/ccoins_caching.cpp b/src/bench/ccoins_caching.cpp index 89ba3d3d21..74169bcad7 100644 --- a/src/bench/ccoins_caching.cpp +++ b/src/bench/ccoins_caching.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2016 The Bitcoin Core developers +// Copyright (c) 2016-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -84,4 +84,4 @@ static void CCoinsCaching(benchmark::State& state) } } -BENCHMARK(CCoinsCaching); +BENCHMARK(CCoinsCaching, 170 * 1000); diff --git a/src/bench/checkblock.cpp b/src/bench/checkblock.cpp index 9533b3c711..fac7e079a7 100644 --- a/src/bench/checkblock.cpp +++ b/src/bench/checkblock.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2016 The Bitcoin Core developers +// Copyright (c) 2016-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -52,5 +52,5 @@ static void DeserializeAndCheckBlockTest(benchmark::State& state) } } -BENCHMARK(DeserializeBlockTest); -BENCHMARK(DeserializeAndCheckBlockTest); +BENCHMARK(DeserializeBlockTest, 130); +BENCHMARK(DeserializeAndCheckBlockTest, 160); diff --git a/src/bench/checkqueue.cpp b/src/bench/checkqueue.cpp index 7e63e820db..6e816f1bec 100644 --- a/src/bench/checkqueue.cpp +++ b/src/bench/checkqueue.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2015 The Bitcoin Core developers +// Copyright (c) 2015-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -12,51 +12,11 @@ #include <random.h> -// This Benchmark tests the CheckQueue with the lightest -// weight Checks, so it should make any lock contention -// particularly visible static const int MIN_CORES = 2; static const size_t BATCHES = 101; static const size_t BATCH_SIZE = 30; static const int PREVECTOR_SIZE = 28; -static const int QUEUE_BATCH_SIZE = 128; -static void CCheckQueueSpeed(benchmark::State& state) -{ - struct FakeJobNoWork { - bool operator()() - { - return true; - } - void swap(FakeJobNoWork& x){}; - }; - CCheckQueue<FakeJobNoWork> queue {QUEUE_BATCH_SIZE}; - boost::thread_group tg; - for (auto x = 0; x < std::max(MIN_CORES, GetNumCores()); ++x) { - tg.create_thread([&]{queue.Thread();}); - } - while (state.KeepRunning()) { - CCheckQueueControl<FakeJobNoWork> control(&queue); - - // We call Add a number of times to simulate the behavior of adding - // a block of transactions at once. - - std::vector<std::vector<FakeJobNoWork>> vBatches(BATCHES); - for (auto& vChecks : vBatches) { - vChecks.resize(BATCH_SIZE); - } - for (auto& vChecks : vBatches) { - // We can't make vChecks in the inner loop because we want to measure - // the cost of getting the memory to each thread and we might get the same - // memory - control.Add(vChecks); - } - // control waits for completion by RAII, but - // it is done explicitly here for clarity - control.Wait(); - } - tg.interrupt_all(); - tg.join_all(); -} +static const unsigned int QUEUE_BATCH_SIZE = 128; // This Benchmark tests the CheckQueue with a slightly realistic workload, // where checks all contain a prevector that is indirect 50% of the time @@ -99,5 +59,4 @@ static void CCheckQueueSpeedPrevectorJob(benchmark::State& state) tg.interrupt_all(); tg.join_all(); } -BENCHMARK(CCheckQueueSpeed); -BENCHMARK(CCheckQueueSpeedPrevectorJob); +BENCHMARK(CCheckQueueSpeedPrevectorJob, 1400); diff --git a/src/bench/coin_selection.cpp b/src/bench/coin_selection.cpp index ff57f88170..06d2abeac6 100644 --- a/src/bench/coin_selection.cpp +++ b/src/bench/coin_selection.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2016 The Bitcoin Core developers +// Copyright (c) 2012-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -56,4 +56,4 @@ static void CoinSelection(benchmark::State& state) } } -BENCHMARK(CoinSelection); +BENCHMARK(CoinSelection, 650); diff --git a/src/bench/crypto_hash.cpp b/src/bench/crypto_hash.cpp index b37b5cad62..adb69bc6c3 100644 --- a/src/bench/crypto_hash.cpp +++ b/src/bench/crypto_hash.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2016 The Bitcoin Core developers +// Copyright (c) 2016-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -46,9 +46,9 @@ static void SHA256_32b(benchmark::State& state) { std::vector<uint8_t> in(32,0); while (state.KeepRunning()) { - for (int i = 0; i < 1000000; i++) { - CSHA256().Write(in.data(), in.size()).Finalize(in.data()); - } + CSHA256() + .Write(in.data(), in.size()) + .Finalize(in.data()); } } @@ -63,10 +63,9 @@ static void SHA512(benchmark::State& state) static void SipHash_32b(benchmark::State& state) { uint256 x; + uint64_t k1 = 0; while (state.KeepRunning()) { - for (int i = 0; i < 1000000; i++) { - *((uint64_t*)x.begin()) = SipHashUint256(0, i, x); - } + *((uint64_t*)x.begin()) = SipHashUint256(0, ++k1, x); } } @@ -75,9 +74,7 @@ static void FastRandom_32bit(benchmark::State& state) FastRandomContext rng(true); uint32_t x = 0; while (state.KeepRunning()) { - for (int i = 0; i < 1000000; i++) { - x += rng.rand32(); - } + x += rng.rand32(); } } @@ -86,18 +83,16 @@ static void FastRandom_1bit(benchmark::State& state) FastRandomContext rng(true); uint32_t x = 0; while (state.KeepRunning()) { - for (int i = 0; i < 1000000; i++) { - x += rng.randbool(); - } + x += rng.randbool(); } } -BENCHMARK(RIPEMD160); -BENCHMARK(SHA1); -BENCHMARK(SHA256); -BENCHMARK(SHA512); +BENCHMARK(RIPEMD160, 440); +BENCHMARK(SHA1, 570); +BENCHMARK(SHA256, 340); +BENCHMARK(SHA512, 330); -BENCHMARK(SHA256_32b); -BENCHMARK(SipHash_32b); -BENCHMARK(FastRandom_32bit); -BENCHMARK(FastRandom_1bit); +BENCHMARK(SHA256_32b, 4700 * 1000); +BENCHMARK(SipHash_32b, 40 * 1000 * 1000); +BENCHMARK(FastRandom_32bit, 110 * 1000 * 1000); +BENCHMARK(FastRandom_1bit, 440 * 1000 * 1000); diff --git a/src/bench/lockedpool.cpp b/src/bench/lockedpool.cpp index b0bfa95144..ca30d81e59 100644 --- a/src/bench/lockedpool.cpp +++ b/src/bench/lockedpool.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2016 The Bitcoin Core developers +// Copyright (c) 2016-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -43,5 +43,4 @@ static void BenchLockedPool(benchmark::State& state) addr.clear(); } -BENCHMARK(BenchLockedPool); - +BENCHMARK(BenchLockedPool, 530); diff --git a/src/bench/mempool_eviction.cpp b/src/bench/mempool_eviction.cpp index eda6edbb23..cdda0bd9be 100644 --- a/src/bench/mempool_eviction.cpp +++ b/src/bench/mempool_eviction.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -111,4 +111,4 @@ static void MempoolEviction(benchmark::State& state) } } -BENCHMARK(MempoolEviction); +BENCHMARK(MempoolEviction, 41000); diff --git a/src/bench/perf.cpp b/src/bench/perf.cpp index 4045670a31..f92d08c56e 100644 --- a/src/bench/perf.cpp +++ b/src/bench/perf.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2016 The Bitcoin Core developers +// Copyright (c) 2016-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/bench/prevector_destructor.cpp b/src/bench/prevector_destructor.cpp index de7ecab737..39d0ee5eb1 100644 --- a/src/bench/prevector_destructor.cpp +++ b/src/bench/prevector_destructor.cpp @@ -32,5 +32,5 @@ static void PrevectorClear(benchmark::State& state) } } -BENCHMARK(PrevectorDestructor); -BENCHMARK(PrevectorClear); +BENCHMARK(PrevectorDestructor, 5700); +BENCHMARK(PrevectorClear, 5600); diff --git a/src/bench/rollingbloom.cpp b/src/bench/rollingbloom.cpp index 452099b800..f7f72605d7 100644 --- a/src/bench/rollingbloom.cpp +++ b/src/bench/rollingbloom.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2016 The Bitcoin Core developers +// Copyright (c) 2016-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -12,8 +12,6 @@ static void RollingBloom(benchmark::State& state) CRollingBloomFilter filter(120000, 0.000001); std::vector<unsigned char> data(32); uint32_t count = 0; - uint32_t nEntriesPerGeneration = (120000 + 1) / 2; - uint32_t countnow = 0; uint64_t match = 0; while (state.KeepRunning()) { count++; @@ -21,16 +19,8 @@ static void RollingBloom(benchmark::State& state) data[1] = count >> 8; data[2] = count >> 16; data[3] = count >> 24; - if (countnow == nEntriesPerGeneration) { - auto b = benchmark::clock::now(); - filter.insert(data); - auto total = std::chrono::duration_cast<std::chrono::nanoseconds>(benchmark::clock::now() - b).count(); - std::cout << "RollingBloom-refresh,1," << total << "," << total << "," << total << "\n"; - countnow = 0; - } else { - filter.insert(data); - } - countnow++; + filter.insert(data); + data[0] = count >> 24; data[1] = count >> 16; data[2] = count >> 8; @@ -39,4 +29,4 @@ static void RollingBloom(benchmark::State& state) } } -BENCHMARK(RollingBloom); +BENCHMARK(RollingBloom, 1500 * 1000); diff --git a/src/bench/verify_script.cpp b/src/bench/verify_script.cpp index bfa5806c9d..29dedeef0b 100644 --- a/src/bench/verify_script.cpp +++ b/src/bench/verify_script.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2016 The Bitcoin Core developers +// Copyright (c) 2016-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -105,4 +105,4 @@ static void VerifyScriptBench(benchmark::State& state) } } -BENCHMARK(VerifyScriptBench); +BENCHMARK(VerifyScriptBench, 6300); diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp index 5e3b76a295..e9ef75eb7b 100644 --- a/src/bitcoin-cli.cpp +++ b/src/bitcoin-cli.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -213,6 +213,9 @@ public: /** Create a simulated `getinfo` request. */ UniValue PrepareRequest(const std::string& method, const std::vector<std::string>& args) override { + if (!args.empty()) { + throw std::runtime_error("-getinfo takes no arguments"); + } UniValue result(UniValue::VARR); result.push_back(JSONRPCRequestObj("getnetworkinfo", NullUniValue, ID_NETWORKINFO)); result.push_back(JSONRPCRequestObj("getblockchaininfo", NullUniValue, ID_BLOCKCHAININFO)); diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp index c9223dbf10..f1cf7c9d2d 100644 --- a/src/bitcoin-tx.cpp +++ b/src/bitcoin-tx.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -305,8 +305,8 @@ static void MutateTxAddOutPubKey(CMutableTransaction& tx, const std::string& str bool bScriptHash = false; if (vStrInputParts.size() == 3) { std::string flags = vStrInputParts[2]; - bSegWit = (flags.find("W") != std::string::npos); - bScriptHash = (flags.find("S") != std::string::npos); + bSegWit = (flags.find('W') != std::string::npos); + bScriptHash = (flags.find('S') != std::string::npos); } if (bSegWit) { @@ -367,8 +367,8 @@ static void MutateTxAddOutMultiSig(CMutableTransaction& tx, const std::string& s bool bScriptHash = false; if (vStrInputParts.size() == numkeys + 4) { std::string flags = vStrInputParts.back(); - bSegWit = (flags.find("W") != std::string::npos); - bScriptHash = (flags.find("S") != std::string::npos); + bSegWit = (flags.find('W') != std::string::npos); + bScriptHash = (flags.find('S') != std::string::npos); } else if (vStrInputParts.size() > numkeys + 4) { // Validate that there were no more parameters passed @@ -447,8 +447,8 @@ static void MutateTxAddOutScript(CMutableTransaction& tx, const std::string& str bool bScriptHash = false; if (vStrInputParts.size() == 3) { std::string flags = vStrInputParts.back(); - bSegWit = (flags.find("W") != std::string::npos); - bScriptHash = (flags.find("S") != std::string::npos); + bSegWit = (flags.find('W') != std::string::npos); + bScriptHash = (flags.find('S') != std::string::npos); } if (scriptPubKey.size() > MAX_SCRIPT_SIZE) { diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp index bc23912d2b..de19787a16 100644 --- a/src/bitcoind.cpp +++ b/src/bitcoind.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/blockencodings.cpp b/src/blockencodings.cpp index 6ff4d97bf4..391db0cfcb 100644 --- a/src/blockencodings.cpp +++ b/src/blockencodings.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2016 The Bitcoin Core developers +// Copyright (c) 2016-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/blockencodings.h b/src/blockencodings.h index d034bb3080..ba8c1d6a2a 100644 --- a/src/blockencodings.h +++ b/src/blockencodings.h @@ -1,4 +1,4 @@ -// Copyright (c) 2016 The Bitcoin Core developers +// Copyright (c) 2016-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/bloom.cpp b/src/bloom.cpp index 11ea099637..f07b5b6066 100644 --- a/src/bloom.cpp +++ b/src/bloom.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2016 The Bitcoin Core developers +// Copyright (c) 2012-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/bloom.h b/src/bloom.h index d29a8dcd6f..2f9d2109cd 100644 --- a/src/bloom.h +++ b/src/bloom.h @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2016 The Bitcoin Core developers +// Copyright (c) 2012-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/chain.cpp b/src/chain.cpp index 9f40c41fde..79e8bdfa44 100644 --- a/src/chain.cpp +++ b/src/chain.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -80,12 +80,13 @@ int static inline GetSkipHeight(int height) { return (height & 1) ? InvertLowestOne(InvertLowestOne(height - 1)) + 1 : InvertLowestOne(height); } -CBlockIndex* CBlockIndex::GetAncestor(int height) +const CBlockIndex* CBlockIndex::GetAncestor(int height) const { - if (height > nHeight || height < 0) + if (height > nHeight || height < 0) { return nullptr; + } - CBlockIndex* pindexWalk = this; + const CBlockIndex* pindexWalk = this; int heightWalk = nHeight; while (heightWalk > height) { int heightSkip = GetSkipHeight(heightWalk); @@ -106,9 +107,9 @@ CBlockIndex* CBlockIndex::GetAncestor(int height) return pindexWalk; } -const CBlockIndex* CBlockIndex::GetAncestor(int height) const +CBlockIndex* CBlockIndex::GetAncestor(int height) { - return const_cast<CBlockIndex*>(this)->GetAncestor(height); + return const_cast<CBlockIndex*>(static_cast<const CBlockIndex*>(this)->GetAncestor(height)); } void CBlockIndex::BuildSkip() diff --git a/src/chain.h b/src/chain.h index ca1900c22b..3728f768c4 100644 --- a/src/chain.h +++ b/src/chain.h @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/chainparams.cpp b/src/chainparams.cpp index e753c5ccff..96e9b2727b 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -102,10 +102,10 @@ public: consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nTimeout = 1510704000; // November 15th, 2017. // The best chain should have at least this much work. - consensus.nMinimumChainWork = uint256S("0x000000000000000000000000000000000000000000723d3581fe1bd55373540a"); + consensus.nMinimumChainWork = uint256S("0x000000000000000000000000000000000000000000f91c579d57cad4bc5278cc"); // By default assume that the signatures in ancestors of this block are valid. - consensus.defaultAssumeValid = uint256S("0x0000000000000000003b9ce759c2a087d52abc4266f8f4ebd6d768b89defa50a"); //477890 + consensus.defaultAssumeValid = uint256S("0x0000000000000000005214481d2d96f898e3d5416e43359c145944a909d242e0"); //506067 /** * The message start string is designed to be unlikely to occur in normal data. @@ -124,13 +124,17 @@ public: assert(consensus.hashGenesisBlock == uint256S("0x000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f")); assert(genesis.hashMerkleRoot == uint256S("0x4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b")); - // Note that of those with the service bits flag, most only support a subset of possible options - vSeeds.emplace_back("seed.bitcoin.sipa.be", true); // Pieter Wuille, only supports x1, x5, x9, and xd - vSeeds.emplace_back("dnsseed.bluematt.me", true); // Matt Corallo, only supports x9 - vSeeds.emplace_back("dnsseed.bitcoin.dashjr.org", false); // Luke Dashjr - vSeeds.emplace_back("seed.bitcoinstats.com", true); // Christian Decker, supports x1 - xf - vSeeds.emplace_back("seed.bitcoin.jonasschnelli.ch", true); // Jonas Schnelli, only supports x1, x5, x9, and xd - vSeeds.emplace_back("seed.btc.petertodd.org", true); // Peter Todd, only supports x1, x5, x9, and xd + // Note that of those which support the service bits prefix, most only support a subset of + // possible options. + // This is fine at runtime as we'll fall back to using them as a oneshot if they dont support the + // service bits we want, but we should get them updated to support all service bits wanted by any + // release ASAP to avoid it where possible. + vSeeds.emplace_back("seed.bitcoin.sipa.be"); // Pieter Wuille, only supports x1, x5, x9, and xd + vSeeds.emplace_back("dnsseed.bluematt.me"); // Matt Corallo, only supports x9 + vSeeds.emplace_back("dnsseed.bitcoin.dashjr.org"); // Luke Dashjr + vSeeds.emplace_back("seed.bitcoinstats.com"); // Christian Decker, supports x1 - xf + vSeeds.emplace_back("seed.bitcoin.jonasschnelli.ch"); // Jonas Schnelli, only supports x1, x5, x9, and xd + vSeeds.emplace_back("seed.btc.petertodd.org"); // Peter Todd, only supports x1, x5, x9, and xd base58Prefixes[PUBKEY_ADDRESS] = std::vector<unsigned char>(1,0); base58Prefixes[SCRIPT_ADDRESS] = std::vector<unsigned char>(1,5); @@ -146,7 +150,7 @@ public: fRequireStandard = true; fMineBlocksOnDemand = false; - checkpointData = (CCheckpointData) { + checkpointData = { { { 11111, uint256S("0x0000000069e244f73d78e8fd29ba2fd2ed618bd6fa2ee92559f542fdb26e7c1d")}, { 33333, uint256S("0x000000002dd5588a74784eaa7ab0507a18ad16a236e7b1ce69f00d7ddfb5d0a6")}, @@ -165,11 +169,11 @@ public: }; chainTxData = ChainTxData{ - // Data as of block 000000000000000000d97e53664d17967bd4ee50b23abb92e54a34eb222d15ae (height 478913). - 1501801925, // * UNIX timestamp of last known number of transactions - 243756039, // * total number of transactions between genesis and that timestamp + // Data as of block 0000000000000000002d6cca6761c99b3c2e936f9a0e304b7c7651a993f461de (height 506081). + 1516903077, // * UNIX timestamp of last known number of transactions + 295363220, // * total number of transactions between genesis and that timestamp // (the tx=... number in the SetBestChain debug.log lines) - 3.1 // * estimated number of transactions per second after that timestamp + 3.5 // * estimated number of transactions per second after that timestamp }; } }; @@ -229,9 +233,10 @@ public: vFixedSeeds.clear(); vSeeds.clear(); // nodes with support for servicebits filtering should be at the top - vSeeds.emplace_back("testnet-seed.bitcoin.jonasschnelli.ch", true); - vSeeds.emplace_back("seed.tbtc.petertodd.org", true); - vSeeds.emplace_back("testnet-seed.bluematt.me", false); + vSeeds.emplace_back("testnet-seed.bitcoin.jonasschnelli.ch"); + vSeeds.emplace_back("seed.tbtc.petertodd.org"); + vSeeds.emplace_back("seed.testnet.bitcoin.sprovoost.nl"); + vSeeds.emplace_back("testnet-seed.bluematt.me"); // Just a static list of stable node(s), only supports x9 base58Prefixes[PUBKEY_ADDRESS] = std::vector<unsigned char>(1,111); base58Prefixes[SCRIPT_ADDRESS] = std::vector<unsigned char>(1,196); @@ -248,17 +253,17 @@ public: fMineBlocksOnDemand = false; - checkpointData = (CCheckpointData) { + checkpointData = { { {546, uint256S("000000002a936ca763904c3c35fce2f3556c559c0214345d31b1bcebf76acb70")}, } }; chainTxData = ChainTxData{ - // Data as of block 00000000000001c200b9790dc637d3bb141fe77d155b966ed775b17e109f7c6c (height 1156179) - 1501802953, - 14706531, - 0.15 + // Data as of block 000000000000033cfa3c975eb83ecf2bb4aaedf68e6d279f6ed2b427c64caff9 (height 1260526) + 1516903490, + 17082348, + 0.09 }; } @@ -319,7 +324,7 @@ public: fRequireStandard = false; fMineBlocksOnDemand = true; - checkpointData = (CCheckpointData) { + checkpointData = { { {0, uint256S("0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206")}, } diff --git a/src/chainparams.h b/src/chainparams.h index 0d82a998b1..d478da9891 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -14,12 +14,6 @@ #include <memory> #include <vector> -struct CDNSSeedData { - std::string host; - bool supportsServiceBitsFiltering; - CDNSSeedData(const std::string &strHost, bool supportsServiceBitsFilteringIn) : host(strHost), supportsServiceBitsFiltering(supportsServiceBitsFilteringIn) {} -}; - struct SeedSpec6 { uint8_t addr[16]; uint16_t port; @@ -71,7 +65,8 @@ public: bool MineBlocksOnDemand() const { return fMineBlocksOnDemand; } /** Return the BIP70 network string (main, test or regtest) */ std::string NetworkIDString() const { return strNetworkID; } - const std::vector<CDNSSeedData>& DNSSeeds() const { return vSeeds; } + /** Return the list of hostnames to look up for DNS seeds */ + const std::vector<std::string>& DNSSeeds() const { return vSeeds; } const std::vector<unsigned char>& Base58Prefix(Base58Type type) const { return base58Prefixes[type]; } const std::string& Bech32HRP() const { return bech32_hrp; } const std::vector<SeedSpec6>& FixedSeeds() const { return vFixedSeeds; } @@ -85,7 +80,7 @@ protected: CMessageHeader::MessageStartChars pchMessageStart; int nDefaultPort; uint64_t nPruneAfterHeight; - std::vector<CDNSSeedData> vSeeds; + std::vector<std::string> vSeeds; std::vector<unsigned char> base58Prefixes[MAX_BASE58_TYPES]; std::string bech32_hrp; std::string strNetworkID; diff --git a/src/chainparamsbase.cpp b/src/chainparamsbase.cpp index a7e87faee3..a03137f407 100644 --- a/src/chainparamsbase.cpp +++ b/src/chainparamsbase.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2010 Satoshi Nakamoto -// Copyright (c) 2009-2015 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/chainparamsbase.h b/src/chainparamsbase.h index fc101f5b77..b4d2bb4f08 100644 --- a/src/chainparamsbase.h +++ b/src/chainparamsbase.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2015 The Bitcoin Core developers +// Copyright (c) 2014-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/chainparamsseeds.h b/src/chainparamsseeds.h index 2c99ca8ab0..2b102c464f 100644 --- a/src/chainparamsseeds.h +++ b/src/chainparamsseeds.h @@ -8,1005 +8,1089 @@ * IPv4 as well as onion addresses are wrapped inside a IPv6 address accordingly. */ static SeedSpec6 pnSeed6_main[] = { - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x02,0xe4,0x46,0xc6}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x04,0x0f,0xb4,0x1d}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x04,0x0f,0xb4,0x1e}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0x02,0x43,0x6e}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0x27,0xe0,0x67}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0x2b,0x7c,0x9a}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0xbd,0xa5,0x66}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0xe2,0x95,0x91}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0xe4,0x07,0x92}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0x13,0x05,0x7f}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0x1d,0x8b,0x78}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0x27,0x40,0x07}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0x27,0xae,0x74}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0x2d,0x45,0x0d}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0x2d,0x4b,0x0f}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0x2d,0x6c,0x6c}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0x65,0x8c,0xc2}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0x85,0x0d,0x38}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0xaf,0x18,0x07}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0xbd,0x85,0x82}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0xe4,0x40,0x47}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0xf9,0x98,0x65}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0xfe,0x7c,0x37}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0xff,0x40,0xe7}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0xff,0x5a,0xea}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x0d,0x50,0x43,0xa2}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x0e,0xc0,0x08,0x1b}, 21301}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x12,0x3e,0x03,0x56}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x12,0x55,0x23,0x50}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x17,0x1c,0x80,0x41}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x17,0x6c,0x53,0x0c}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x17,0xe9,0x02,0xee}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0x1b,0x41,0xa8}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0x38,0xf1,0xdb}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0x40,0x4b,0x84}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0x49,0x46,0x1a}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0x79,0x9a,0x8c}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0xcb,0x60,0x48}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x17,0x59,0xc1,0xc9}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x17,0x7d,0xe0,0x54}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x17,0xe1,0xa0,0x1a}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x17,0xe2,0xe7,0x7a}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x17,0xe3,0xcc,0x4e}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x17,0xee,0x84,0xbc}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x17,0xf0,0x43,0xcc}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0x19,0x8d,0xba}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0x78,0xeb,0xb9}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0x8a,0xbc,0x3c}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0xd3,0xe5,0x07}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0xdc,0x4e,0xa1}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0xe1,0x22,0x3e}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0xe3,0x45,0x92}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0xe8,0x88,0x77}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x1f,0x10,0x7b,0xeb}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x1f,0x13,0xcd,0x35}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x1f,0x84,0x88,0x23}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x1f,0xb8,0xea,0x55}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x1f,0xd3,0x66,0xa1}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x1b,0x44,0x83,0x0a}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x1f,0x1c,0x0a,0x0d}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x1f,0x1f,0xcb,0x71}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x1f,0x91,0x6a,0x3d}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x1f,0xd3,0x66,0x81}, 62734}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0x30,0x40,0x8c}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0x61,0x8d,0x74}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0x78,0xa0,0x0c}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0x78,0xa4,0x10}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0x86,0xe2,0xb5}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0x93,0x6e,0x2b}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0x78,0xa3,0xb5}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0x86,0xa7,0x5b}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0xbf,0xe1,0xae}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0xc0,0x29,0x20}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0xc2,0x0a,0x1e}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0xf7,0x16,0x35}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x26,0x1b,0x41,0x9e}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x26,0x85,0x8d,0x22}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0xc8,0x22,0x12}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0xcd,0x08,0x4e}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x26,0x1b,0x64,0x2c}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x26,0x66,0x45,0x46}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x26,0x68,0xe1,0x1e}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x29,0x56,0x68,0x5e}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x29,0xaa,0x40,0x08}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2b,0xe5,0x4c,0x2d}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2b,0xf8,0xa0,0x97}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2d,0x20,0x82,0x13}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2d,0x20,0xc1,0x9d}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2d,0x2e,0xa1,0x79}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2d,0x38,0x61,0x3f}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2d,0x74,0xb2,0x4f}, 8188}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0x10,0xf0,0x62}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0x14,0xf6,0x64}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0x15,0x61,0x87}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0x3b,0x0a,0xed}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0x3b,0x0d,0x3b}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0x94,0x10,0xd2}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0xa6,0xa0,0x60}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0xbc,0x2c,0x14}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0xe5,0xee,0xbb}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0xe7,0x10,0x95}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2f,0x58,0x23,0xb5}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2f,0x58,0x64,0x82}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2f,0xb8,0x81,0x5e}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2f,0xc7,0x44,0xcc}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x32,0x1e,0x26,0xcb}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x32,0x3f,0xa2,0xf2}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x32,0x61,0x85,0xd0}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x32,0x72,0xe3,0xe0}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2d,0x20,0x41,0x13}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2d,0x3e,0xc6,0x2e}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0x13,0x88,0x8a}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0x14,0xf6,0x75}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0x1c,0x45,0x8a}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0x1c,0xcd,0x70}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0xa0,0xc3,0x79}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0xa3,0x76,0x33}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0xa6,0x81,0x9f}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0xb7,0xec,0xfe}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0xe3,0x65,0xb0}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0xe5,0xa8,0xc9}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0xee,0xee,0xb0}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0xf2,0x83,0xa8}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2f,0x14,0x67,0x6c}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2f,0x5e,0xe0,0x63}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2f,0xbb,0x01,0x53}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2f,0xdf,0xe8,0x3a}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2f,0xfe,0x80,0x0f}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2f,0xfe,0x80,0xc5}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x32,0x02,0xbd,0x23}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x32,0x1c,0x63,0x51}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x32,0x1f,0xaa,0x33}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x32,0x7e,0xc2,0xbe}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x33,0x0f,0x00,0x11}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x33,0xae,0x45,0xef}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x34,0x07,0x87,0x45}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x34,0x0e,0x40,0x52}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x34,0xcc,0x69,0x19}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x36,0xff,0xa0,0x57}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3d,0x2f,0x02,0x14}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x34,0x1d,0x00,0x25}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x34,0x3b,0x60,0x0b}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x34,0xe1,0x80,0xbf}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x36,0x54,0x62,0x45}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x36,0xc5,0x04,0x5c}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x36,0xdf,0x88,0x3e}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3a,0xad,0xe0,0x62}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3a,0xe5,0xd0,0xa6}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3d,0x7d,0x83,0x37}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3e,0x2b,0x82,0xb2}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3e,0x6a,0x10,0x6f}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3e,0x0d,0xc1,0xce}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3e,0x2d,0x00,0x0f}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3e,0x6b,0xc8,0x1e}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3e,0x6d,0x14,0x63}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3e,0x85,0xc2,0x02}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3e,0x85,0xc2,0x9c}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3e,0xb0,0x06,0x5e}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3e,0xb6,0xa9,0xde}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3e,0xcd,0x84,0xf5}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3e,0xd8,0xee,0x85}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3f,0xe7,0xef,0xd4}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3e,0x8a,0x0b,0x0a}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3e,0xb6,0xab,0x74}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3e,0xc3,0xc1,0x23}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3e,0xd2,0xa1,0xf9}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3f,0x8d,0xe4,0x12}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3f,0x8f,0x25,0x2e}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x40,0x22,0xe7,0x8c}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x40,0xcb,0x66,0x56}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x40,0xe9,0xf5,0x27}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x41,0xb7,0x4c,0x49}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x42,0x60,0xc7,0xa6}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x40,0x27,0xea,0x31}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x40,0x6e,0x19,0x1a}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x40,0x79,0x23,0x03}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x41,0x13,0x9b,0x58}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x42,0x12,0xac,0x10}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x42,0xa0,0x80,0xd7}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x42,0xb4,0x40,0x5f}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x42,0xc2,0x26,0xfa}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x42,0xc2,0x26,0xfd}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x42,0xc4,0x0c,0x3f}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x43,0xd7,0x06,0x22}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x43,0xdd,0xc1,0x37}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x44,0x42,0xc1,0xc0}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x44,0x45,0xeb,0xe6}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x44,0x6f,0x0a,0xdb}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x44,0x77,0x8a,0xaf}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x44,0x84,0xc1,0xde}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x44,0xc2,0x2a,0x4c}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x44,0xeb,0x29,0xcc}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0x0b,0x61,0x2b}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0x29,0x03,0xd4}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x43,0x44,0x65,0xf9}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x43,0x80,0x24,0x5a}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x43,0x94,0x3c,0x82}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x43,0xd2,0xe4,0xcb}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x43,0xe1,0x86,0x1a}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x44,0x0c,0x62,0xf6}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x44,0xc7,0x0a,0x4b}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0x27,0x31,0xc7}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0x29,0xab,0x23}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0x29,0xab,0x24}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0x37,0x40,0xd8}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0x54,0x2a,0x38}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x46,0x30,0x30,0xfa}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x46,0x70,0x20,0x1d}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x46,0xfa,0x4a,0x14}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0x29,0xab,0xe0}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0x40,0x22,0x01}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0x40,0x2e,0x1b}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0x40,0xe1,0x02}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0x9f,0x86,0x3a}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0xb5,0xa0,0x50}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0xde,0xc0,0x58}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x46,0x0f,0x4a,0x48}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x46,0x23,0x62,0x0c}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x46,0x3c,0x41,0x3e}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x46,0x71,0x21,0x83}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x47,0x55,0xe2,0x4c}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x47,0x5d,0xa1,0xa2}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x47,0xc6,0x00,0x7e}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x48,0x05,0xa7,0x29}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x48,0xe0,0x0b,0x67}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x49,0x48,0xa0,0xd5}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x49,0xf1,0xc0,0x28}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4a,0x76,0xc0,0x77}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4a,0x7a,0xed,0x7c}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4b,0x56,0x89,0x22}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4b,0xa5,0x63,0x90}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4c,0x40,0x4a,0xc1}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4c,0x4c,0xe3,0x88}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4c,0xad,0xa1,0x2c}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4c,0xb2,0x16,0x2c}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4d,0x2f,0x89,0x1b}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4d,0x4d,0x2e,0xfa}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4d,0x5b,0xc1,0x98}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4b,0x9f,0x06,0xa7}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4c,0x0a,0x9d,0x3a}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4c,0x5c,0x88,0x4b}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4d,0x5f,0xe2,0xc2}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4d,0x78,0xf6,0xfe}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4d,0xa3,0x88,0x88}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4d,0xcb,0x0d,0x39}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4d,0xec,0x25,0xd6}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4d,0xea,0x32,0x02}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4d,0xef,0x25,0x0c}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4d,0xf7,0xb3,0x2c}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4e,0x22,0x0e,0x34}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4e,0x1f,0x43,0x9c}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4e,0x6d,0xa3,0x99}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4e,0xc4,0xac,0x2d}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4f,0x84,0xe6,0x90}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4f,0xa0,0x02,0x69}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4e,0x82,0xa1,0x4e}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4e,0xc0,0x23,0x82}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4e,0xf8,0x41,0x22}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4f,0x2e,0xc2,0xa3}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4f,0x4d,0x06,0x88}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4f,0x62,0xc4,0x59}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4f,0x9a,0x61,0xa8}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4f,0xa5,0xeb,0x77}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4f,0xa9,0x23,0xeb}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4f,0xb6,0xa7,0x89}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x50,0x52,0x43,0xb6}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x50,0x52,0x4d,0x8a}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x50,0x64,0xcb,0x97}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x50,0x93,0x44,0xed}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x50,0xed,0xf0,0x66}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x51,0x02,0xf6,0x7f}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x51,0x07,0x07,0x56}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x51,0x07,0x0a,0xee}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x50,0x54,0x36,0x1a}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x50,0xd0,0xe0,0xd9}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x50,0xd0,0xe3,0x35}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x50,0xdc,0x2b,0xe4}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x50,0xfe,0xbc,0xeb}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x51,0x07,0x0a,0xfb}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x51,0x07,0x0d,0x54}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x51,0x12,0xe0,0x3e}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x51,0x1b,0x60,0x25}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x51,0x53,0x60,0x05}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x51,0x6c,0xc4,0x48}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x51,0xba,0xf3,0xdc}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x51,0xe4,0xc2,0xbb}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0x2d,0x45,0xd8}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0x45,0x2c,0xb7}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0x48,0xc6,0x44}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0x5f,0xcc,0x0a}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0x76,0xec,0x7f}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0x76,0xf2,0x04}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0x86,0x42,0x92}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0x4a,0xe0,0x23}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0x60,0x40,0x06}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0x75,0xa6,0x4d}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0x76,0xec,0x45}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xa1,0x6d,0xbe}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xc1,0x66,0xe4}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xc1,0x6d,0xc7}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xc5,0xd2,0x41}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xc7,0x66,0x0a}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xc8,0xcd,0x1e}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xc8,0xcc,0x77}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xca,0xc5,0xe0}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xd4,0x07,0xf2}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xdd,0x6c,0x1b}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xdd,0x80,0x51}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xdd,0x8b,0x61}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xe8,0xca,0xf6}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0x3c,0x40,0xfc}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0x3d,0x08,0xe4}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0x80,0x29,0x30}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0x80,0x6f,0x45}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0x32,0x86,0x08}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0x4e,0x21,0x87}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0x89,0x29,0x0a}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0x96,0x2b,0x11}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0xa9,0x02,0x2b}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0xae,0xd1,0x57}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0xff,0x2b,0xa3}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0x2a,0xc1,0x06}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0x34,0x91,0xe7}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0x34,0xea,0x46}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0x55,0x66,0x71}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0x5c,0x5c,0xf7}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0x92,0x23,0x7b}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0xd4,0xc6,0xde}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0xd9,0xa3,0x87}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0xf5,0x1b,0xb9}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0xfb,0xcb,0x05}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0x15,0x90,0xe2}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0x96,0x25,0x5e}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0xa2,0x2b,0x9a}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0xa4,0x83,0xf2}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0xa4,0x83,0xf3}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0xd1,0x08,0x8c}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0xec,0x87,0xfb}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0xf3,0x3b,0x29}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0xf9,0x0d,0xdf}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0xfa,0x56,0x6c}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0x5e,0xeb,0xa1}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0x75,0x01,0x1b}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0xc8,0x6a,0x80}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0xd5,0x40,0x15}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0xe2,0xa4,0xa1}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0xf5,0x1b,0x82}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0xfb,0xa1,0xcd}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0x05,0x01,0x48}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0x0a,0x29,0x29}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0x19,0xc2,0x0c}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0x19,0xc2,0x1c}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0x90,0x77,0xde}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0xb7,0x8c,0x3e}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0xd6,0xe4,0xcb}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0xd6,0xea,0xfe}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0xda,0x96,0x01}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0xe4,0xc4,0x0a}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x56,0x0f,0x02,0xeb}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x56,0x3d,0x06,0xd2}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x57,0x5c,0x73,0xc2}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0x5f,0xf1,0x2e}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0x81,0x00,0x7e}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0xaa,0xe8,0xf5}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0xc3,0xe8,0x27}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0xd6,0x44,0x7a}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0xd6,0xeb,0x89}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0xf5,0xa7,0xf6}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x56,0x08,0x23,0x11}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x56,0x69,0x05,0x71}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x56,0x6a,0x83,0xb3}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x57,0x4f,0x44,0x56}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x57,0x78,0x08,0x05}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x57,0x78,0x25,0xe6}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x57,0xe9,0xb5,0x92}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x57,0xef,0x65,0x66}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x58,0x57,0x4e,0x7e}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x57,0xef,0xca,0xef}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x58,0x62,0xc6,0x82}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x58,0x62,0xe1,0xd6}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x58,0x63,0x3a,0xc2}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x58,0x96,0xc0,0x11}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x58,0xc4,0x88,0x1f}, 17556}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x58,0xd0,0x3a,0xc1}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x58,0xd0,0x3a,0xc2}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x59,0x16,0x60,0x84}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x59,0x16,0x68,0x30}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x59,0x19,0x50,0x62}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x59,0x22,0x63,0x29}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x59,0x8e,0xc3,0x70}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x59,0xa3,0xe0,0xbb}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x58,0x95,0x6a,0xec}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x58,0xcf,0xec,0xaf}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x59,0x23,0x1d,0x03}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x59,0x26,0x60,0x46}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x59,0x8e,0x41,0x97}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x59,0xa3,0xe0,0xc3}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x59,0xee,0x4f,0xeb}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5a,0x2e,0xf0,0xd6}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5a,0x41,0xe8,0x81}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5a,0x47,0x75,0x5a}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5a,0x95,0x26,0xac}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5a,0x9c,0x61,0x91}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5a,0xb1,0x30,0x68}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0x6a,0xc2,0x61}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x59,0xb3,0xf0,0x83}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x59,0xe6,0x60,0x2a}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x59,0xec,0x65,0x34}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5a,0xbf,0xcb,0x12}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0x41,0x07,0x1e}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0x41,0xc0,0x9f}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0x87,0x00,0xbb}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0x96,0xbd,0x9b}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0xb9,0xc6,0xd8}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0xc4,0x0b,0x2d}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0xc5,0x2c,0x85}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0x9a,0x71,0xe3}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0xc3,0x2a,0x86}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0xca,0x43,0x6b}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0xdd,0x47,0x73}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0xe0,0x00,0xe3}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0xe2,0x0a,0x5a}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0xe0,0x01,0x11}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0xe1,0xec,0x91}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0xe4,0x2d,0x82}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0xe5,0x4d,0xef}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0xe7,0xe5,0x88}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0xee,0x64,0xf9}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0xf0,0x8d,0xa9}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5c,0x1b,0x07,0xd1}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5c,0x36,0x10,0x87}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5d,0x59,0x54,0x5d}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5d,0x64,0x33,0x30}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5d,0x64,0x4c,0x97}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5d,0x68,0xd6,0xeb}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5d,0x73,0x56,0xf6}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5d,0x7b,0x50,0x2f}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5d,0xae,0x58,0xd3}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5d,0xbc,0xe0,0xfd}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5d,0xbe,0x45,0xf2}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0x4a,0x51,0x5d}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5c,0x1b,0x8e,0x1d}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5c,0x3e,0x22,0xb8}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5c,0xb1,0x02,0xb5}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5c,0xf9,0xa9,0x24}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5c,0xff,0xb0,0x6d}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5d,0x4b,0x12,0x97}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5d,0x4f,0xcc,0xde}, 10333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5d,0x5f,0x64,0x9b}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5d,0x71,0x83,0x86}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5d,0xaa,0x0d,0x0f}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5d,0xb3,0xc5,0x98}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5d,0xbe,0xcd,0x19}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0x3b,0x87,0x94}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0x9c,0x23,0x08}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0xb0,0xed,0xf1}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0xb1,0x6a,0xbd}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0xb5,0x2c,0x68}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0xe3,0x2b,0xab}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0x4f,0x66,0xd0}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0x4f,0x66,0xd1}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0x9a,0xed,0x18}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0xb7,0x30,0x3e}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0xb7,0x30,0x47}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0xc6,0x61,0xd7}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0xec,0xc6,0xfd}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0xed,0x40,0x8a}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0xf2,0xe8,0x5c}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0x54,0x86,0x6b}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0x69,0xb7,0xb7}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0xbf,0x82,0x64}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0xd5,0xa1,0x02}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0xd5,0xc9,0x5e}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0xe2,0x4d,0x6c}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x60,0x14,0xe3,0x27}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x60,0x1c,0x29,0x5b}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x60,0x17,0x43,0x55}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x60,0x1b,0x08,0xf2}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x62,0x05,0x1f,0xfb}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x62,0x7f,0x82,0x11}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x64,0x24,0x30,0x65}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x65,0x00,0x51,0x2a}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x65,0x00,0x51,0x2b}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x67,0x0b,0x40,0x2e}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x67,0x18,0xf4,0x45}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x67,0x2f,0xd2,0x32}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x67,0x4c,0x29,0xa9}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x62,0xa2,0xd1,0x82}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x63,0xc6,0xed,0x4c}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x63,0xee,0x03,0x56}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x65,0xa5,0x22,0xfd}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x67,0x2c,0xa2,0x32}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x67,0x38,0x88,0x69}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x67,0x3b,0xa6,0x8b}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x67,0x3c,0x61,0x15}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x67,0x4f,0x6b,0x90}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x67,0x50,0xa8,0x39}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x67,0xcb,0x33,0xba}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x67,0xe0,0x76,0x4f}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x67,0x55,0x0e,0x6a}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x67,0x64,0x2c,0x3a}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x67,0xfa,0x04,0x4a}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x68,0xc0,0xaa,0xca}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x68,0xc4,0x00,0x63}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x67,0xfa,0x05,0x4a}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x68,0x20,0xa2,0x95}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x68,0x9c,0x63,0xf0}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x68,0x9c,0x67,0x48}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x68,0xa8,0x65,0xcf}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x68,0xab,0x71,0x34}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x68,0xc5,0x40,0x03}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x68,0xc7,0xc0,0x55}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x68,0xdb,0xfb,0x2e}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x68,0xdf,0x6c,0x21}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x68,0xed,0x02,0xbd}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x68,0xf7,0xe6,0x1c}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6b,0x96,0x2d,0xd2}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6b,0xae,0x22,0x4d}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6b,0xae,0x22,0x4e}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6b,0xb4,0x47,0x2f}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6c,0x3b,0x0c,0xa3}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6c,0xa8,0x25,0x0d}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x68,0xc8,0x43,0xa1}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x68,0xdc,0x10,0xfd}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x68,0xed,0x04,0x1a}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x68,0xee,0xc6,0xa5}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6b,0xb4,0x55,0x5d}, 33244}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6c,0x04,0x0b,0x1d}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6c,0x31,0xc2,0x3a}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6c,0xaf,0x03,0x12}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6c,0xea,0xc1,0x6a}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0x09,0xad,0x0d}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0x65,0xdc,0x97}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0x3d,0x66,0x05}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0x6a,0x88,0xc3}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0x6e,0x5f,0xc9}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0xac,0x68,0x77}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0xc3,0xc1,0x8a}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0xce,0xb1,0x15}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0xe2,0x23,0x1c}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0xff,0x00,0x6b}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x71,0x1d,0xb7,0x8f}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x72,0x91,0x61,0x49}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x73,0x42,0xcd,0xab}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6e,0x04,0x28,0x93}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x70,0xbb,0xb2,0x74}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x71,0x69,0x8b,0x2a}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x73,0x5a,0xab,0x9e}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x74,0x58,0x4b,0x6e}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x74,0xfa,0xc1,0xea}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x75,0x8d,0x8a,0xf0}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x76,0x43,0xc9,0x28}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x76,0xc2,0xe2,0xa8}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x77,0x1c,0x46,0x90}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x78,0x18,0xa6,0x49}, 9998}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x78,0x4c,0xf4,0xc9}, 10022}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x79,0x52,0x04,0xe8}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x79,0xfe,0xad,0x28}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x76,0x59,0xe5,0xb2}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x76,0xd3,0xa7,0x5a}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x78,0x4f,0x40,0x9a}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x79,0xc8,0x05,0xba}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x79,0xfe,0xad,0x27}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x7b,0x02,0x80,0x6b}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x7b,0xcb,0xa3,0x80}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x7c,0xab,0x46,0x2d}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x7d,0x3f,0x39,0x07}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x7d,0x80,0x23,0x29}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x80,0xd0,0xf4,0x7c}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x80,0xe6,0xd0,0x49}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x80,0x01,0x44,0x2e}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x80,0x7d,0x64,0x02}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x82,0x59,0x4e,0x57}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x82,0xcc,0x4b,0x03}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x83,0x72,0x0a,0xe9}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x83,0x72,0x0a,0xeb}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x84,0xef,0x24,0x69}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x86,0xd5,0xd6,0xe9}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x88,0x3d,0xee,0x79}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x88,0x3e,0x56,0x8c}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x88,0x90,0x80,0x31}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x89,0x30,0x90,0x34}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x89,0x74,0xa0,0xb0}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x89,0x75,0xc1,0x71}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x8a,0x13,0x4f,0xd0}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x8a,0x44,0x40,0x13}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x83,0xbc,0x28,0xbf}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x84,0x94,0x82,0x33}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x86,0xff,0xe2,0xe9}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x87,0x17,0xc2,0x62}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x88,0x19,0x89,0xdc}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x88,0x37,0x0a,0xf9}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x88,0xf3,0x20,0x26}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x88,0xf3,0x40,0x17}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x89,0xe2,0x22,0x2e}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x8b,0x3b,0x60,0x10}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x8b,0xa2,0xa0,0xe8}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x8d,0x88,0x73,0xe6}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x8e,0x3b,0xe8,0x6f}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x8e,0x6f,0x02,0x4a}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x8e,0xa2,0x80,0x17}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x8f,0x6b,0x74,0x05}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x8f,0xe5,0x16,0x4a}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x8f,0xe5,0x24,0x47}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x90,0x02,0x69,0x3c}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x90,0x4c,0xe0,0xd6}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x92,0xb9,0x13,0x1e}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x93,0x20,0x1e,0x19}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x93,0xe5,0x0d,0xd2}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x94,0x67,0x07,0x77}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x96,0x65,0x72,0xc2}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x8b,0xc7,0xe4,0x54}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x8d,0x86,0x47,0xbc}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x8d,0x8a,0x89,0x28}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x91,0x81,0x1f,0x93}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x92,0x47,0x4c,0x35}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x92,0x47,0x4c,0xec}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x95,0xd2,0xe4,0x6c}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x96,0xe5,0x00,0x8f}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x9a,0x42,0xcf,0x7e}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x9e,0x81,0xd4,0xec}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x9e,0x81,0xd4,0xfb}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa0,0x10,0xce,0x1f}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa2,0xd1,0x01,0xe9}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa2,0xd1,0x04,0x7d}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa2,0xdc,0xf6,0xe1}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa3,0xac,0xda,0xba}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x96,0xf9,0x4c,0x66}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x99,0x7d,0xe0,0x2c}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x9b,0x04,0x63,0x96}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x9b,0x85,0x81,0x61}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x9d,0x9f,0x67,0xa1}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x9e,0x8c,0xc9,0x23}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x9e,0x8c,0xe5,0x3e}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x9e,0xb5,0x68,0x84}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x9e,0xb5,0x86,0xc1}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa0,0x10,0x87,0xbb}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa2,0xdd,0xe0,0x3f}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa5,0xa5,0x84,0x44}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa5,0xc2,0x23,0xcb}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa6,0xe6,0x46,0x91}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa8,0xeb,0x4a,0x2d}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa9,0x2c,0x22,0x58}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa9,0x2c,0x22,0xcb}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa9,0x30,0xa3,0xb0}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xaa,0x4b,0xa2,0xb4}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xaa,0x4b,0xc3,0xa8}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xac,0x70,0x02,0x43}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xad,0x5e,0xa4,0x26}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xad,0xb7,0xe8,0x6d}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xad,0xd0,0xb0,0x7a}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xad,0xd4,0xc2,0x72}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xad,0xe8,0xe4,0x92}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xaf,0x7e,0x7c,0x5c}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xaf,0x91,0x6d,0x33}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb0,0x18,0xc6,0xcd}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb0,0x24,0x25,0x3e}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb0,0x24,0x63,0xde}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb0,0x6a,0x90,0xb7}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb1,0x21,0x01,0x28}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0xa2,0xd6,0xe1}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0xa4,0x6d,0x53}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0xaa,0x8a,0xca}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0xaf,0x88,0x7a}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0xda,0xd1,0xa2}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0xfe,0x02,0x40}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xab,0x19,0xa5,0x91}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xac,0x60,0xa1,0x8a}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xac,0x62,0xc1,0x2d}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xac,0x67,0xa4,0x4b}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xac,0x6e,0x08,0xe9}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xad,0xd1,0x35,0x72}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xad,0xd4,0xc0,0x75}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xad,0xf3,0x40,0x31}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xad,0xff,0xe0,0xb9}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xae,0x64,0x83,0x97}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xae,0x71,0x42,0xe6}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xae,0x8a,0x3e,0x5a}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb0,0x0a,0x88,0x19}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb0,0x17,0x0d,0x1b}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb0,0x18,0xdc,0x8d}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb0,0x6a,0xfc,0xad}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb0,0x7e,0xa7,0x0a}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb1,0x34,0xad,0x3f}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0x4e,0xe2,0xb2}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0x84,0x04,0x7b}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0xaf,0x90,0x7a}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0xdd,0x42,0xd4}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0xec,0x82,0xe5}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0xfe,0x07,0x58}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0xfe,0x22,0x90}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0xff,0x29,0x15}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0xff,0x90,0xa3}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb4,0xb5,0xd0,0x2a}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb4,0xc8,0x80,0x3a}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb4,0xeb,0x32,0x0e}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb5,0xd7,0x94,0x9a}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb8,0x40,0x0d,0x2b}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb8,0x5e,0xa4,0xaa}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb8,0x98,0x6b,0xfb}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb8,0xb6,0xe9,0xce}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x04,0x18,0xc7}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x14,0x63,0x31}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x18,0x61,0x0b}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x19,0x30,0x1b}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x19,0x30,0x47}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x1a,0xc4,0xf9}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb3,0x30,0xfb,0x29}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb6,0xf7,0xee,0xa9}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb7,0x6f,0x1d,0x1c}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb8,0x40,0x0c,0x6d}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb8,0x46,0x21,0xbe}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb8,0x5f,0x26,0xda}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x08,0xac,0x79}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x0b,0x52,0x26}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x0c,0x07,0x26}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x0c,0xec,0xf2}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x14,0xe2,0x94}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x15,0xd8,0x86}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x16,0xe8,0xa7}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x1c,0x4c,0xb3}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x23,0x8b,0xfa}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x29,0x71,0x45}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x32,0xd5,0x7b}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x32,0xd5,0x7c}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x32,0xe8,0x72}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x33,0xc0,0x28}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x35,0x81,0xf4}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x47,0xb1,0x64}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x1f,0x88,0x45}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x23,0x89,0xaf}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x23,0x8a,0x54}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x23,0xb6,0x7b}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x2f,0x84,0x6d}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x35,0x80,0xb4}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x3f,0xac,0x0e}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x40,0x68,0x02}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x46,0x69,0x4a}, 8339}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x4d,0x80,0x45}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x4d,0x81,0xb0}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x52,0xc9,0x33}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x55,0x03,0x89}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x66,0x47,0x06}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x79,0xad,0xdf}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x8c,0xfc,0xfd}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x91,0x81,0xb8}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x91,0x82,0xa3}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x7f,0x11,0xa7}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x9a,0x9c,0x32}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0xa2,0x7c,0x45}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0xaa,0x2a,0x02}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xba,0x95,0xc5,0x60}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0x41,0xd4,0x8a}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0x41,0xd5,0x30}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0x5d,0xd1,0xc0}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0x71,0x4f,0x2d}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0x71,0x54,0x74}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0x71,0xa4,0xe7}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0x7a,0x10,0x99}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0xa5,0xe0,0x1c}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0xaf,0xef,0xe3}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0xa2,0x80,0x53}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0xb7,0xa1,0x23}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0xbd,0xc7,0xf8}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0xd7,0xe0,0x6b}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xba,0x05,0x88,0x46}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xba,0x1f,0x04,0xca}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0x1b,0x50,0x7e}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0x41,0xd4,0x31}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0x74,0x8c,0x7f}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0x86,0x4f,0x91}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0xd6,0x80,0x12}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0xd6,0x80,0xaf}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0xe3,0x40,0x13}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0xea,0xf1,0xac}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0xfd,0x02,0x7d}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbd,0x2d,0xcb,0xa6}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbe,0x0a,0x08,0xd3}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbe,0x91,0x16,0xca}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbe,0xb8,0xc6,0x22}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0x97,0x91,0xfa}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0xce,0xca,0x06}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbe,0xd2,0xea,0x26}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0x5c,0x81,0x05}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0x79,0xaa,0xb4}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0xa2,0x64,0x9c}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0xa2,0xd2,0x5b}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0xa9,0x06,0x7f}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0xaf,0x3b,0x8c}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0xde,0xed,0x10}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0xe4,0x65,0x9d}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc1,0x02,0x4c,0x29}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc1,0x1b,0xd1,0x64}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc1,0x21,0xed,0xbb}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc1,0x2e,0x53,0x11}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc1,0x17,0xb5,0x87}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc1,0x31,0x2b,0xdb}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc2,0x18,0xb6,0x1b}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc2,0x1c,0xce,0xc9}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc2,0x3f,0x8f,0xc5}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc2,0x47,0x6d,0x5b}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc2,0x4f,0x08,0x24}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc2,0x87,0x5d,0x26}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc1,0x6a,0x1e,0xad}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc1,0x8a,0xe0,0xe6}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc1,0xe0,0x16,0x2d}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc2,0x0f,0xe7,0xec}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc2,0x6a,0xd8,0x14}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc2,0xba,0xa0,0xfd}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc3,0x09,0x8c,0x86}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc3,0x27,0xce,0x1d}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc3,0x43,0x24,0x59}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc2,0xf6,0x56,0x20}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc3,0x16,0x68,0x17}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc3,0x31,0x4b,0xe9}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc3,0x5b,0xf4,0x8a}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc3,0xa9,0x63,0x52}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc3,0xd6,0xd6,0xfd}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc3,0xdf,0x47,0x93}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc6,0x25,0x76,0x0b}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc6,0x36,0x71,0x7d}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc6,0x65,0x0c,0x8b}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc4,0x1c,0x62,0x15}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc4,0xdc,0x43,0x97}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc5,0x9b,0x06,0x2b}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc5,0xbd,0xec,0xfa}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc5,0xea,0x45,0x92}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc6,0x8f,0x0c,0x69}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc6,0xfb,0x53,0x13}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc6,0xbb,0x1c,0x02}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc7,0x44,0xc5,0x05}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc7,0x7f,0xe0,0x32}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc8,0x0c,0x8a,0x92}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc8,0x74,0x62,0xb9}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc7,0xc1,0x06,0x0e}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc7,0xc9,0x6e,0x92}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc8,0x6d,0x43,0x47}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc8,0x7a,0x80,0x82}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xca,0x1d,0x06,0x30}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xca,0x85,0x73,0x73}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xcb,0x3b,0x11,0xa0}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc9,0xee,0xdf,0xa5}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xca,0x2f,0xe1,0xf2}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xcb,0x3c,0x02,0x43}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xcc,0x0f,0x0b,0x04}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xcc,0x6f,0xf1,0xc3}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xcd,0xfb,0x55,0x97}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xcf,0xf4,0x46,0x28}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xcf,0xfe,0x32,0x48}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd0,0x4c,0x5d,0x53}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd0,0x6b,0x61,0xf2}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd0,0x6e,0x49,0x6b}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xcc,0x0f,0x0b,0x08}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xcc,0x8a,0xa5,0x23}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xce,0x7b,0x0b,0x8b}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xce,0xfd,0xa3,0xe2}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xcf,0xbc,0x10,0x10}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd0,0x4d,0x12,0x19}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd0,0x56,0xa1,0x53}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd0,0x64,0x89,0xcc}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd0,0x6b,0xe0,0xca}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd0,0x76,0xeb,0xbe}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd1,0x49,0x8e,0xe2}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd1,0x51,0x09,0xdf}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd1,0x7e,0x6b,0xa6}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd1,0xb1,0x56,0x13}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd1,0xfa,0x06,0xbe}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd2,0x01,0xdb,0x9b}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd1,0x9f,0x89,0x92}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd1,0xa1,0x04,0xa4}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd1,0xc5,0x0d,0x3e}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd2,0xd3,0x6d,0xa5}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd2,0xdf,0x03,0x2c}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd3,0x15,0x81,0x45}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd4,0x32,0x62,0xa1}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd4,0x33,0x8c,0xb7}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd3,0x97,0x26,0x5c}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd4,0x20,0xe5,0xe6}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd4,0x33,0x0e,0x48}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd4,0x38,0x6c,0x51}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd4,0x53,0x23,0xad}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd4,0x5a,0xb3,0xce}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd4,0x5d,0xe2,0x5a}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd4,0x6e,0xab,0x76}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd5,0x05,0x24,0x3a}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd5,0x05,0xb5,0xcd}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd5,0x11,0x10,0xfb}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd4,0x7c,0xa0,0xc7}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd4,0x80,0x2c,0x31}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd4,0x95,0xeb,0xb9}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd4,0xc7,0xaf,0x1e}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd4,0xed,0x60,0x62}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd5,0x43,0x63,0x8e}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd5,0x5b,0xcd,0x86}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd5,0x5b,0xd3,0x11}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd5,0x73,0xe0,0xfc}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd5,0x83,0x0c,0x0a}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd5,0x84,0x4c,0xb8}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd5,0x98,0xa1,0xaa}, 45893}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd5,0x9b,0x03,0xd8}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd5,0xa8,0x0d,0x97}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd5,0xba,0xaa,0x6d}, 8334}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd5,0xde,0xd0,0x96}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd8,0x20,0xd5,0x70}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd8,0x3b,0x04,0xd4}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd8,0x7e,0xc1,0xa3}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd8,0xc5,0x4f,0x4a}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd8,0xda,0x93,0x8c}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd8,0xe3,0x27,0x54}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd8,0xf5,0xce,0xb5}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd8,0xf9,0x5c,0xe6}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd9,0x0c,0xc7,0xcf}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd9,0x17,0x02,0xb1}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd9,0x17,0x05,0x44}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd9,0x1c,0xc2,0x02}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd9,0x23,0x82,0x2a}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd9,0x40,0x2f,0x8a}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd9,0x65,0x48,0xf2}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd9,0x91,0x51,0xe5}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd9,0xa8,0x8f,0xa9}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd5,0x9c,0x6c,0x3f}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd5,0xdb,0xa2,0x92}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd8,0x24,0xb3,0x1b}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd8,0xb8,0x08,0x1a}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd8,0xf5,0xda,0xf2}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd9,0x0c,0xcc,0x56}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd9,0x14,0x82,0x48}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd9,0xa9,0x07,0x6f}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd9,0xb6,0xc0,0x07}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd9,0xc7,0x63,0x1e}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xdb,0x58,0xe8,0xe5}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xdb,0x71,0xf4,0x34}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xdc,0x82,0x80,0x3a}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xdc,0xf4,0xe1,0xef}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xdd,0x8d,0x03,0x0c}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xde,0xa6,0xb0,0x63}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xdf,0xfc,0xad,0x93}, 8333}, - {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x10,0x25,0x04,0xe5,0xac,0xb0,0x22,0xcd}, 8333}, - {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x10,0x78,0x18,0xa6,0x5d,0x2c,0x24,0x61}, 8333}, - {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x10,0xec,0x23,0x6a,0xbd,0x3b,0xf3,0xc0}, 8333}, - {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x18,0x6d,0x3f,0x17,0xb7,0xad,0x95,0xcf}, 8333}, - {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x18,0x70,0x02,0x42,0xac,0x03,0xaa,0xf9}, 8333}, - {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x18,0xa6,0x11,0x02,0x2a,0xbf,0xeb,0x70}, 8333}, - {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x1c,0xe5,0x24,0x8c,0x4f,0xf5,0x2b,0x1d}, 8333}, - {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x20,0x0f,0x15,0x6a,0xbc,0x77,0x3a,0xcd}, 8333}, - {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x24,0x18,0x19,0xd1,0xcd,0xdc,0xb1,0xaf}, 8333}, - {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x28,0x57,0x3d,0x78,0xaa,0xf8,0xeb,0x28}, 8333}, - {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x28,0xb2,0x1b,0x84,0x64,0xfb,0x2d,0x6a}, 8333}, - {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x2c,0x70,0x0d,0x51,0xd0,0x46,0x12,0x09}, 8333}, - {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x2c,0xac,0x2f,0xcf,0x46,0xbb,0xbe,0x0d}, 8333}, - {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x30,0x5e,0x20,0xee,0xa9,0x4f,0x6f,0x69}, 8333}, - {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x30,0xcd,0x08,0x49,0xad,0xfe,0x6e,0x67}, 8333}, - {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x34,0x5b,0x0f,0x12,0xae,0x1e,0x29,0x48}, 8333}, - {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x3c,0x40,0x14,0x6e,0x97,0x41,0x5a,0x3a}, 8333}, - {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x3c,0x9e,0x3c,0x3e,0x9d,0x6e,0x73,0x40}, 8333}, - {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x04,0x99,0x29,0xa8,0xd0,0x47,0x7e,0xa1}, 8333}, - {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x00,0x51,0x00,0x24,0x81,0xb2,0x59,0xe3}, 8333}, - {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x08,0x89,0x2d,0x7c,0xb6,0x1b,0xbf,0x0d}, 8333}, - {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x0c,0x9f,0x37,0x9c,0xad,0xd2,0xc9,0x38}, 8333}, - {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x0c,0xd6,0x2e,0xb4,0xb8,0x2b,0xad,0xdb}, 8333}, - {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x0c,0xf0,0x2e,0x3a,0xb2,0x9d,0x62,0x07}, 8333}, - {{0x20,0x01,0x00,0x00,0x53,0xaa,0x06,0x4c,0x14,0x85,0xfb,0xf9,0xa7,0x98,0x1f,0xfe}, 8333}, - {{0x20,0x01,0x00,0x00,0x53,0xaa,0x06,0x4c,0x00,0x59,0x61,0x7f,0xa1,0x0d,0x00,0xe0}, 8333}, - {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x10,0x20,0x2c,0xd0,0x47,0x50,0xeb,0x12}, 8333}, - {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x10,0x36,0x1d,0x50,0x38,0x81,0x69,0x30}, 8333}, - {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x10,0xa4,0x27,0xd8,0x9c,0x0a,0xcf,0xa9}, 8333}, - {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x10,0xae,0x05,0xa8,0x52,0x4b,0xdc,0xc4}, 8333}, - {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x18,0x92,0x3e,0x3a,0x3f,0x74,0xaf,0xfa}, 8333}, - {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x1c,0x95,0x1a,0x60,0xd1,0xf5,0x21,0x5b}, 8333}, - {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x20,0x0b,0x16,0xef,0xb9,0xcf,0x98,0x60}, 8333}, - {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x28,0xe4,0xfb,0xff,0x32,0x37,0x09,0x92}, 8333}, - {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x2c,0xe8,0x1d,0x9e,0xb3,0xbf,0xb5,0x3e}, 8333}, - {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x30,0x0a,0x2e,0x20,0x47,0x50,0xeb,0x12}, 8333}, - {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x30,0xa2,0x1a,0xd9,0x53,0x24,0x83,0x6a}, 8333}, - {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x34,0x09,0x19,0x96,0xbc,0xac,0x24,0x1f}, 8333}, - {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x34,0x4b,0x2b,0xd4,0xbb,0x3e,0x0e,0x26}, 8333}, - {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x34,0xb3,0x11,0xdb,0xe7,0xda,0xd4,0x61}, 8333}, - {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x38,0x39,0x2e,0x0c,0xba,0x30,0x28,0x8e}, 8333}, - {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x38,0x80,0x0e,0xf4,0xb5,0xf0,0xee,0x4d}, 8333}, - {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x38,0x9f,0x00,0x52,0x9c,0x0c,0x1f,0x41}, 8333}, - {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x3c,0x73,0x30,0x4a,0x9d,0x8b,0x99,0xd5}, 8333}, - {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x3c,0xac,0x33,0xe4,0x39,0xca,0x03,0x8c}, 8333}, - {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x00,0x6f,0x36,0x67,0x53,0x98,0x53,0x8f}, 8333}, - {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x08,0x8c,0x03,0xe6,0x94,0x54,0x33,0x31}, 8333}, - {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x00,0x89,0x3b,0x55,0x9f,0xcc,0x8e,0x66}, 8333}, - {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x0c,0x9b,0x3d,0x65,0xbd,0xf4,0x5d,0x58}, 8333}, - {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x0c,0xb7,0x08,0xcc,0xb8,0xee,0x68,0x06}, 8333}, - {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfd,0x24,0xf6,0x37,0xb5,0xb9,0xd2,0x2a,0xa7}, 8333}, - {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfd,0x3c,0x63,0x08,0x2e,0xaa,0xbc,0xbd,0x39}, 8333}, - {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfd,0x3c,0xf5,0x2e,0xb7,0xc9,0x66,0x56,0x1d}, 8333}, - {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfd,0x0c,0xf4,0x28,0xe2,0xaa,0xbd,0xb7,0x66}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x10,0xf6,0x04,0x53,0x3c,0xa4,0x1a,0x8e}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x14,0xdd,0x29,0x8b,0x43,0x1c,0xbf,0xec}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x30,0x51,0x15,0x61,0xb6,0x2d,0x73,0xa5}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x34,0x67,0x0f,0xfa,0xb6,0x12,0xe9,0xc6}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x08,0xe8,0x1e,0x26,0xe8,0xe3,0xee,0xd7}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x0c,0x82,0x37,0xb3,0x47,0xee,0x3a,0xe2}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x10,0x52,0x3c,0xd8,0xa8,0x9b,0x0e,0x67}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x14,0x4d,0x23,0xf3,0xab,0xcb,0x8b,0xcb}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x1c,0x2e,0x31,0xdf,0xad,0xf1,0xe6,0x16}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x1c,0x41,0x21,0x3b,0xfa,0xcc,0x9c,0x6b}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x20,0x93,0x12,0xb5,0x8c,0xbf,0x4f,0x57}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x24,0x3a,0x23,0x94,0xfd,0x91,0x71,0x2c}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x28,0x33,0x09,0xf8,0xc9,0x4c,0x68,0x81}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x2c,0x84,0x29,0xd3,0xae,0x5a,0xf6,0xf0}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x2c,0xe4,0x0d,0x50,0xcb,0x22,0x36,0x72}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x38,0x24,0x08,0x16,0xc3,0x0d,0xe9,0xd4}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x38,0x9a,0x24,0xe9,0xcb,0x5c,0xa1,0xcd}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x38,0xbd,0x08,0x8f,0x21,0x93,0x49,0x32}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x3c,0x4f,0x0c,0xb1,0xd6,0x5b,0xd7,0x75}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x3c,0x51,0x28,0x0b,0xb1,0xe9,0x0f,0xfd}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x3c,0x5a,0x02,0xe2,0x21,0x93,0x49,0x32}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x3c,0x5e,0x3e,0xbf,0x3d,0xc0,0x70,0x3a}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x04,0xc9,0x12,0xfc,0xd1,0xd9,0xdc,0x21}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x00,0x6e,0x34,0xe7,0xd0,0xa7,0x67,0x72}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x08,0xde,0x1f,0x29,0x2a,0xea,0xf9,0x6f}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x0c,0x5f,0x26,0x74,0xa4,0x67,0x78,0x7c}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x0c,0xc0,0x23,0xa4,0xad,0x7c,0xc9,0x98}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x78,0xcf,0x20,0xc0,0x20,0x97,0xd1,0x88,0x9c,0x3b}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x78,0xcf,0x24,0x20,0x0d,0xda,0x4f,0xf6,0x87,0x94}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x78,0xcf,0x28,0x92,0x0f,0xcb,0x26,0xb2,0x22,0xac}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x78,0xcf,0x30,0x20,0x1a,0xd7,0x26,0xb2,0x22,0xac}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x78,0xcf,0x30,0xae,0x21,0x1b,0xe7,0x17,0x77,0x88}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x78,0xcf,0x30,0xd0,0x6e,0xdd,0xa4,0x18,0xa9,0xe9}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x78,0xcf,0x30,0xd9,0x32,0x78,0xb0,0x04,0x65,0xa7}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x78,0xcf,0x38,0x7a,0x17,0xd5,0xda,0xcb,0xbd,0xf1}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x78,0xcf,0x3c,0x38,0x0c,0x41,0x43,0x3c,0x7b,0x87}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x78,0xcf,0x04,0x67,0x01,0x93,0xa8,0xb0,0xa1,0x22}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x78,0xcf,0x0c,0x65,0xfb,0x96,0x97,0xd2,0xa9,0xb0}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x78,0xcf,0x0c,0x9f,0x26,0x33,0xd1,0x69,0x99,0x99}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x78,0xcf,0x0c,0xe2,0x0a,0xba,0xd1,0x20,0x90,0xdb}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x10,0x5d,0x26,0xf2,0xa2,0x41,0x73,0x39}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x10,0x62,0x3f,0x95,0xe0,0x65,0xfc,0x21}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x10,0xa6,0x19,0xf6,0xab,0x95,0xeb,0xcb}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x14,0xe2,0x22,0xcb,0x73,0x8f,0x94,0x89}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x18,0xfb,0x3d,0xa9,0x89,0x3d,0x1d,0x57}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x1c,0xc3,0x25,0x34,0xe0,0x20,0x53,0xfa}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x20,0x6d,0x2b,0x34,0xd0,0xcb,0x9d,0xe8}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x20,0xcb,0x02,0xcb,0xb9,0xa7,0xca,0x5e}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x24,0x5c,0x27,0x53,0x43,0x82,0x70,0x4b}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x24,0xd6,0x22,0x5f,0x79,0x3b,0x0b,0xf5}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x24,0xda,0x08,0xf0,0xbb,0xf9,0x9c,0x93}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x28,0xa2,0x10,0x7b,0x43,0x8e,0xb0,0x8d}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x2c,0x16,0x0d,0x58,0xb3,0x81,0x0b,0x61}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x2c,0x68,0x30,0x68,0xcb,0x59,0x3b,0xe7}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x2c,0x90,0x38,0x55,0xb9,0x4f,0xc9,0x26}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x2c,0xa2,0x35,0x92,0xc1,0x11,0xdd,0x82}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x2c,0xce,0x1f,0x6e,0xb3,0x81,0x86,0x05}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x34,0x35,0x39,0x15,0x2b,0xcc,0x6c,0xc7}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x34,0x38,0x2b,0x9f,0xad,0x57,0xa7,0x21}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xdc,0xbf,0xa9,0x5a}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xdd,0x7f,0x2b,0xcf}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xde,0xef,0xc1,0xd2}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xdf,0x11,0xca,0xce}, 8333}, + {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x10,0xf2,0x28,0x73,0x97,0x0b,0x20,0x68}, 8333}, + {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x10,0xf6,0x1a,0xa2,0xae,0x9d,0x42,0x86}, 8333}, + {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x14,0x0a,0x0d,0x05,0xc1,0xe1,0xb5,0xc4}, 8333}, + {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x14,0x2a,0x19,0x57,0xb6,0x1e,0x05,0x6e}, 8333}, + {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x14,0x2d,0x0f,0xac,0x2a,0xaf,0xe4,0xc2}, 8333}, + {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x14,0x71,0x04,0x52,0x66,0x71,0x82,0x74}, 8333}, + {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x14,0x82,0x05,0x30,0xb1,0x45,0x7e,0x28}, 8333}, + {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x18,0xac,0x39,0x54,0x39,0x01,0xa2,0x57}, 8333}, + {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x18,0xd5,0x3c,0x77,0x82,0x9a,0x6f,0xe6}, 8333}, + {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x20,0x66,0x16,0x4f,0xb3,0x9d,0xb0,0x87}, 8333}, + {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x20,0x69,0x07,0x8b,0xb7,0xd5,0x58,0x60}, 8333}, + {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x20,0xac,0x22,0xb1,0xbb,0x18,0x11,0x60}, 8333}, + {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x20,0xf6,0x14,0x7f,0xe7,0xe9,0xdd,0xd1}, 8333}, + {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x20,0xfa,0x31,0x26,0x97,0xf1,0x60,0x0d}, 8333}, + {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x24,0x57,0x0f,0x34,0xa3,0x13,0x4b,0x99}, 8333}, + {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x28,0xf4,0x25,0x12,0xbc,0x91,0x2e,0x53}, 8333}, + {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x2c,0x55,0x0f,0xa9,0xfd,0xe5,0x5d,0x86}, 8333}, + {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x2c,0xba,0x18,0x28,0x52,0xae,0x75,0x01}, 8333}, + {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x2c,0xf3,0x78,0xfc,0xa1,0x38,0xe6,0xed}, 8333}, + {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x30,0x01,0x0b,0xf6,0xbe,0x62,0xcc,0xe5}, 8333}, + {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x30,0xa8,0x3a,0xfb,0xb6,0xd5,0x2b,0xd7}, 8333}, + {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x30,0xe6,0x04,0x4d,0xae,0x7f,0x74,0x9d}, 8333}, + {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x34,0x02,0x0d,0xaf,0xb4,0x75,0xda,0xf9}, 8333}, + {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x34,0x23,0x3d,0x03,0xd7,0x71,0xd5,0x01}, 8333}, + {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x34,0x24,0x02,0x11,0xb6,0x00,0xb4,0xcb}, 8333}, + {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x34,0x2f,0x14,0x53,0xcd,0xdc,0x4f,0x03}, 8333}, + {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x34,0x57,0x24,0x8d,0xa0,0xb9,0x3b,0xc9}, 8333}, + {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x38,0x6f,0x38,0x46,0xb9,0x95,0x01,0x88}, 8333}, + {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x38,0xa8,0x31,0x8a,0xe7,0xdc,0xae,0xe1}, 8333}, + {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x38,0xeb,0x1e,0x88,0xad,0xdb,0x18,0x1c}, 8333}, + {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x3c,0x39,0x27,0xe3,0x47,0x58,0x36,0x5c}, 8333}, + {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x3c,0x7d,0x3f,0xa4,0x86,0xad,0x4e,0xbb}, 8333}, + {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x3c,0xfd,0x31,0x81,0xb2,0xc7,0x5c,0x5e}, 8333}, + {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x04,0x01,0x21,0x57,0x68,0x4e,0xf2,0xd6}, 8333}, + {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x04,0x3a,0x1a,0x64,0xbd,0x14,0xfb,0x16}, 8333}, + {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x04,0x7d,0x00,0xbb,0xae,0x1e,0x29,0x48}, 8333}, + {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x08,0x43,0x9b,0x9e,0xcd,0x0a,0x66,0x55}, 8333}, + {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x08,0x86,0x3c,0x19,0xad,0xdd,0x9a,0x58}, 8333}, + {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x08,0xba,0x09,0xf8,0x9e,0xad,0x0f,0x21}, 8333}, + {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x0c,0x06,0x12,0x4c,0xa4,0x82,0xa7,0x61}, 8333}, + {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x0c,0xda,0x0b,0x84,0x8d,0x4c,0xd1,0xe6}, 8333}, + {{0x20,0x01,0x00,0x00,0x53,0xaa,0x06,0x4c,0x00,0x20,0x0a,0x71,0x85,0x8b,0x83,0xf7}, 8333}, + {{0x20,0x01,0x00,0x00,0x53,0xaa,0x06,0x4c,0x00,0xc5,0x23,0x5d,0xa1,0x0d,0x00,0xe0}, 8333}, + {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x10,0x3a,0x23,0xfb,0xbb,0x8a,0xed,0x5b}, 8333}, + {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x10,0x64,0x0d,0x3d,0x51,0xff,0x59,0x38}, 8333}, + {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x10,0xfd,0x13,0x69,0x71,0x5e,0x6a,0xa7}, 8333}, + {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x14,0xd5,0x17,0x58,0xb1,0x7d,0x5e,0xb1}, 8333}, + {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x18,0x17,0x26,0x34,0x9f,0xc9,0x1b,0xc4}, 8333}, + {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x18,0x1a,0x27,0x17,0x94,0x41,0xc1,0xeb}, 8333}, + {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x18,0x75,0x0b,0xc8,0xb1,0xc2,0x01,0xb4}, 8333}, + {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x18,0xb5,0x31,0x85,0x51,0xa2,0x03,0x5d}, 8333}, + {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x18,0xc3,0x0f,0xeb,0xb4,0x71,0x49,0xd1}, 8333}, + {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x18,0xdd,0x3b,0xd5,0x41,0x8f,0x0c,0x1e}, 8333}, + {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x1c,0x19,0x30,0x62,0xbc,0xaa,0x09,0x6b}, 8333}, + {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x1c,0x53,0x14,0xbd,0xb8,0xd9,0x7a,0xa2}, 8333}, + {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x1c,0x60,0x08,0x2b,0x94,0xfd,0xa4,0x52}, 8333}, + {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x1c,0x85,0x2e,0x50,0xba,0x7d,0x0a,0x1a}, 8333}, + {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x1c,0xff,0x2d,0x43,0x51,0xf9,0xb8,0x89}, 8333}, + {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x20,0x74,0x22,0x1a,0x47,0x50,0xeb,0x12}, 8333}, + {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x20,0x8f,0x2d,0x83,0xe0,0xf5,0xe3,0x1f}, 8333}, + {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x20,0x92,0x37,0x1f,0x9d,0xfb,0x98,0xcd}, 8333}, + {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x20,0xf3,0x39,0xa2,0x39,0xca,0x03,0x8c}, 8333}, + {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x28,0x1c,0x20,0x85,0x51,0x8d,0x9c,0x97}, 8333}, + {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x28,0x51,0x00,0x0c,0x52,0x4c,0xa1,0x80}, 8333}, + {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x28,0x53,0x3b,0x95,0xa4,0x30,0x40,0xf3}, 8333}, + {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x28,0xf6,0x30,0xa4,0x30,0xd9,0x12,0x01}, 8333}, + {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x2c,0x5f,0x1a,0xde,0x71,0x8f,0x60,0x9d}, 8333}, + {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x2c,0xc0,0x1b,0x38,0xe7,0xaf,0xae,0x80}, 8333}, + {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x30,0x00,0x3d,0xc4,0x52,0x4d,0x3c,0xe2}, 8333}, + {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x30,0x60,0x2e,0x81,0x51,0x8f,0x63,0xbc}, 8333}, + {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x30,0x68,0x05,0x07,0xbc,0xaf,0xdb,0xad}, 8333}, + {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x30,0x8f,0x00,0xf3,0x93,0x5d,0x6a,0x1b}, 8333}, + {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x30,0xce,0x33,0x01,0xd2,0xd0,0x9b,0xbc}, 8333}, + {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x30,0xdb,0x31,0x45,0x43,0x81,0xf1,0x47}, 8333}, + {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x34,0xa3,0x22,0x98,0xb7,0xcd,0x22,0xf6}, 8333}, + {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x04,0x1e,0x01,0x60,0xbc,0x48,0x79,0x1d}, 8333}, + {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x00,0x42,0xb4,0xfc,0x3f,0x74,0xaf,0xfb}, 8333}, + {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x04,0x7a,0x16,0xaa,0xd0,0xc9,0x30,0xa4}, 8333}, + {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x08,0x9c,0x34,0x81,0xd9,0x73,0x5d,0xad}, 8333}, + {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x08,0xbe,0x31,0x4a,0x26,0xb2,0xef,0xef}, 8333}, + {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x08,0xf3,0x3d,0xaf,0x3f,0x21,0x0b,0xac}, 8333}, + {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x0c,0x1f,0x20,0xf4,0xb9,0xac,0x99,0xdb}, 8333}, + {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x0c,0x70,0x10,0x5c,0x77,0xde,0x9f,0x7d}, 8333}, + {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x00,0xed,0x20,0x0c,0xb9,0xac,0x34,0xdb}, 8333}, + {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfd,0x30,0x57,0x08,0x5b,0xb7,0x03,0x25,0x5d}, 8333}, + {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfd,0x08,0xd1,0x13,0xc6,0x5d,0x0a,0xb1,0x17}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x10,0x07,0x39,0x5e,0xcd,0x3a,0x82,0xf2}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x10,0x8b,0x34,0xb5,0xe8,0xe3,0xee,0xd7}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x10,0x9c,0x07,0x38,0x7f,0xb9,0x78,0x5c}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x14,0x01,0x03,0x93,0xba,0x7f,0xc3,0x13}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x14,0x49,0x21,0xd9,0xa0,0x5e,0x32,0xf5}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x14,0x98,0x36,0xb6,0xa2,0x9b,0x12,0xa4}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x18,0x3d,0x36,0x49,0xb8,0xf5,0x35,0xd9}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x18,0x57,0x32,0x93,0x43,0x8b,0x73,0xde}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x18,0xb0,0x15,0xd3,0x43,0x1c,0xbf,0xec}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x18,0xb1,0x28,0x8b,0x51,0xc9,0xdb,0x37}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x18,0xd5,0x2a,0x37,0x68,0x06,0x97,0x97}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x1c,0x42,0x3a,0x1c,0x94,0x2f,0x7f,0x08}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x1c,0x7a,0x2f,0xb7,0xe7,0xd5,0x7e,0xe2}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x1c,0xc6,0x38,0xc6,0x43,0x8b,0x73,0xde}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x1c,0xd6,0x2f,0x48,0xfa,0x1b,0x51,0xc1}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x1c,0xda,0x2f,0xdf,0xb0,0x91,0xdb,0xe5}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x1c,0xf3,0x0b,0x9e,0xa1,0x4a,0x41,0xf3}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x20,0x15,0x04,0x73,0x9d,0x21,0xcc,0x3c}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x20,0x5d,0xee,0xa3,0xa3,0xc8,0xea,0x79}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x20,0x7c,0x19,0xb1,0xe7,0x58,0x1c,0x46}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x20,0xcb,0x06,0xb0,0x46,0xcc,0xc2,0x7d}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x20,0xcd,0x1c,0xd9,0x54,0xe6,0x5a,0x6e}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x20,0xef,0x0b,0xc1,0x95,0xf0,0xa6,0x58}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x24,0x09,0x2e,0xa4,0x47,0xee,0x3c,0x9d}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x24,0x27,0x33,0x0a,0x94,0x41,0xdc,0x2d}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x24,0x36,0x3c,0x78,0x43,0x1d,0xd5,0x59}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x24,0xdd,0x2a,0xcb,0xb8,0xa9,0x5a,0xde}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x28,0x69,0x2c,0xb3,0xb5,0x7b,0x31,0x1c}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x28,0xbf,0x33,0xd4,0x9d,0x29,0x8e,0xdc}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x28,0xe0,0x14,0x2e,0x3e,0xd6,0xb1,0x82}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x28,0xf3,0x16,0x75,0xc3,0xed,0x5b,0xe7}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x2c,0x4c,0x21,0xd6,0x94,0x6c,0xef,0x01}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x2c,0xd6,0x3f,0x49,0xa1,0xec,0x07,0x36}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x30,0x1d,0x1c,0xd6,0xba,0x5a,0x29,0x35}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x30,0x2b,0x34,0x0f,0xe7,0x23,0xb1,0x5e}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x30,0x34,0x2d,0x96,0xb5,0x7f,0xb0,0xe6}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x30,0x6b,0x08,0x72,0xb4,0xbc,0xd7,0x9f}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x30,0xa4,0x11,0x90,0x43,0x15,0x0e,0x53}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x30,0xc3,0x13,0x62,0x52,0x1f,0x52,0xc5}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x30,0xe7,0x3e,0x5c,0xda,0x3f,0x64,0x66}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x34,0x39,0x02,0x23,0xa0,0x4a,0xfd,0xfd}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x34,0x77,0x14,0xcd,0xf7,0xde,0xde,0xe8}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x34,0x98,0x01,0xa5,0x46,0x35,0x2b,0x50}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x34,0x9d,0x0d,0xb2,0xa0,0xe6,0x29,0xa2}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x34,0xf7,0x15,0xb2,0x30,0x12,0x3a,0x74}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x38,0x09,0x29,0x41,0x43,0x44,0x48,0x38}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x38,0x09,0x37,0xb7,0x31,0xb5,0x8e,0x3d}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x38,0x77,0x2d,0xac,0xb6,0x91,0x71,0x9c}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x38,0x8a,0x24,0xf3,0xa1,0x41,0xc1,0x94}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x38,0xba,0x3b,0x3e,0x43,0x0c,0xfb,0x74}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x38,0xc4,0x2f,0x2a,0x93,0x57,0xb1,0xae}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x38,0xe2,0x02,0x3f,0xb4,0xf6,0x6a,0xd1}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x3c,0x56,0x21,0x71,0x9d,0x80,0xd3,0x60}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x3c,0xab,0x14,0x21,0x3c,0xa4,0x1a,0x8e}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x00,0x3f,0x24,0x41,0x68,0x06,0x97,0x97}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x04,0x24,0x03,0x21,0x52,0xb3,0x56,0x33}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x04,0x7c,0x32,0xef,0xa7,0xa8,0xa2,0xb4}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x04,0xa7,0x3c,0xdd,0x9d,0x1b,0x07,0x08}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x04,0xc3,0x3a,0x54,0x9d,0x1c,0x2a,0xd7}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x08,0x13,0x3a,0xe3,0xbd,0xd2,0x66,0xd8}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x08,0x18,0x0c,0xf4,0x27,0xf2,0xb5,0xf5}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x08,0x55,0x33,0xf7,0x6d,0xbd,0x53,0xc4}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x08,0x68,0x1b,0xaa,0xb1,0x74,0xb7,0x64}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x08,0x78,0x21,0xcf,0x2b,0x5b,0x28,0x60}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x08,0xa4,0xe1,0xd1,0x79,0xec,0x7c,0xee}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x08,0xb3,0x39,0x2c,0xab,0x0d,0xae,0x6b}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x08,0xff,0x35,0x2f,0xb2,0x08,0x56,0x04}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x0c,0x2f,0x17,0x93,0xfa,0x42,0xac,0xdc}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x0c,0x36,0x02,0x5f,0xa0,0xd0,0xe8,0x71}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x00,0xd3,0x06,0x9e,0xd0,0xa0,0x1b,0x73}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x10,0x9f,0x37,0x9e,0xae,0xff,0x39,0x57}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x10,0xa5,0x2f,0x7d,0xab,0x07,0x9c,0x7b}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x14,0x62,0x3f,0xe1,0xb2,0xcf,0xdc,0xf0}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x18,0x0b,0x29,0xbe,0x34,0x29,0xfe,0xde}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x18,0x57,0x02,0x4c,0x46,0xf4,0x7d,0xc9}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x18,0xd5,0x0a,0x69,0x4b,0x4a,0x6e,0x8b}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x1c,0x20,0x25,0xa2,0x3f,0x5d,0x2d,0xa4}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x1c,0x96,0x24,0xdc,0xa7,0x53,0xd6,0xf2}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x1c,0xe7,0x05,0x33,0x26,0xf3,0x2a,0xab}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x20,0x65,0x30,0x08,0x76,0xb5,0xcb,0x06}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x20,0xb2,0x04,0x34,0x43,0x87,0xf5,0xe1}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x20,0xff,0x14,0x7c,0x84,0x0c,0xb0,0xdb}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x24,0x36,0x3c,0x96,0x91,0xe9,0x2d,0xe3}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x24,0x4c,0x18,0x17,0xae,0x9f,0x8a,0x38}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x28,0x4c,0x29,0xce,0x88,0xb5,0xc8,0x6f}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x28,0x5a,0x00,0x5c,0xc1,0x6b,0x11,0x9a}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x2c,0x5f,0x0a,0x51,0xa6,0x71,0x3d,0x90}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x30,0x65,0x32,0x55,0x4b,0x21,0xe5,0x20}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x34,0x1d,0x2d,0xfa,0x89,0x2f,0x43,0x66}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x34,0x50,0x30,0x2f,0x23,0xb3,0xa3,0x3a}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x34,0x56,0x23,0x08,0xd0,0xb5,0x79,0x70}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x34,0x70,0x34,0x6d,0xaf,0x23,0xd4,0x1b}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x34,0xba,0x20,0xc2,0x9a,0x5a,0xdd,0x02}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x38,0x46,0x11,0x33,0xa6,0x8c,0xea,0x80}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x38,0xef,0x31,0xea,0x6c,0xd1,0x45,0xdb}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x3c,0x1f,0xc3,0x5a,0xcc,0x00,0x28,0xd3}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x3c,0x49,0x15,0x39,0xfe,0x22,0x5b,0x3b}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x3c,0x5e,0x2e,0xcd,0x88,0xee,0x78,0x7c}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x3c,0x74,0x01,0x94,0x4f,0x94,0x0e,0x1b}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x04,0xc4,0x34,0x92,0x4d,0x56,0x35,0xdd}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x04,0xe7,0x35,0xf2,0xae,0x92,0xcb,0xcd}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x08,0x50,0x2b,0x2f,0xad,0xbf,0xfa,0x7e}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x08,0xba,0x0f,0x4f,0x3e,0x75,0xb0,0x0b}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x00,0x9e,0x32,0x94,0xc2,0xb5,0x67,0xd7}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x0c,0x74,0x08,0x1b,0xa2,0xfb,0xaa,0x90}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x78,0xcf,0x14,0x6b,0x2c,0xc2,0xb2,0xa5,0x0d,0xb7}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x78,0xcf,0x18,0xd3,0x16,0x02,0x2a,0x06,0xc5,0x62}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x78,0xcf,0x24,0xa7,0x0e,0xe0,0x72,0xcc,0x7f,0x75}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x78,0xcf,0x28,0x62,0x13,0x84,0xb4,0xb8,0x40,0x6f}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x78,0xcf,0x30,0xc4,0x36,0x98,0x92,0xa5,0x3a,0xf9}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x78,0xcf,0x34,0x0b,0x12,0x70,0x4d,0x61,0x08,0x57}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x78,0xcf,0x3c,0xb3,0x27,0x73,0x4d,0xa3,0x0d,0x4c}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x78,0xcf,0x3c,0xdf,0x08,0xab,0xa3,0x31,0x0d,0x75}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x78,0xcf,0x04,0xd1,0x36,0x6f,0x4f,0x91,0xea,0xfb}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x78,0xcf,0x08,0x3f,0x0b,0x1c,0xc1,0xa4,0xad,0x71}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x10,0x67,0x13,0xc5,0xa6,0x9c,0xb0,0x99}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x10,0xaa,0x20,0xc7,0xaa,0x6f,0xd3,0x18}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x10,0xdf,0x16,0xc3,0xb3,0x51,0xe8,0x24}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x14,0x64,0x25,0x5e,0x92,0x08,0x80,0x12}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x14,0xe1,0x01,0xb8,0xb2,0x56,0xff,0x4c}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x18,0x0c,0x0e,0xbf,0x2a,0x63,0x93,0xc0}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x18,0xfb,0x09,0xd7,0xaf,0x8d,0xa5,0xd5}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x1c,0xa1,0x3e,0x8e,0xab,0x02,0xed,0xbe}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x1c,0xd7,0x3f,0xe8,0xe8,0x0f,0x53,0xf9}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x20,0xd8,0x10,0x62,0x26,0x84,0x32,0xc2}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x24,0x19,0x37,0x3e,0xda,0x40,0x1e,0x51}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x24,0x2b,0x1a,0xc2,0xfd,0xcc,0xaf,0x6a}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x24,0x42,0x2d,0x34,0x9e,0x97,0x36,0xa0}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x24,0x6c,0x24,0xf1,0x3c,0x0f,0x65,0xfc}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x24,0xc4,0x15,0xe7,0xd0,0xcb,0x7a,0x52}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x28,0x37,0x32,0x4e,0xd0,0xcb,0x9f,0x45}, 22475}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x28,0x58,0x2d,0x7c,0xbc,0x51,0x6e,0xe0}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x28,0x9e,0x1b,0x03,0x43,0x8e,0xb5,0x17}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x28,0x9f,0x30,0xfc,0x54,0xbc,0x96,0x85}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x28,0xa2,0x07,0x60,0xa6,0xb3,0x31,0x39}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x28,0xa4,0x1b,0x25,0xb8,0xc7,0x38,0xff}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x28,0xd3,0x10,0x49,0xfd,0x91,0x71,0x2c}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x2c,0x32,0x2d,0xa7,0xc1,0x11,0xdd,0x82}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x2c,0x91,0x1e,0x07,0x5d,0x3d,0x7e,0xb1}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x2c,0xe5,0x03,0xc7,0xb7,0x36,0x91,0x28}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x2c,0xf4,0x30,0xd4,0xe0,0x20,0x53,0xfa}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x2c,0xfc,0x22,0x21,0x98,0xe5,0xee,0xd7}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x30,0x16,0x0a,0xed,0x61,0x07,0x04,0xdf}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x30,0x3e,0x3e,0x8a,0xd0,0x6a,0xd1,0x37}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x30,0xee,0x19,0xd6,0x6e,0x7b,0x90,0x8e}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x34,0x2c,0x3e,0xcc,0xc2,0xa2,0x1e,0x31}, 8333}, {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x34,0x74,0x1d,0xf1,0xe7,0x32,0xe5,0xe3}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x38,0xc4,0x37,0xaf,0xab,0x0a,0xf5,0xef}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x00,0x3a,0x39,0xfd,0xa4,0x3b,0x55,0x91}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x3c,0x9d,0x2a,0x45,0xd5,0x37,0x3b,0xd6}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x3c,0xfb,0x2c,0xf5,0x52,0x54,0x4d,0x1e}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x04,0x3f,0x03,0x37,0xad,0xb4,0x63,0x10}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x04,0x93,0x09,0x95,0xd2,0xe9,0x39,0xbe}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x00,0x5b,0x0c,0xe3,0xb2,0x75,0x92,0xab}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x08,0xa8,0x05,0x9d,0xd0,0xcb,0xd5,0x85}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x0c,0x8e,0x1b,0xa0,0xc5,0xa9,0xda,0xce}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x0c,0xdb,0x36,0x5f,0x23,0x02,0xf7,0x29}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x0c,0xf5,0x22,0x2e,0x89,0x3e,0x71,0x6c}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x00,0xd6,0x10,0x85,0xb8,0xdd,0x41,0xc2}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x10,0x1a,0x23,0xb3,0x6b,0x98,0xf8,0x88}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x18,0x05,0x0f,0x38,0x3e,0xb2,0x21,0x21}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x18,0x58,0x16,0xf9,0x38,0x33,0xda,0x19}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x18,0xea,0x27,0x35,0xe7,0x3d,0xad,0xc5}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x34,0x96,0x2e,0x2d,0xcb,0x17,0xc3,0xbd}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x34,0xf3,0x35,0x84,0xd0,0xa4,0x0a,0xa5}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x38,0xe6,0x10,0x92,0xd0,0xcb,0x75,0x76}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x38,0xec,0x06,0x11,0xe0,0x5f,0xdf,0x3d}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x38,0xf5,0x39,0x38,0xb4,0x54,0x47,0x17}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x38,0xf8,0x14,0xce,0x88,0x09,0x77,0x86}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x3c,0x2c,0x10,0xa4,0xbb,0xfa,0xe0,0x9d}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x3c,0x35,0x2a,0x8e,0xe7,0x9f,0x62,0xfd}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x3c,0x40,0x07,0x7b,0xc2,0xbb,0x00,0x79}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x00,0x65,0x2a,0xdf,0xb8,0xde,0x17,0x81}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x00,0x7c,0x01,0x29,0xd0,0xcb,0x6e,0x8b}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x08,0x51,0x10,0xd8,0x9d,0x58,0x70,0x59}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x08,0x5d,0x01,0x02,0x2a,0xa2,0x51,0x9a}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x08,0x96,0x0f,0xe0,0xaf,0xc6,0x22,0x70}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x08,0xa0,0x22,0xcc,0xa0,0xb3,0xd9,0xda}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x0c,0x0d,0x0d,0xe2,0xb9,0x4f,0x07,0x74}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x0c,0xff,0x0c,0x79,0xaa,0x69,0xcb,0x82}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x10,0x4e,0x08,0xaf,0xb3,0xaa,0xf3,0x00}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x10,0x63,0x10,0xc4,0x93,0xfd,0x77,0xb5}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x10,0xdd,0x3d,0x0d,0xda,0xee,0xcc,0xda}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x18,0x83,0x22,0xe3,0xaf,0x92,0x33,0xc7}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x1c,0x0a,0x15,0x83,0x94,0x73,0x5f,0x2e}, 8333}, {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x1c,0x44,0x2b,0x70,0x9d,0xe7,0xa7,0xcc}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x20,0x0a,0x3f,0x95,0xbb,0x7c,0xc0,0x9f}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x20,0x0c,0x34,0x73,0xb8,0x5d,0x0d,0xdd}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x20,0x0f,0x05,0xa0,0x47,0xc6,0x55,0x07}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x20,0x97,0x20,0x4a,0x47,0xc5,0x58,0x81}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x24,0x8f,0x24,0xcd,0xaa,0xf5,0xde,0xe3}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x28,0x7d,0x16,0x8e,0x3c,0xaf,0x47,0xaf}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x28,0xc1,0x05,0x8d,0xb7,0x21,0x94,0xc1}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x2c,0x31,0x30,0xa3,0x39,0xd3,0x05,0x28}, 8188}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x2c,0x3d,0x30,0x9b,0xd2,0xdb,0x82,0x88}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x2c,0x47,0x1b,0x36,0x52,0xc1,0x3c,0x73}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x30,0x4a,0x10,0xe1,0xb7,0x39,0x82,0x2a}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x30,0xa3,0x29,0xfd,0x33,0xf6,0xea,0xab}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x34,0x27,0x85,0x9b,0xb5,0x25,0x10,0x69}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x34,0x59,0x25,0x41,0x36,0x51,0xd6,0x75}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x04,0xf5,0x9c,0x88,0xaf,0x91,0xd3,0xd3}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x0c,0xd1,0x1d,0x54,0xb8,0x0a,0x42,0xf4}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x0c,0xfa,0x37,0xe6,0x9d,0x8e,0x74,0x74}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x1c,0xbb,0x06,0x46,0xd2,0xcf,0xfd,0x00}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x20,0x51,0x34,0x8d,0xdc,0x5a,0xc3,0xc2}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x24,0xf8,0x19,0x8a,0xd0,0x23,0x65,0x80}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x2c,0x32,0x2e,0xa8,0xb8,0x17,0x2b,0xb0}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x2c,0x6d,0x3c,0xef,0x43,0x86,0x49,0x37}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x2c,0xb1,0x17,0x19,0x53,0x98,0xe4,0x44}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x30,0x53,0x8a,0x5e,0x25,0xe4,0x35,0x2d}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x30,0x7b,0x23,0x09,0xb3,0x47,0x3f,0xdc}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x30,0x84,0x1e,0x46,0x8a,0x72,0x75,0x0f}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x30,0xa8,0x23,0x04,0x9d,0x47,0x7f,0xdf}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x30,0xb9,0x2e,0xa0,0xe8,0x0c,0x53,0xe5}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x30,0xcf,0x3e,0x04,0xa8,0x8b,0x4f,0xe8}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x34,0x27,0x2c,0x62,0xbd,0x53,0xf1,0x2d}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x34,0x45,0x1b,0xcb,0xb8,0xb5,0x96,0x53}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x38,0x74,0x29,0x5f,0x9d,0xe2,0xcf,0x3c}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x38,0xbc,0x03,0xf1,0x52,0xc4,0xea,0x47}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x38,0xc9,0x39,0x4f,0xbe,0xa2,0xfd,0x60}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x38,0xe8,0x23,0x91,0xb6,0xb2,0x90,0xc1}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x3c,0x43,0x03,0xf1,0xb4,0x89,0xf8,0xb8}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x04,0xc5,0x2a,0xe2,0xb6,0x43,0x38,0x66}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x04,0xdb,0x3a,0x7f,0x87,0xb0,0xf8,0x76}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x08,0xbe,0x0c,0xe8,0xb8,0xc5,0x52,0x12}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x00,0xac,0x2e,0xab,0x2f,0x99,0x80,0xc4}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x0c,0x0a,0x19,0x23,0x52,0xa0,0x7a,0xb2}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x00,0xc2,0x17,0x15,0xb8,0x0b,0x71,0x21}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x0c,0x8c,0x0e,0xe1,0x51,0x99,0xbf,0x8a}, 8333}, + {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x0c,0xbb,0x03,0xf5,0xa6,0x70,0xb0,0x45}, 8333}, + {{0x20,0x01,0x13,0xd8,0x1c,0x01,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08}, 8333}, {{0x20,0x01,0x13,0xd8,0x1c,0x01,0x20,0x00,0x24,0x70,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x20,0x01,0x14,0x70,0xff,0xfd,0x20,0x2c,0x02,0x25,0x90,0xff,0xfe,0x8f,0x5f,0x62}, 8333}, - {{0x20,0x01,0x14,0xba,0x02,0x00,0x00,0x00,0x54,0x3c,0x42,0xce,0xa4,0x8b,0xb0,0xd0}, 8333}, - {{0x20,0x01,0x14,0xba,0x02,0xfc,0x07,0x00,0x41,0xb2,0xdf,0x51,0xef,0xd8,0xf5,0x81}, 8333}, + {{0x20,0x01,0x14,0xba,0x19,0x00,0x00,0x00,0x00,0x00,0x07,0x54,0xf2,0x71,0x15,0x1c}, 8333}, + {{0x20,0x01,0x16,0x08,0x00,0x10,0x01,0x56,0x00,0x38,0x00,0x00,0x00,0x00,0x26,0x5c}, 8333}, + {{0x20,0x01,0x16,0x20,0x09,0x23,0x00,0x00,0x75,0xbe,0xed,0x92,0x1a,0x01,0x06,0x41}, 8333}, + {{0x20,0x01,0x16,0x80,0x01,0x01,0x00,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x20,0x01,0x18,0x38,0x20,0x00,0x04,0x13,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03}, 8333}, + {{0x20,0x01,0x19,0xc0,0x00,0x01,0x08,0x01,0x08,0x01,0xff,0x00,0x04,0x6c,0x00,0x02}, 8333}, + {{0x20,0x01,0x19,0xf0,0x00,0x00,0x20,0x4f,0x54,0x00,0x00,0xff,0xfe,0x05,0x2d,0x2e}, 8333}, {{0x20,0x01,0x19,0xf0,0x50,0x00,0x8c,0x8b,0x54,0x00,0x00,0xff,0xfe,0x1f,0xc0,0x23}, 8333}, - {{0x20,0x01,0x19,0xf0,0x00,0x05,0x07,0x49,0x54,0x00,0x00,0xff,0xfe,0x71,0xc3,0xfc}, 8333}, - {{0x20,0x01,0x19,0xf0,0x00,0x05,0x00,0xbc,0x54,0x00,0x00,0xff,0xfe,0x3b,0x93,0x39}, 8333}, - {{0x20,0x01,0x19,0xf0,0x74,0x02,0x04,0x2c,0x54,0x00,0x00,0xff,0xfe,0x6c,0xb9,0xb8}, 8333}, - {{0x20,0x01,0x1a,0xf8,0x40,0x10,0xa0,0x8f,0xf8,0x11,0xe5,0xf0,0x3f,0x63,0xe7,0x53}, 8333}, - {{0x20,0x01,0x1a,0xf8,0x40,0x10,0xa0,0x94,0x33,0x33,0x00,0x00,0x00,0x00,0x8c,0x38}, 8333}, + {{0x20,0x01,0x19,0xf0,0x00,0x05,0x17,0xa7,0x54,0x00,0x00,0xff,0xfe,0x87,0xcc,0x21}, 8333}, + {{0x20,0x01,0x19,0xf0,0x5c,0x01,0x06,0x3b,0x54,0x00,0x01,0xff,0xfe,0x47,0x2e,0xde}, 8333}, + {{0x20,0x01,0x19,0xf0,0xac,0x01,0x02,0xfb,0x54,0x00,0x00,0xff,0xfe,0x5b,0xc3,0xff}, 8333}, {{0x20,0x01,0x1a,0xf8,0x40,0x70,0xa0,0x16,0x33,0x33,0x00,0x00,0x00,0x00,0x5a,0xfb}, 8333}, {{0x20,0x01,0x1a,0xf8,0x47,0x00,0xa0,0x71,0x44,0x44,0x00,0x00,0x00,0x00,0xe2,0x6e}, 8333}, - {{0x20,0x01,0x1b,0xc8,0x01,0xa0,0x59,0x0e,0x02,0xe0,0xf4,0xff,0xfe,0x16,0x3a,0x39}, 8333}, - {{0x20,0x01,0x20,0x40,0x00,0x77,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x89}, 8333}, - {{0x20,0x01,0x02,0x88,0x10,0x01,0x01,0x07,0x29,0x4e,0x55,0x81,0x74,0xbd,0x42,0xf9}, 8333}, - {{0x20,0x01,0x03,0xc8,0xc1,0x03,0xa0,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48}, 8333}, + {{0x20,0x01,0x1b,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xaa,0xaa,0x00,0x21}, 8333}, + {{0x20,0x01,0x02,0x00,0x00,0x00,0x88,0x01,0x50,0x54,0x00,0xff,0xfe,0xf2,0x01,0xd0}, 8333}, {{0x20,0x01,0x41,0x28,0x61,0x35,0x00,0x10,0x02,0x0c,0x29,0xff,0xfe,0x69,0x9e,0x81}, 8333}, {{0x20,0x01,0x41,0x28,0x61,0x35,0x20,0x10,0x02,0x1e,0x0b,0xff,0xfe,0xe8,0xa3,0xc0}, 8333}, {{0x20,0x01,0x41,0x28,0x61,0x35,0xe0,0x01,0x50,0x54,0x00,0xff,0xfe,0x37,0xe9,0xeb}, 8333}, {{0x20,0x01,0x41,0x78,0x00,0x06,0x14,0x27,0x00,0x62,0x01,0x16,0x01,0x88,0x00,0x85}, 8333}, - {{0x20,0x01,0x41,0xd0,0x10,0x04,0x20,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, + {{0x20,0x01,0x41,0xc9,0x00,0x01,0x04,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x31}, 8333}, + {{0x20,0x01,0x41,0xd0,0x10,0x00,0x1e,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, + {{0x20,0x01,0x41,0xd0,0x10,0x04,0x1f,0xef,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, + {{0x20,0x01,0x41,0xd0,0x10,0x04,0x24,0xa5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, + {{0x20,0x01,0x41,0xd0,0x10,0x08,0x1c,0x23,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, {{0x20,0x01,0x41,0xd0,0x10,0x08,0x27,0x52,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, - {{0x20,0x01,0x41,0xd0,0x00,0x01,0x47,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x20,0x01,0x41,0xd0,0x00,0x01,0x6f,0x57,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x20,0x01,0x41,0xd0,0x00,0x01,0x73,0x53,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x20,0x01,0x41,0xd0,0x00,0x01,0x74,0x69,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x20,0x01,0x41,0xd0,0x00,0x01,0x45,0xd8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, {{0x20,0x01,0x41,0xd0,0x00,0x01,0x7d,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x20,0x01,0x41,0xd0,0x00,0x01,0x81,0x13,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x20,0x01,0x41,0xd0,0x00,0x01,0x86,0x49,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, {{0x20,0x01,0x41,0xd0,0x00,0x01,0x8b,0x26,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x20,0x01,0x41,0xd0,0x00,0x01,0xc1,0x29,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x20,0x01,0x41,0xd0,0x00,0x01,0xa5,0xb8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x20,0x01,0x41,0xd0,0x00,0x01,0xab,0x6b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x20,0x01,0x41,0xd0,0x00,0x01,0xaf,0xd8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, + {{0x20,0x01,0x41,0xd0,0x00,0x01,0xb4,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x20,0x01,0x41,0xd0,0x00,0x01,0xb5,0xce,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, {{0x20,0x01,0x41,0xd0,0x00,0x01,0xd2,0x27,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, + {{0x20,0x01,0x41,0xd0,0x00,0x01,0xda,0xbd,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, {{0x20,0x01,0x41,0xd0,0x00,0x01,0xe1,0x3b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x20,0x01,0x41,0xd0,0x00,0x01,0xe6,0x23,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x20,0x01,0x41,0xd0,0x00,0x01,0xf1,0x76,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x20,0x01,0x41,0xd0,0x02,0x03,0x10,0xbd,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, {{0x20,0x01,0x41,0xd0,0x00,0x02,0x16,0xbe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x20,0x01,0x41,0xd0,0x00,0x02,0x20,0x3c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x20,0x01,0x41,0xd0,0x00,0x02,0x32,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, - {{0x20,0x01,0x41,0xd0,0x00,0x02,0x8a,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, + {{0x20,0x01,0x41,0xd0,0x00,0x02,0x53,0xdf,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, {{0x20,0x01,0x41,0xd0,0x00,0x02,0x8c,0x65,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, - {{0x20,0x01,0x41,0xd0,0x00,0x02,0x8d,0x13,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, - {{0x20,0x01,0x41,0xd0,0x00,0x02,0x94,0x59,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, - {{0x20,0x01,0x41,0xd0,0x00,0x02,0x95,0x0a,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x03}, 8333}, + {{0x20,0x01,0x41,0xd0,0x00,0x02,0x94,0x31,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, {{0x20,0x01,0x41,0xd0,0x00,0x02,0x9c,0x94,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x20,0x01,0x41,0xd0,0x00,0x02,0xa2,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, - {{0x20,0x01,0x41,0xd0,0x00,0x02,0xa2,0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, - {{0x20,0x01,0x41,0xd0,0x00,0x02,0xab,0x1c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, - {{0x20,0x01,0x41,0xd0,0x00,0x02,0xbf,0x2a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, - {{0x20,0x01,0x41,0xd0,0x00,0x02,0xc7,0x93,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, + {{0x20,0x01,0x41,0xd0,0x00,0x02,0xa5,0xa9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, + {{0x20,0x01,0x41,0xd0,0x00,0x02,0xab,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, + {{0x20,0x01,0x41,0xd0,0x00,0x02,0x0c,0x6e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, + {{0x20,0x01,0x41,0xd0,0x00,0x02,0xc9,0xbf,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, {{0x20,0x01,0x41,0xd0,0x03,0x02,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfa,0x25}, 8333}, + {{0x20,0x01,0x41,0xd0,0x03,0x03,0x01,0x88,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, {{0x20,0x01,0x41,0xd0,0x03,0x03,0x19,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, + {{0x20,0x01,0x41,0xd0,0x03,0x03,0x25,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1a}, 8333}, + {{0x20,0x01,0x41,0xd0,0x03,0x03,0x41,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, + {{0x20,0x01,0x41,0xd0,0x03,0x03,0x0d,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, + {{0x20,0x01,0x41,0xd0,0x04,0x03,0x05,0x89,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, {{0x20,0x01,0x41,0xd0,0x00,0x52,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0xe2}, 8333}, {{0x20,0x01,0x41,0xd0,0x00,0x52,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0xe3}, 8333}, + {{0x20,0x01,0x41,0xd0,0x06,0x02,0x00,0x3b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, + {{0x20,0x01,0x41,0xd0,0x06,0x02,0x06,0xca,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, + {{0x20,0x01,0x41,0xd0,0x06,0x02,0x00,0xe0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, + {{0x20,0x01,0x41,0xd0,0x06,0x04,0x01,0x77,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, + {{0x20,0x01,0x41,0xd0,0x07,0x00,0x04,0x68,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, + {{0x20,0x01,0x41,0xd0,0x07,0x00,0x04,0x79,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, + {{0x20,0x01,0x41,0xd0,0x08,0x00,0x02,0x83,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, {{0x20,0x01,0x41,0xd0,0x00,0x08,0x1b,0x29,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, - {{0x20,0x01,0x41,0xd0,0x00,0x08,0x3d,0x4b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x20,0x01,0x41,0xd0,0x00,0x08,0x4d,0x4d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x20,0x01,0x41,0xd0,0x00,0x08,0x25,0x56,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, {{0x20,0x01,0x41,0xd0,0x00,0x08,0x7a,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x20,0x01,0x41,0xd0,0x00,0x08,0x80,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, {{0x20,0x01,0x41,0xd0,0x00,0x08,0x8f,0x46,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x20,0x01,0x41,0xd0,0x00,0x08,0xba,0x87,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x20,0x01,0x41,0xd0,0x00,0x08,0xbd,0x45,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x20,0x01,0x41,0xd0,0x00,0x08,0x9c,0x6e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x20,0x01,0x41,0xd0,0x00,0x08,0xb3,0xad,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x20,0x01,0x41,0xd0,0x00,0x08,0xb7,0xd0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, {{0x20,0x01,0x41,0xd0,0x00,0x08,0xbe,0xd3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, {{0x20,0x01,0x41,0xd0,0x00,0x08,0xc6,0x7c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, + {{0x20,0x01,0x41,0xd0,0x00,0x08,0xd4,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, {{0x20,0x01,0x41,0xd0,0x00,0x08,0xd8,0x44,0x13,0x37,0x00,0x00,0x00,0x00,0x10,0x17}, 8333}, + {{0x20,0x01,0x41,0xd0,0x00,0x08,0xdb,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, {{0x20,0x01,0x41,0xd0,0x00,0x08,0x0d,0xdb,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, {{0x20,0x01,0x41,0xd0,0x00,0x08,0x0d,0xdf,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x20,0x01,0x41,0xd0,0x00,0x08,0xde,0x3d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, {{0x20,0x01,0x41,0xd0,0x00,0x08,0xe3,0xe4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x20,0x01,0x41,0xd0,0x00,0x0a,0x4e,0x3f,0x00,0x00,0x00,0x00,0x1c,0x7d,0x6b,0x01}, 8333}, + {{0x20,0x01,0x41,0xd0,0x00,0x0a,0x3b,0x5f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x20,0x01,0x41,0xd0,0x00,0x0a,0x40,0x5c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, {{0x20,0x01,0x41,0xd0,0x00,0x0a,0x63,0x5b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x20,0x01,0x41,0xd0,0x00,0x0a,0x68,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x20,0x01,0x41,0xd0,0x00,0x0a,0x6a,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x20,0x01,0x41,0xd0,0x00,0x0a,0x06,0xa1,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, {{0x20,0x01,0x41,0xd0,0x00,0x0a,0x6c,0x29,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, {{0x20,0x01,0x41,0xd0,0x00,0x0a,0x6f,0xd0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, - {{0x20,0x01,0x41,0xd0,0x00,0x0a,0xfa,0xc7,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x20,0x01,0x41,0xd0,0x00,0x0d,0x11,0x1c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, - {{0x20,0x01,0x41,0xd0,0x00,0x0d,0x2a,0xc8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, + {{0x20,0x01,0x41,0xd0,0x00,0x0a,0x07,0x55,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x20,0x01,0x41,0xd0,0x00,0x0a,0xf8,0xd2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x20,0x01,0x41,0xd0,0x00,0x0a,0xf9,0x15,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x20,0x01,0x41,0xd0,0x00,0x0e,0x11,0x46,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, {{0x20,0x01,0x41,0xd0,0x00,0x0e,0x13,0x88,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x20,0x01,0x41,0xd0,0x00,0x0e,0x02,0x6b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x20,0x01,0x41,0xd0,0x00,0x0e,0x09,0xe7,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x20,0x01,0x41,0xd0,0x00,0x0e,0x0e,0xc5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, {{0x20,0x01,0x41,0xf0,0x00,0x61,0x00,0x00,0x72,0xf3,0x95,0xff,0xfe,0x09,0x75,0x21}, 8333}, {{0x20,0x01,0x41,0xf0,0x00,0x61,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07}, 8333}, - {{0x20,0x01,0x04,0x70,0x1f,0x07,0x15,0x1c,0xba,0xac,0x6f,0xff,0xfe,0xb7,0x3b,0xa9}, 8333}, + {{0x20,0x01,0x46,0x42,0xe5,0x27,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xbe,0xef}, 8333}, + {{0x20,0x01,0x04,0x70,0x00,0x1d,0x08,0xa9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, + {{0x20,0x01,0x04,0x70,0x00,0x1d,0x08,0xa9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04}, 8333}, + {{0x20,0x01,0x04,0x70,0x1f,0x06,0x15,0xb4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x20,0x01,0x04,0x70,0x1f,0x07,0x08,0x03,0x02,0x0c,0x29,0xff,0xfe,0x2d,0x58,0x79}, 8333}, + {{0x20,0x01,0x04,0x70,0x1f,0x09,0x03,0x25,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40}, 8333}, + {{0x20,0x01,0x04,0x70,0x1f,0x0b,0x05,0x6e,0x7e,0x5c,0xf8,0xff,0xfe,0x32,0x53,0x02}, 8333}, {{0x20,0x01,0x04,0x70,0x1f,0x0b,0x08,0xc4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05}, 8333}, + {{0x20,0x01,0x04,0x70,0x1f,0x0b,0x08,0xfe,0x00,0xc4,0x43,0x38,0xe5,0x28,0x27,0x13}, 8333}, {{0x20,0x01,0x04,0x70,0x1f,0x0b,0x09,0x67,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11}, 8333}, + {{0x20,0x01,0x04,0x70,0x1f,0x10,0x07,0x76,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, {{0x20,0x01,0x04,0x70,0x1f,0x15,0x11,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10}, 8333}, {{0x20,0x01,0x04,0x70,0x1f,0x15,0x1b,0x95,0x2c,0x3e,0x8a,0x9a,0x24,0xe1,0x70,0x84}, 8333}, - {{0x20,0x01,0x04,0x70,0x1f,0x15,0x0f,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03}, 8333}, - {{0x20,0x01,0x04,0x70,0x1f,0x1a,0x01,0x72,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x20,0x01,0x04,0x70,0x1f,0x1c,0x0b,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x20,0x01,0x04,0x70,0x1f,0x1d,0x03,0xa9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10}, 8333}, + {{0x20,0x01,0x04,0x70,0x1f,0x15,0x0c,0xf7,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14}, 8333}, + {{0x20,0x01,0x04,0x70,0x1f,0x15,0x0e,0x9b,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xef}, 8333}, + {{0x20,0x01,0x04,0x70,0x1f,0x17,0x02,0x2a,0x08,0xd2,0x72,0xbf,0xa5,0x64,0x21,0xfb}, 8333}, + {{0x20,0x01,0x04,0x70,0x1f,0x17,0x00,0xb5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10}, 8333}, + {{0x20,0x01,0x04,0x70,0x1f,0x1b,0x05,0xa6,0x02,0x16,0x3e,0xff,0xfe,0x24,0x11,0x62}, 8333}, + {{0x20,0x01,0x04,0x70,0x21,0x79,0xde,0xad,0xde,0xaf,0x00,0x00,0x2e,0x70,0x9d,0x8b}, 8333}, {{0x20,0x01,0x04,0x70,0x00,0x25,0x04,0x82,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x20,0x01,0x04,0x70,0x00,0x28,0x03,0x65,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04}, 8333}, - {{0x20,0x01,0x04,0x70,0x75,0x4f,0x00,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x7a}, 8333}, + {{0x20,0x01,0x04,0x70,0x00,0x27,0x04,0x83,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, {{0x20,0x01,0x04,0x70,0x00,0x07,0x0b,0x74,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x20,0x01,0x04,0x70,0x7d,0xda,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x20,0x01,0x04,0x70,0x00,0x08,0x0c,0x70,0x02,0x0c,0x29,0xff,0xfe,0x6a,0x8f,0xdc}, 8333}, - {{0x20,0x01,0x04,0x70,0x00,0x08,0x0c,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x54}, 8333}, + {{0x20,0x01,0x04,0x70,0x00,0x08,0x02,0xe1,0x44,0xff,0x65,0x4e,0xe5,0x3e,0xad,0x59}, 8333}, + {{0x20,0x01,0x04,0x70,0x00,0x08,0x02,0xe1,0x70,0x58,0x53,0xf6,0x56,0x81,0x5b,0xe4}, 8333}, + {{0x20,0x01,0x04,0x70,0x00,0x08,0x02,0xe1,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x43}, 8333}, + {{0x20,0x01,0x04,0x70,0x00,0x08,0x07,0xb3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x17}, 8333}, + {{0x20,0x01,0x04,0x70,0x8a,0x2f,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe9,0x98}, 8333}, + {{0x20,0x01,0x04,0x70,0xa0,0x68,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x20,0x01,0x04,0x70,0x00,0x0a,0x08,0x8b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, {{0x20,0x01,0x04,0x70,0x00,0x0a,0x0c,0x13,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x20,0x01,0x04,0x70,0xb3,0xd5,0x00,0x01,0x64,0x1c,0x6b,0xff,0xfe,0x9d,0xbc,0xcf}, 8333}, + {{0x20,0x01,0x04,0x70,0xc1,0x44,0xca,0xfe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x09}, 8333}, {{0x20,0x01,0x04,0x70,0xd0,0x0d,0x00,0x00,0x36,0x64,0xa9,0xff,0xfe,0x9a,0x51,0x50}, 8333}, {{0x20,0x01,0x04,0x70,0xdb,0xf2,0xaa,0xaa,0x00,0x00,0x00,0x00,0x0b,0x17,0xc0,0x1c}, 8333}, - {{0x20,0x01,0x04,0x70,0xf4,0x57,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa6}, 8333}, - {{0x20,0x01,0x48,0x01,0x78,0x19,0x00,0x74,0xb7,0x45,0xb9,0xd5,0xff,0x10,0xa6,0x1a}, 8333}, - {{0x20,0x01,0x48,0x01,0x78,0x19,0x00,0x74,0xb7,0x45,0xb9,0xd5,0xff,0x10,0xaa,0xec}, 8333}, - {{0x20,0x01,0x48,0x01,0x78,0x28,0x01,0x04,0xbe,0x76,0x4e,0xff,0xfe,0x10,0x13,0x25}, 8333}, - {{0x20,0x01,0x4b,0xa0,0xca,0xfe,0x13,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x20,0x01,0x4b,0xa0,0xca,0xfe,0x04,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x20,0x01,0x05,0x58,0x60,0x45,0x00,0x23,0x18,0x30,0x89,0x6c,0xd9,0x01,0x19,0x0d}, 8333}, - {{0x20,0x01,0x06,0x7c,0x12,0x20,0x08,0x0c,0x00,0x00,0x00,0x00,0x93,0xe5,0x0d,0xd2}, 8333}, - {{0x20,0x01,0x06,0x7c,0x21,0x28,0xff,0xff,0x60,0x62,0x36,0xff,0xfe,0x30,0x65,0x32}, 8333}, - {{0x20,0x01,0x08,0xd8,0x09,0x23,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x87,0x0e,0xbd}, 8333}, - {{0x20,0x01,0x09,0x81,0x44,0x52,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00}, 8333}, - {{0x20,0x01,0x09,0x81,0x00,0x46,0x00,0x01,0xba,0x27,0xeb,0xff,0xfe,0x5b,0xed,0xee}, 8333}, - {{0x20,0x01,0x09,0x81,0xbd,0xbd,0x00,0x01,0xc5,0x06,0x7d,0x38,0x4b,0x47,0xda,0x15}, 8333}, + {{0x20,0x01,0x48,0x02,0x78,0x02,0x01,0x03,0xbe,0x76,0x4e,0xff,0xfe,0x21,0x19,0xf9}, 8333}, + {{0x20,0x01,0x48,0xf8,0x10,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xba}, 8333}, + {{0x20,0x01,0x4b,0x99,0x00,0x01,0x00,0x01,0x02,0x16,0x3e,0xff,0xfe,0xbd,0x85,0xba}, 8333}, + {{0x20,0x01,0x4b,0xa0,0xba,0xbe,0x26,0x81,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, + {{0x20,0x01,0x4b,0xa0,0xba,0xbe,0x08,0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, + {{0x20,0x01,0x4b,0xa0,0xca,0xfe,0x02,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x20,0x01,0x05,0x79,0x92,0x84,0x00,0xbc,0x10,0xbe,0x5d,0xf1,0xf6,0xd2,0x41,0x94}, 8333}, + {{0x20,0x01,0x06,0x38,0xa0,0x00,0x41,0x40,0x00,0x00,0x00,0x00,0xff,0x10,0x04,0x15}, 8333}, + {{0x20,0x01,0x06,0x38,0xa0,0x00,0x41,0x40,0x00,0x00,0x00,0x00,0xff,0xff,0x01,0x91}, 8333}, + {{0x20,0x01,0x06,0x7c,0x25,0x64,0x05,0x20,0x78,0x00,0x48,0x17,0x52,0xec,0x0d,0x8f}, 8333}, + {{0x20,0x01,0x07,0x08,0x01,0x50,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x43,0x29}, 8333}, + {{0x20,0x01,0x09,0x80,0x23,0x1b,0x00,0x01,0x8e,0x89,0xa5,0xff,0xfe,0xe3,0xf8,0xbe}, 8333}, + {{0x20,0x01,0x09,0x80,0xad,0xe8,0x00,0x01,0x14,0xfc,0xfd,0x6d,0x60,0x8c,0xf6,0x69}, 8333}, + {{0x20,0x01,0x09,0x84,0xae,0xc7,0x00,0x01,0xdc,0xb7,0x02,0x9a,0x7e,0xda,0xb9,0xa2}, 8333}, {{0x20,0x01,0x09,0x85,0x79,0xaf,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x35}, 8333}, {{0x20,0x01,0x0b,0xc8,0x22,0x5f,0x01,0x0e,0x05,0x05,0x65,0x73,0x75,0x73,0x0d,0x0a}, 8333}, - {{0x20,0x01,0x0b,0xc8,0x32,0x3c,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x53}, 8333}, - {{0x20,0x01,0x0b,0xc8,0x32,0x3c,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x04}, 8333}, - {{0x20,0x01,0x0b,0xc8,0x32,0x3c,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xca,0xfe}, 8333}, - {{0x20,0x01,0x0b,0xc8,0x36,0x80,0x42,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x20,0x01,0x0b,0xc8,0x32,0x3c,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, {{0x20,0x01,0x0b,0xc8,0x39,0x9f,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x20,0x02,0x01,0xe2,0x55,0x87,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xe2,0x55,0x87}, 8333}, - {{0x20,0x02,0x01,0xe2,0x55,0x88,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xe2,0x55,0x88}, 8333}, - {{0x20,0x02,0x2a,0x33,0x21,0xc4,0x00,0x00,0x00,0x00,0x00,0x00,0x2a,0x33,0x21,0xc4}, 8333}, + {{0x20,0x01,0x0b,0xc8,0x3c,0xbf,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05}, 8333}, + {{0x20,0x01,0x0b,0xc8,0x44,0x00,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x0f}, 8333}, + {{0x20,0x02,0x26,0x1b,0x64,0x2c,0x00,0x00,0x00,0x00,0x00,0x00,0x26,0x1b,0x64,0x2c}, 8333}, + {{0x20,0x02,0x29,0x56,0x68,0x5e,0x00,0x00,0x00,0x00,0x00,0x00,0x29,0x56,0x68,0x5e}, 8333}, + {{0x20,0x02,0x2d,0x7b,0x67,0x4f,0x00,0x00,0x00,0x00,0x00,0x00,0x2d,0x7b,0x67,0x4f}, 8333}, + {{0x20,0x02,0x2d,0xf9,0x5e,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x2d,0xf9,0x5e,0x40}, 8333}, {{0x20,0x02,0x2e,0x04,0x78,0x4b,0x00,0x00,0x00,0x00,0x00,0x00,0x2e,0x04,0x78,0x4b}, 8333}, - {{0x20,0x02,0x2e,0xbc,0x2c,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x16}, 8333}, + {{0x20,0x02,0x2f,0x58,0xfe,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x2f,0x58,0xfe,0x42}, 8333}, + {{0x20,0x02,0x2f,0x58,0xfe,0x62,0x00,0x00,0x00,0x00,0x00,0x00,0x2f,0x58,0xfe,0x62}, 8333}, + {{0x20,0x02,0x2f,0x59,0x30,0xf3,0x00,0x00,0x00,0x00,0x00,0x00,0x2f,0x59,0x30,0xf3}, 8333}, {{0x20,0x02,0x2f,0x5a,0x3c,0x1c,0x00,0x00,0x00,0x00,0x00,0x00,0x2f,0x5a,0x3c,0x1c}, 10011}, {{0x20,0x02,0x2f,0x5a,0x56,0x2a,0x00,0x00,0x00,0x00,0x00,0x00,0x2f,0x5a,0x56,0x2a}, 8333}, {{0x20,0x02,0x2f,0x5b,0xa5,0xf9,0x00,0x00,0x00,0x00,0x00,0x00,0x2f,0x5b,0xa5,0xf9}, 8333}, - {{0x20,0x02,0x31,0x41,0x02,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0x31,0x41,0x02,0x8c}, 8333}, - {{0x20,0x02,0x32,0x3f,0xa2,0xf2,0x00,0x00,0x00,0x00,0x00,0x00,0x32,0x3f,0xa2,0xf2}, 8333}, - {{0x20,0x02,0x32,0x3f,0x0f,0xbd,0x00,0x00,0x00,0x00,0x00,0x00,0x32,0x3f,0x0f,0xbd}, 8333}, + {{0x20,0x02,0x2f,0x5b,0xb0,0x86,0x00,0x00,0x00,0x00,0x00,0x00,0x2f,0x5b,0xb0,0x86}, 8333}, + {{0x20,0x02,0x32,0x3f,0xa6,0x1b,0x00,0x00,0x00,0x00,0x00,0x00,0x32,0x3f,0xa6,0x1b}, 8333}, {{0x20,0x02,0x33,0xff,0x69,0xa0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x20,0x02,0x3e,0x6a,0x10,0x6f,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0x6a,0x10,0x6f}, 8333}, - {{0x20,0x02,0x3e,0x70,0x0b,0xbc,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0x70,0x0b,0xbc}, 8333}, - {{0x20,0x02,0x3e,0x7a,0x67,0x27,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0x7a,0x67,0x27}, 8333}, {{0x20,0x02,0x3f,0x62,0xe6,0xbb,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0x62,0xe6,0xbb}, 8333}, - {{0x20,0x02,0x45,0x40,0x4b,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x45,0x40,0x4b,0x30}, 8333}, - {{0x20,0x02,0x4e,0x6b,0xc7,0x45,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x20,0x02,0x50,0x52,0x4d,0x8a,0x00,0x00,0x00,0x00,0x00,0x00,0x50,0x52,0x4d,0x8a}, 8333}, + {{0x20,0x02,0x4b,0x63,0x50,0xb4,0x12,0x34,0x40,0x59,0xbf,0x54,0xe0,0x88,0x7d,0xaa}, 8333}, + {{0x20,0x02,0x05,0x09,0x6a,0xc5,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x09,0x6a,0xc5}, 8333}, {{0x20,0x02,0x51,0xa9,0x9c,0xc9,0x00,0x00,0x00,0x00,0x00,0x00,0x51,0xa9,0x9c,0xc9}, 8333}, - {{0x20,0x02,0x54,0xfb,0xcb,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x20,0x02,0x54,0xfb,0xa1,0xcd,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, {{0x20,0x02,0x5b,0xc2,0x54,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x5b,0xc2,0x54,0x28}, 8333}, {{0x20,0x02,0x5b,0xce,0x12,0x53,0x00,0x00,0x00,0x00,0x00,0x00,0x5b,0xce,0x12,0x53}, 8333}, - {{0x20,0x02,0x5b,0xdb,0x19,0xe8,0x00,0x00,0x00,0x00,0x00,0x00,0x5b,0xdb,0x19,0xe8}, 8333}, - {{0x20,0x02,0x5c,0x3f,0x39,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x5c,0x3f,0x39,0x12}, 8333}, + {{0x20,0x02,0x5d,0x68,0xd2,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x5d,0x68,0xd2,0x70}, 8333}, {{0x20,0x02,0x5d,0xbd,0x91,0xa9,0x00,0x00,0x00,0x00,0x00,0x00,0x5d,0xbd,0x91,0xa9}, 8333}, - {{0x20,0x02,0x5d,0xbe,0x8c,0xc6,0x00,0x00,0x00,0x00,0x00,0x00,0x5d,0xbe,0x8c,0xc6}, 8333}, {{0x20,0x02,0x5f,0xd3,0x89,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x5f,0xd3,0x89,0x44}, 8333}, - {{0x20,0x02,0x65,0xc8,0xa0,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x65,0xc8,0xa0,0x18}, 8333}, - {{0x20,0x02,0x67,0x50,0xa8,0x39,0x00,0x00,0x00,0x00,0x00,0x00,0x67,0x50,0xa8,0x39}, 8333}, + {{0x20,0x02,0x67,0x38,0x88,0x69,0x00,0x00,0x00,0x00,0x00,0x00,0x67,0x38,0x88,0x69}, 8333}, + {{0x20,0x02,0x67,0xe9,0xfe,0x16,0x00,0x00,0x00,0x00,0x00,0x00,0x67,0xe9,0xfe,0x16}, 8333}, + {{0x20,0x02,0x67,0xfa,0x04,0x4a,0x00,0x00,0x00,0x00,0x00,0x00,0x67,0xfa,0x04,0x4a}, 8333}, {{0x20,0x02,0x67,0xfa,0x04,0x4b,0x00,0x00,0x00,0x00,0x00,0x00,0x67,0xfa,0x04,0x4b}, 8333}, + {{0x20,0x02,0x68,0x25,0xd4,0x25,0x00,0x00,0x00,0x00,0x00,0x00,0x68,0x25,0xd4,0x25}, 8333}, {{0x20,0x02,0x6a,0x0e,0x3e,0xa8,0x00,0x00,0x00,0x00,0x00,0x00,0x6a,0x0e,0x3e,0xa8}, 10011}, - {{0x20,0x02,0x6a,0x0f,0x24,0x97,0x00,0x00,0x00,0x00,0x00,0x00,0x6a,0x0f,0x24,0x97}, 8333}, - {{0x20,0x02,0x6d,0xec,0x5a,0xc7,0x00,0x00,0x00,0x00,0x00,0x00,0x6d,0xec,0x5a,0xc7}, 8333}, + {{0x20,0x02,0x6b,0xb4,0x47,0x5c,0x00,0x00,0x00,0x00,0x00,0x00,0x6b,0xb4,0x47,0x5c}, 41888}, + {{0x20,0x02,0x6b,0xb4,0x54,0xbc,0x00,0x00,0x00,0x00,0x00,0x00,0x6b,0xb4,0x54,0xbc}, 8333}, + {{0x20,0x02,0x6c,0x3d,0xd8,0x8a,0x00,0x00,0x00,0x00,0x00,0x00,0x6c,0x3d,0xd8,0x8a}, 8333}, {{0x20,0x02,0x70,0x4a,0xd6,0xd4,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x4a,0xd6,0xd4}, 9997}, + {{0x20,0x02,0x71,0x69,0x8b,0x2a,0x00,0x00,0x00,0x00,0x00,0x00,0x71,0x69,0x8b,0x2a}, 8333}, {{0x20,0x02,0x72,0x37,0xfc,0xf6,0x00,0x00,0x00,0x00,0x00,0x00,0x72,0x37,0xfc,0xf6}, 20188}, - {{0x20,0x02,0x76,0xb2,0x7f,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x76,0xb2,0x7f,0x40}, 8333}, {{0x20,0x02,0x78,0x19,0x7e,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x19,0x7e,0x80}, 7743}, - {{0x20,0x02,0x78,0x1b,0x8d,0xb8,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x1b,0x8d,0xb8}, 8333}, - {{0x20,0x02,0x7b,0x38,0xcd,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7b,0x38,0xcd,0x00}, 8333}, - {{0x20,0x02,0xac,0x52,0xb8,0x54,0x00,0x00,0x00,0x00,0x00,0x00,0xac,0x52,0xb8,0x54}, 8333}, + {{0x20,0x02,0x84,0x94,0x82,0x33,0x00,0x00,0x00,0x00,0x00,0x00,0x84,0x94,0x82,0x33}, 8333}, + {{0x20,0x02,0x84,0x94,0x84,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x84,0x94,0x84,0xfc}, 8333}, + {{0x20,0x02,0x92,0x47,0x4c,0xec,0x00,0x00,0x00,0x00,0x00,0x00,0x92,0x47,0x4c,0xec}, 8333}, + {{0x20,0x02,0x95,0x38,0x73,0x5d,0x00,0x00,0x00,0x00,0x00,0x00,0x95,0x38,0x73,0x5d}, 8333}, + {{0x20,0x02,0xad,0xcd,0xb8,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0xad,0xcd,0xb8,0x8c}, 8333}, + {{0x20,0x02,0xb0,0x25,0x5c,0x52,0x00,0x00,0x00,0x00,0x00,0x00,0xb0,0x25,0x5c,0x52}, 8333}, + {{0x20,0x02,0xb0,0x7e,0xa7,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0xb0,0x7e,0xa7,0x0a}, 8333}, + {{0x20,0x02,0xb2,0xc9,0xe6,0xfc,0x00,0x10,0x3d,0x5c,0xe3,0xad,0x08,0x13,0x9c,0x46}, 8333}, + {{0x20,0x02,0xb4,0xb2,0x36,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0xb4,0xb2,0x36,0x12}, 8333}, {{0x20,0x02,0xb6,0x10,0x1c,0xa3,0x00,0x00,0x00,0x00,0x00,0x00,0xb6,0x10,0x1c,0xa3}, 8333}, + {{0x20,0x02,0xb8,0x5f,0x26,0xda,0x00,0x00,0x00,0x00,0x00,0x00,0xb8,0x5f,0x26,0xda}, 8333}, + {{0x20,0x02,0xb9,0x23,0xb6,0x7b,0x00,0x00,0x00,0x00,0x00,0x00,0xb9,0x23,0xb6,0x7b}, 8333}, {{0x20,0x02,0xb9,0x46,0x69,0x4a,0x00,0x00,0x00,0x00,0x00,0x00,0xb9,0x46,0x69,0x4a}, 8339}, - {{0x20,0x02,0xb9,0x94,0x91,0x67,0x00,0x00,0x00,0x00,0x00,0x00,0xb9,0x94,0x91,0x67}, 8333}, - {{0x20,0x02,0xbc,0x28,0x6b,0x92,0x00,0x00,0x00,0x00,0x00,0x00,0xbc,0x28,0x6b,0x92}, 8333}, + {{0x20,0x02,0xb9,0x60,0x5e,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0xb9,0x60,0x5e,0x18}, 8333}, + {{0x20,0x02,0xbc,0x48,0xd6,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0xbc,0x48,0xd6,0x06}, 8333}, + {{0x20,0x02,0xc1,0x3a,0xc4,0xd4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x20,0x02,0xc1,0x6a,0x1c,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0xc1,0x6a,0x1c,0x08}, 8333}, + {{0x20,0x02,0xc1,0x6a,0x1d,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0xc1,0x6a,0x1d,0x12}, 8333}, {{0x20,0x02,0xc2,0x3f,0x8f,0xc5,0x00,0x00,0x00,0x00,0x00,0x00,0xc2,0x3f,0x8f,0xc5}, 8333}, - {{0x20,0x02,0xc3,0x38,0x3f,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0xc3,0x38,0x3f,0x0a}, 8333}, - {{0x20,0x02,0xd1,0xb1,0x56,0x15,0x00,0x00,0x00,0x00,0x00,0x00,0xd1,0xb1,0x56,0x15}, 8333}, + {{0x20,0x02,0xc2,0xa5,0x10,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0xc2,0xa5,0x10,0x21}, 8333}, + {{0x20,0x02,0xc2,0xa5,0x10,0xfe,0x00,0x00,0x00,0x00,0x00,0x00,0xc2,0xa5,0x10,0xfe}, 8333}, + {{0x20,0x02,0xc3,0x9a,0xa4,0xa8,0x00,0x00,0x00,0x00,0x00,0x00,0xc3,0x9a,0xa4,0xa8}, 8333}, + {{0x20,0x02,0xcb,0x82,0xd0,0x2d,0x00,0x00,0x00,0x00,0x00,0x00,0xcb,0x82,0xd0,0x2d}, 8333}, + {{0x20,0x02,0xd0,0x35,0x27,0x34,0x00,0x00,0x00,0x00,0x00,0x00,0xd0,0x35,0x27,0x34}, 8333}, {{0x20,0x02,0xd2,0xd3,0x6d,0xa5,0x00,0x00,0x00,0x00,0x00,0x00,0xd2,0xd3,0x6d,0xa5}, 8333}, - {{0x20,0x02,0xd9,0x17,0x02,0xb1,0x00,0x00,0x00,0x00,0x00,0x00,0xd9,0x17,0x02,0xb1}, 8333}, - {{0x20,0x02,0xdb,0x71,0xf4,0x34,0x00,0x00,0x00,0x00,0x00,0x00,0xdb,0x71,0xf4,0x34}, 8333}, - {{0x20,0x03,0x00,0x0a,0x03,0x6f,0x4f,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x20,0x03,0x00,0x0a,0x03,0x7f,0xef,0x4f,0xde,0xad,0xba,0xbe,0xb0,0x0b,0xbe,0xef}, 8333}, - {{0x24,0x00,0x89,0x01,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0x2c,0x63,0xd8}, 8333}, - {{0x24,0x00,0x89,0x02,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0xd5,0x9d,0x8d}, 8333}, - {{0x24,0x01,0x25,0x00,0x02,0x03,0x00,0x10,0x01,0x53,0x01,0x20,0x01,0x56,0x00,0x83}, 8333}, - {{0x24,0x01,0xa4,0x00,0x32,0x00,0x56,0x00,0x14,0xee,0xf3,0x61,0x4b,0xdc,0x1f,0x7c}, 8333}, + {{0x20,0x02,0xd4,0x53,0x91,0x74,0x00,0x00,0x00,0x00,0x00,0x00,0xd4,0x53,0x91,0x74}, 8333}, + {{0x20,0x02,0xd9,0x17,0x0d,0x95,0x00,0x00,0x00,0x00,0x00,0x00,0xd9,0x17,0x0d,0x95}, 8333}, + {{0x20,0x03,0x00,0x0a,0x11,0x14,0x10,0x01,0x6a,0xb5,0x99,0xff,0xfe,0xb0,0x87,0x70}, 8333}, + {{0x24,0x00,0x26,0x50,0x04,0x80,0xbc,0x00,0xbc,0xaf,0x7c,0x49,0x8c,0x9e,0x7c,0xdf}, 8333}, + {{0x24,0x00,0x89,0x01,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0x1f,0xec,0x00}, 8333}, + {{0x24,0x00,0x89,0x01,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0x3e,0x57,0x1b}, 8333}, + {{0x24,0x00,0x89,0x01,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0x3e,0x57,0xef}, 8333}, + {{0x24,0x00,0x89,0x01,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0xb4,0x71,0xf1}, 8333}, + {{0x24,0x00,0x89,0x02,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0xb9,0xc5,0x9c}, 8333}, + {{0x24,0x00,0xdd,0x01,0x10,0x34,0x0e,0x00,0xf2,0x1f,0xaf,0xff,0xfe,0xdc,0x16,0x4d}, 8333}, + {{0x24,0x00,0xdd,0x08,0x10,0x01,0x01,0x20,0xf0,0xf7,0xd9,0xda,0x8b,0x5b,0x58,0xd7}, 8333}, + {{0x24,0x01,0x18,0x00,0x78,0x00,0x01,0x02,0xbe,0x76,0x4e,0xff,0xfe,0x1c,0x0a,0x7d}, 8333}, + {{0x24,0x01,0x18,0x00,0x78,0x01,0x01,0x01,0xbe,0x76,0x4e,0xff,0xfe,0x1c,0x0f,0x4b}, 8333}, {{0x24,0x02,0x1f,0x00,0x81,0x00,0x00,0x36,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, - {{0x24,0x03,0x42,0x00,0x04,0x03,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff}, 8333}, - {{0x24,0x05,0x98,0x00,0xb4,0x40,0x94,0x7f,0x59,0xa5,0xf3,0x79,0x18,0x76,0x85,0x8c}, 8333}, + {{0x24,0x04,0x7a,0x83,0x94,0xe0,0x7f,0x00,0x85,0x8f,0x8a,0x7d,0x3a,0x8c,0x26,0xdd}, 8333}, + {{0x24,0x04,0xc8,0x05,0x0d,0x00,0x01,0x01,0x71,0x6a,0xcf,0xf7,0xc9,0xab,0xa5,0x95}, 8333}, {{0x24,0x05,0xaa,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40}, 8333}, - {{0x24,0x06,0xda,0x14,0x04,0x45,0x52,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04}, 8333}, - {{0x24,0x06,0xda,0x18,0x0f,0x7c,0x43,0x51,0x1a,0x58,0x81,0xfe,0x6e,0xd0,0x11,0x03}, 8333}, - {{0x24,0x06,0xda,0x18,0x0f,0x7c,0x43,0x51,0x22,0xaa,0x25,0x85,0xfe,0x88,0x7d,0x58}, 8333}, - {{0x24,0x06,0xda,0x18,0x0f,0x7c,0x43,0x51,0x26,0x74,0x33,0xbb,0x25,0xd6,0xcb,0xba}, 8333}, - {{0x24,0x06,0xda,0x18,0x0f,0x7c,0x43,0x51,0x2e,0x19,0xa8,0xc7,0xa3,0x6a,0xbd,0xe0}, 8333}, - {{0x24,0x06,0xda,0x18,0x0f,0x7c,0x43,0x51,0x3c,0xc8,0x04,0x3d,0xfb,0xcc,0x50,0x67}, 8333}, - {{0x24,0x06,0xda,0x18,0x0f,0x7c,0x43,0x51,0x52,0x28,0x2b,0x53,0xbb,0x9a,0xed,0xf5}, 8333}, - {{0x24,0x06,0xda,0x18,0x0f,0x7c,0x43,0x51,0x57,0x29,0x01,0x02,0x99,0x8c,0xd4,0x1a}, 8333}, - {{0x24,0x06,0xda,0x18,0x0f,0x7c,0x43,0x51,0x59,0x1b,0x48,0x81,0x39,0x86,0x37,0x03}, 8333}, - {{0x24,0x06,0xda,0x18,0x0f,0x7c,0x43,0x51,0x59,0xb9,0x0b,0x50,0xf4,0x7f,0xb5,0x60}, 8333}, - {{0x24,0x06,0xda,0x18,0x0f,0x7c,0x43,0x51,0x61,0xf2,0xcf,0xb0,0x8c,0x45,0x5f,0xdd}, 8333}, - {{0x24,0x06,0xda,0x18,0x0f,0x7c,0x43,0x51,0x63,0x56,0x68,0xe0,0x73,0xfc,0xac,0x0b}, 8333}, - {{0x24,0x06,0xda,0x18,0x0f,0x7c,0x43,0x51,0x66,0x0e,0xf6,0xbc,0x35,0x63,0xba,0x8e}, 8333}, - {{0x24,0x06,0xda,0x18,0x0f,0x7c,0x43,0x51,0x06,0x91,0x00,0x9e,0xf2,0xdf,0x22,0x7d}, 8333}, - {{0x24,0x06,0xda,0x18,0x0f,0x7c,0x43,0x51,0x72,0x1c,0x83,0xd2,0x67,0x65,0x43,0x00}, 8333}, - {{0x24,0x06,0xda,0x18,0x0f,0x7c,0x43,0x51,0x72,0x37,0x09,0xbe,0x46,0x01,0xbc,0x15}, 8333}, - {{0x24,0x06,0xda,0x18,0x0f,0x7c,0x43,0x51,0x7a,0x3b,0xc2,0x03,0xfd,0x11,0x6c,0x7d}, 8333}, - {{0x24,0x06,0xda,0x18,0x0f,0x7c,0x43,0x51,0x7a,0x74,0xa8,0x0e,0x88,0x9a,0xba,0x42}, 8333}, - {{0x24,0x06,0xda,0x18,0x0f,0x7c,0x43,0x51,0x7e,0xe3,0xa1,0x81,0xf2,0x5c,0xfa,0x79}, 8333}, - {{0x24,0x06,0xda,0x18,0x0f,0x7c,0x43,0x51,0x8a,0x25,0x90,0x84,0x01,0x40,0x45,0x49}, 8333}, - {{0x24,0x06,0xda,0x18,0x0f,0x7c,0x43,0x51,0x8b,0xc0,0xc6,0xfd,0xec,0xfb,0xf0,0x74}, 8333}, - {{0x24,0x06,0xda,0x18,0x0f,0x7c,0x43,0x51,0x91,0xce,0xd0,0xba,0x1b,0x9e,0xc2,0x7b}, 8333}, - {{0x24,0x06,0xda,0x18,0x0f,0x7c,0x43,0x51,0x93,0x36,0x44,0xe7,0x84,0xb4,0x85,0xb9}, 8333}, - {{0x24,0x06,0xda,0x18,0x0f,0x7c,0x43,0x51,0x93,0x6c,0xc3,0xb9,0xa1,0xd0,0x08,0x48}, 8333}, - {{0x24,0x06,0xda,0x18,0x0f,0x7c,0x43,0x51,0x93,0xef,0x1e,0xef,0x65,0xc8,0x76,0x6d}, 8333}, - {{0x24,0x06,0xda,0x18,0x0f,0x7c,0x43,0x51,0x94,0xe0,0x5b,0x27,0x78,0xc2,0x51,0x11}, 8333}, - {{0x24,0x06,0xda,0x18,0x0f,0x7c,0x43,0x51,0x98,0x15,0xa2,0x02,0x18,0xa3,0x2a,0x36}, 8333}, - {{0x24,0x06,0xda,0x18,0x0f,0x7c,0x43,0x51,0x9e,0x1b,0x13,0x5c,0x74,0x72,0x09,0xd9}, 8333}, - {{0x24,0x06,0xda,0x18,0x0f,0x7c,0x43,0x51,0x9f,0x84,0x02,0x78,0x68,0xf5,0xb8,0xea}, 8333}, - {{0x24,0x06,0xda,0x18,0x0f,0x7c,0x43,0x51,0xa0,0x62,0x49,0x3f,0xa6,0xf8,0xca,0x75}, 8333}, - {{0x24,0x06,0xda,0x18,0x0f,0x7c,0x43,0x51,0xa1,0x92,0x0b,0x98,0x30,0x66,0x8f,0x11}, 8333}, - {{0x24,0x06,0xda,0x18,0x0f,0x7c,0x43,0x51,0xa1,0xcb,0x2f,0x19,0x4a,0x54,0x38,0xc9}, 8333}, - {{0x24,0x06,0xda,0x18,0x0f,0x7c,0x43,0x51,0xa4,0xa2,0x04,0xc9,0xc4,0x3a,0x98,0xae}, 8333}, - {{0x24,0x06,0xda,0x18,0x0f,0x7c,0x43,0x51,0xa7,0xe9,0xcd,0x48,0xfa,0x90,0x46,0xd3}, 8333}, - {{0x24,0x06,0xda,0x18,0x0f,0x7c,0x43,0x51,0x0a,0x88,0x00,0x99,0x66,0x71,0xfc,0xe4}, 8333}, - {{0x24,0x06,0xda,0x18,0x0f,0x7c,0x43,0x51,0xab,0xe1,0x2e,0x48,0xeb,0x97,0x2a,0xb5}, 8333}, - {{0x24,0x06,0xda,0x18,0x0f,0x7c,0x43,0x51,0xac,0xf5,0x2b,0x21,0x5d,0x2a,0x6b,0x31}, 8333}, - {{0x24,0x06,0xda,0x18,0x0f,0x7c,0x43,0x51,0xb5,0x1f,0x89,0x66,0x74,0xa5,0x6c,0x53}, 8333}, - {{0x24,0x06,0xda,0x18,0x0f,0x7c,0x43,0x51,0xb8,0xe3,0xf3,0xca,0xe4,0x12,0xda,0xa5}, 8333}, - {{0x24,0x06,0xda,0x18,0x0f,0x7c,0x43,0x51,0xba,0x7c,0x6d,0xa8,0xda,0x59,0xb1,0xb6}, 8333}, - {{0x24,0x06,0xda,0x18,0x0f,0x7c,0x43,0x51,0xbe,0x04,0x6f,0x8e,0x8f,0x93,0xc5,0x55}, 8333}, - {{0x24,0x06,0xda,0x18,0x0f,0x7c,0x43,0x51,0xc8,0x2d,0x2a,0x0b,0x31,0xa5,0xe2,0x8d}, 8333}, - {{0x24,0x06,0xda,0x18,0x0f,0x7c,0x43,0x51,0xc9,0x93,0xeb,0x06,0xbd,0x2c,0x1e,0x65}, 8333}, - {{0x24,0x06,0xda,0x18,0x0f,0x7c,0x43,0x51,0xd4,0xb9,0xbf,0xf8,0xc4,0xd4,0x1e,0x05}, 8333}, - {{0x24,0x06,0xda,0x18,0x0f,0x7c,0x43,0x51,0xd7,0x0d,0xa7,0x3d,0x1d,0xdd,0x43,0x9e}, 8333}, - {{0x24,0x06,0xda,0x18,0x0f,0x7c,0x43,0x51,0xe1,0x03,0xf4,0x56,0xb2,0x96,0x9f,0x29}, 8333}, - {{0x24,0x06,0xda,0x18,0x0f,0x7c,0x43,0x51,0xea,0x3b,0x27,0xec,0x07,0xc2,0xae,0xbc}, 8333}, - {{0x24,0x06,0xda,0x18,0x0f,0x7c,0x43,0x51,0xf6,0x2c,0x50,0x13,0x37,0x9b,0x36,0x3e}, 8333}, - {{0x24,0x0b,0x00,0x10,0xca,0x20,0x00,0xf0,0x02,0x24,0xe8,0xff,0xfe,0x1f,0x60,0xd9}, 8333}, - {{0x24,0x0b,0x02,0x50,0x01,0xe0,0x24,0x00,0xb9,0xef,0x8f,0xe3,0xa6,0x9a,0x73,0x78}, 8333}, - {{0x26,0x00,0x1f,0x14,0x03,0x4a,0xfe,0x00,0x13,0xf4,0xce,0xb6,0xa9,0xdb,0x4f,0x47}, 8333}, - {{0x26,0x00,0x1f,0x14,0x03,0x4a,0xfe,0x00,0x25,0x50,0x93,0x66,0xa5,0xd9,0x78,0xa5}, 8333}, - {{0x26,0x00,0x1f,0x14,0x03,0x4a,0xfe,0x00,0x02,0x7d,0x06,0xed,0x7c,0x8d,0x7b,0xee}, 8333}, - {{0x26,0x00,0x1f,0x14,0x03,0x4a,0xfe,0x00,0x2e,0xd6,0x8a,0x19,0x04,0xeb,0x36,0xc1}, 8333}, - {{0x26,0x00,0x1f,0x14,0x03,0x4a,0xfe,0x00,0x34,0xc7,0x2e,0x9e,0xe6,0x0e,0xf8,0x23}, 8333}, - {{0x26,0x00,0x1f,0x14,0x03,0x4a,0xfe,0x00,0x38,0xde,0x04,0x42,0x72,0xdf,0x63,0x46}, 8333}, - {{0x26,0x00,0x1f,0x14,0x03,0x4a,0xfe,0x00,0x3a,0x1e,0x87,0x8f,0x99,0x1a,0x95,0x82}, 8333}, - {{0x26,0x00,0x1f,0x14,0x03,0x4a,0xfe,0x00,0x3d,0x88,0x18,0x05,0x54,0xe3,0xf4,0xc8}, 8333}, - {{0x26,0x00,0x1f,0x14,0x03,0x4a,0xfe,0x00,0x3f,0x3e,0x58,0xbd,0xec,0x82,0x5d,0xac}, 8333}, - {{0x26,0x00,0x1f,0x14,0x03,0x4a,0xfe,0x00,0x44,0x9a,0x95,0x15,0x84,0x36,0xf4,0x07}, 8333}, - {{0x26,0x00,0x1f,0x14,0x03,0x4a,0xfe,0x00,0x4f,0x84,0x27,0x7f,0xe6,0x4d,0x1f,0x06}, 8333}, - {{0x26,0x00,0x1f,0x14,0x03,0x4a,0xfe,0x00,0x52,0x29,0xde,0x84,0x82,0x26,0x72,0x57}, 8333}, - {{0x26,0x00,0x1f,0x14,0x03,0x4a,0xfe,0x00,0x57,0x43,0x42,0xc3,0x95,0x1b,0xe9,0x7a}, 8333}, - {{0x26,0x00,0x1f,0x14,0x03,0x4a,0xfe,0x00,0x5a,0x29,0x08,0x5b,0x86,0xb5,0xfa,0x0e}, 8333}, - {{0x26,0x00,0x1f,0x14,0x03,0x4a,0xfe,0x00,0x5d,0xe8,0x08,0x1e,0x6d,0x79,0x33,0x0b}, 8333}, - {{0x26,0x00,0x1f,0x14,0x03,0x4a,0xfe,0x00,0x5f,0xca,0xad,0x1e,0x5b,0x9c,0x52,0x65}, 8333}, - {{0x26,0x00,0x1f,0x14,0x03,0x4a,0xfe,0x00,0x68,0xc4,0xca,0x1b,0x81,0x3e,0x1b,0xce}, 8333}, - {{0x26,0x00,0x1f,0x14,0x03,0x4a,0xfe,0x00,0x00,0x06,0xde,0x9e,0x7b,0x5e,0xa5,0x58}, 8333}, - {{0x26,0x00,0x1f,0x14,0x03,0x4a,0xfe,0x00,0x6c,0x72,0x1f,0xcd,0x04,0x33,0xdc,0x97}, 8333}, - {{0x26,0x00,0x1f,0x14,0x03,0x4a,0xfe,0x00,0x77,0xee,0x62,0x9f,0xbc,0x13,0xfb,0x4f}, 8333}, - {{0x26,0x00,0x1f,0x14,0x03,0x4a,0xfe,0x00,0x79,0xd0,0x85,0xd6,0x51,0x6f,0x32,0x93}, 8333}, - {{0x26,0x00,0x1f,0x14,0x03,0x4a,0xfe,0x00,0x00,0x81,0x42,0x2f,0x9e,0xf3,0x45,0x79}, 8333}, - {{0x26,0x00,0x1f,0x14,0x03,0x4a,0xfe,0x00,0x82,0x2b,0x5f,0x05,0xec,0x8d,0x48,0xc6}, 8333}, - {{0x26,0x00,0x1f,0x14,0x03,0x4a,0xfe,0x00,0x08,0x2a,0x76,0xa2,0xfd,0xc9,0x84,0x5e}, 8333}, - {{0x26,0x00,0x1f,0x14,0x03,0x4a,0xfe,0x00,0x83,0xca,0xce,0xf6,0xe0,0x4c,0x50,0xc0}, 8333}, - {{0x26,0x00,0x1f,0x14,0x03,0x4a,0xfe,0x00,0x8b,0xa2,0xa3,0x6c,0x86,0x87,0xd5,0xaa}, 8333}, - {{0x26,0x00,0x1f,0x14,0x03,0x4a,0xfe,0x00,0x8c,0x80,0x5c,0x67,0x3b,0x47,0x90,0xb3}, 8333}, - {{0x26,0x00,0x1f,0x14,0x03,0x4a,0xfe,0x00,0x8e,0xb8,0xf4,0x7f,0x6d,0x53,0xe3,0xae}, 8333}, - {{0x26,0x00,0x1f,0x14,0x03,0x4a,0xfe,0x00,0x98,0x9c,0xf8,0xf8,0xa9,0x22,0x1b,0x9a}, 8333}, - {{0x26,0x00,0x1f,0x14,0x03,0x4a,0xfe,0x00,0x98,0xc9,0x1e,0xb3,0xea,0x12,0xa8,0xf0}, 8333}, - {{0x26,0x00,0x1f,0x14,0x03,0x4a,0xfe,0x00,0x9e,0xe5,0xa8,0xf6,0x6b,0x2a,0x86,0x6e}, 8333}, - {{0x26,0x00,0x1f,0x14,0x03,0x4a,0xfe,0x00,0xa4,0x6b,0x7b,0xd5,0x62,0x9f,0xf7,0x5c}, 8333}, - {{0x26,0x00,0x1f,0x14,0x03,0x4a,0xfe,0x00,0xa6,0x27,0x82,0x99,0x87,0x84,0xd4,0x39}, 8333}, - {{0x26,0x00,0x1f,0x14,0x03,0x4a,0xfe,0x00,0xad,0x0b,0x95,0x5e,0xb4,0xe5,0xd9,0x7d}, 8333}, - {{0x26,0x00,0x1f,0x14,0x03,0x4a,0xfe,0x00,0xae,0x82,0x71,0x17,0x9d,0x69,0x7c,0x86}, 8333}, - {{0x26,0x00,0x1f,0x14,0x03,0x4a,0xfe,0x00,0xcc,0xee,0x36,0x5a,0x43,0xf8,0xb8,0x71}, 8333}, - {{0x26,0x00,0x1f,0x14,0x03,0x4a,0xfe,0x00,0xd5,0xee,0xa3,0xe2,0x2f,0x85,0xe5,0x93}, 8333}, - {{0x26,0x00,0x1f,0x14,0x03,0x4a,0xfe,0x00,0xd5,0xf0,0x1f,0xe0,0x6b,0xd5,0x18,0xa8}, 8333}, - {{0x26,0x00,0x1f,0x14,0x03,0x4a,0xfe,0x00,0xe4,0xa7,0x5a,0xba,0xaf,0x87,0x4c,0xdb}, 8333}, - {{0x26,0x00,0x1f,0x14,0x03,0x4a,0xfe,0x00,0xe8,0xe5,0x02,0xd0,0xfb,0x6f,0x02,0xf5}, 8333}, - {{0x26,0x00,0x1f,0x14,0x03,0x4a,0xfe,0x00,0xe9,0xef,0x46,0x90,0xa5,0xac,0x92,0xbe}, 8333}, - {{0x26,0x00,0x1f,0x14,0x03,0x4a,0xfe,0x00,0xef,0xba,0x22,0x60,0x69,0x97,0xfc,0xf7}, 8333}, - {{0x26,0x00,0x1f,0x14,0x03,0x4a,0xfe,0x00,0xf1,0x07,0x2d,0x08,0x0c,0x67,0xe5,0xdd}, 8333}, - {{0x26,0x00,0x1f,0x14,0x03,0x4a,0xfe,0x00,0xf1,0xb9,0x88,0xfb,0xf3,0xdb,0xa8,0x6e}, 8333}, - {{0x26,0x00,0x1f,0x14,0x03,0x4a,0xfe,0x00,0xf7,0x9c,0x17,0xb7,0x6f,0x75,0x95,0xb7}, 8333}, + {{0x24,0x09,0x00,0x10,0xca,0x20,0x1d,0xf0,0x02,0x24,0xe8,0xff,0xfe,0x1f,0x60,0xd9}, 8333}, {{0x26,0x00,0x1f,0x14,0x06,0xae,0xd9,0x00,0x65,0x50,0x3f,0xc5,0xe0,0x74,0xa7,0x2c}, 8333}, - {{0x26,0x00,0x1f,0x16,0x06,0x25,0x0e,0x00,0x12,0x43,0x38,0xb3,0x0c,0xaa,0xd6,0x2e}, 8333}, - {{0x26,0x00,0x1f,0x16,0x06,0x25,0x0e,0x00,0x16,0x6d,0xa9,0x56,0x10,0x41,0xf9,0x7d}, 8333}, - {{0x26,0x00,0x1f,0x16,0x06,0x25,0x0e,0x00,0x35,0xf2,0x24,0x28,0xfc,0x57,0xd6,0x38}, 8333}, - {{0x26,0x00,0x1f,0x16,0x06,0x25,0x0e,0x00,0x3c,0x75,0x33,0x3e,0x0b,0x7f,0x8c,0xc0}, 8333}, - {{0x26,0x00,0x1f,0x16,0x06,0x25,0x0e,0x00,0x3f,0xbf,0x03,0x1f,0x1b,0x57,0x8b,0x18}, 8333}, - {{0x26,0x00,0x1f,0x16,0x06,0x25,0x0e,0x00,0x56,0x17,0x75,0x75,0x03,0x79,0xa8,0xcc}, 8333}, - {{0x26,0x00,0x1f,0x16,0x06,0x25,0x0e,0x00,0x58,0xfa,0xfc,0xe6,0x00,0x30,0xa5,0xdc}, 8333}, - {{0x26,0x00,0x1f,0x16,0x06,0x25,0x0e,0x00,0x5e,0x74,0x70,0xdc,0xaf,0x78,0x6b,0x77}, 8333}, - {{0x26,0x00,0x1f,0x16,0x06,0x25,0x0e,0x00,0x70,0x36,0xf6,0x51,0x02,0xee,0x39,0xcd}, 8333}, - {{0x26,0x00,0x1f,0x16,0x06,0x25,0x0e,0x00,0x07,0xfc,0x90,0x04,0xe7,0xbe,0xff,0xe2}, 8333}, - {{0x26,0x00,0x1f,0x16,0x06,0x25,0x0e,0x00,0x81,0x4a,0x23,0xf6,0xe9,0x96,0x5e,0x64}, 8333}, - {{0x26,0x00,0x1f,0x16,0x06,0x25,0x0e,0x00,0x82,0x2c,0xa8,0x8b,0x0f,0x9c,0x57,0xe3}, 8333}, - {{0x26,0x00,0x1f,0x16,0x06,0x25,0x0e,0x00,0x83,0x14,0xb9,0x1e,0xa7,0xba,0x07,0x02}, 8333}, - {{0x26,0x00,0x1f,0x16,0x06,0x25,0x0e,0x00,0x88,0xbb,0xee,0x9a,0x10,0xde,0x00,0x12}, 8333}, - {{0x26,0x00,0x1f,0x16,0x06,0x25,0x0e,0x00,0x8c,0x30,0x56,0xf5,0xa2,0x9a,0x91,0xde}, 8333}, - {{0x26,0x00,0x1f,0x16,0x06,0x25,0x0e,0x00,0x8f,0xdf,0x65,0x17,0x77,0x18,0x8c,0x42}, 8333}, - {{0x26,0x00,0x1f,0x16,0x06,0x25,0x0e,0x00,0x91,0xfd,0x78,0xb1,0x62,0xa3,0x01,0x93}, 8333}, - {{0x26,0x00,0x1f,0x16,0x06,0x25,0x0e,0x00,0x93,0x0d,0x93,0xed,0x76,0xa6,0x32,0x85}, 8333}, - {{0x26,0x00,0x1f,0x16,0x06,0x25,0x0e,0x00,0x93,0xc2,0x61,0x5f,0xa7,0x9a,0xc1,0x1f}, 8333}, - {{0x26,0x00,0x1f,0x16,0x06,0x25,0x0e,0x00,0xa7,0x80,0x8b,0xc8,0xa1,0xf6,0xd4,0x17}, 8333}, - {{0x26,0x00,0x1f,0x16,0x06,0x25,0x0e,0x00,0xa9,0x51,0xe6,0x63,0x40,0x46,0x8c,0x3a}, 8333}, - {{0x26,0x00,0x1f,0x16,0x06,0x25,0x0e,0x00,0xab,0x19,0x5f,0xe3,0xf1,0x55,0x13,0x71}, 8333}, - {{0x26,0x00,0x1f,0x16,0x06,0x25,0x0e,0x00,0xae,0xfd,0x9c,0xc7,0x00,0xd3,0x6e,0x86}, 8333}, - {{0x26,0x00,0x1f,0x16,0x06,0x25,0x0e,0x00,0xb0,0x31,0xe8,0x6e,0x86,0x04,0x32,0x4a}, 8333}, - {{0x26,0x00,0x1f,0x16,0x06,0x25,0x0e,0x00,0x0b,0x6e,0x43,0x99,0x9d,0xc2,0x6b,0x45}, 8333}, - {{0x26,0x00,0x1f,0x16,0x06,0x25,0x0e,0x00,0xb7,0xc7,0x58,0xc6,0x21,0xa1,0xfd,0x41}, 8333}, - {{0x26,0x00,0x1f,0x16,0x06,0x25,0x0e,0x00,0xc1,0x69,0x62,0x82,0x17,0x8c,0x27,0xd6}, 8333}, - {{0x26,0x00,0x1f,0x16,0x06,0x25,0x0e,0x00,0xc9,0x4e,0x05,0x8b,0xbd,0x35,0xd8,0x15}, 8333}, - {{0x26,0x00,0x1f,0x16,0x06,0x25,0x0e,0x00,0xca,0xa5,0x73,0x69,0x73,0xa4,0x57,0x11}, 8333}, - {{0x26,0x00,0x1f,0x16,0x06,0x25,0x0e,0x00,0xcd,0x15,0xb9,0xf2,0x6e,0x3e,0x6f,0xd1}, 8333}, - {{0x26,0x00,0x1f,0x16,0x06,0x25,0x0e,0x00,0xd6,0xf3,0x07,0x75,0x66,0xb7,0x3e,0x92}, 8333}, - {{0x26,0x00,0x1f,0x16,0x06,0x25,0x0e,0x00,0xdb,0xec,0xf7,0xd9,0x0e,0x15,0xf8,0xe0}, 8333}, - {{0x26,0x00,0x1f,0x16,0x06,0x25,0x0e,0x00,0xdb,0xf4,0x4d,0x41,0x59,0x4e,0xbc,0x20}, 8333}, - {{0x26,0x00,0x1f,0x16,0x06,0x25,0x0e,0x00,0xe1,0x1b,0x45,0x89,0xa0,0xc3,0x9c,0xc7}, 8333}, - {{0x26,0x00,0x1f,0x16,0x06,0x25,0x0e,0x00,0xed,0x68,0x15,0xb0,0x3a,0x97,0xbe,0x0c}, 8333}, - {{0x26,0x00,0x1f,0x16,0x06,0x25,0x0e,0x00,0xee,0xf3,0xbc,0xe0,0x84,0xee,0xa9,0x8b}, 8333}, - {{0x26,0x00,0x1f,0x16,0x06,0x25,0x0e,0x00,0xef,0x3a,0xf6,0x6e,0xf0,0x59,0xd0,0x3f}, 8333}, - {{0x26,0x00,0x1f,0x16,0x06,0x25,0x0e,0x00,0xf6,0x7c,0xd3,0x98,0x05,0xb6,0xd3,0x4f}, 8333}, - {{0x26,0x00,0x1f,0x16,0x06,0x25,0x0e,0x00,0xfe,0x35,0x50,0x99,0x3a,0x8e,0xd1,0x23}, 8333}, - {{0x26,0x00,0x1f,0x18,0x64,0xd9,0x16,0x03,0x6f,0x6f,0xee,0xf9,0xb5,0x95,0x19,0x58}, 8333}, - {{0x26,0x00,0x3c,0x00,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0x84,0xd6,0x50}, 8333}, - {{0x26,0x00,0x3c,0x00,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0x89,0x74,0x38}, 8333}, + {{0x26,0x00,0x1f,0x14,0x06,0xd0,0x2e,0x03,0x64,0x0e,0x19,0x37,0x99,0x60,0x32,0xe9}, 8333}, + {{0x26,0x00,0x1f,0x14,0x06,0xd0,0x2e,0x03,0x07,0x61,0x6e,0x21,0x95,0x2c,0xde,0x5b}, 8333}, + {{0x26,0x00,0x1f,0x16,0x06,0x25,0x0e,0x00,0x26,0x9a,0x34,0x52,0x2e,0xdf,0x10,0x11}, 8333}, + {{0x26,0x00,0x1f,0x16,0x06,0x25,0x0e,0x00,0x07,0xbc,0x58,0x79,0x44,0x63,0x15,0xdd}, 8333}, + {{0x26,0x00,0x1f,0x16,0x06,0x25,0x0e,0x00,0xa2,0x8b,0x5a,0x16,0x84,0x9c,0xfe,0x41}, 8333}, + {{0x26,0x00,0x1f,0x16,0x06,0x25,0x0e,0x00,0xa7,0x0f,0xe7,0x28,0xe8,0xe1,0x2c,0x2e}, 8333}, + {{0x26,0x00,0x1f,0x16,0x0b,0x32,0x31,0x02,0x04,0x40,0x0f,0xab,0xd8,0xa2,0xcc,0x59}, 8333}, + {{0x26,0x00,0x1f,0x18,0x00,0x3d,0x46,0x00,0x69,0x9a,0xd6,0xb3,0x76,0xe8,0x9b,0x8d}, 48333}, + {{0x26,0x00,0x1f,0x18,0x03,0xf8,0xf9,0x0f,0x2b,0x39,0x20,0x1b,0xe9,0xa4,0xe8,0x82}, 8333}, + {{0x26,0x00,0x1f,0x18,0x60,0x9f,0xda,0x02,0xb2,0x83,0xb1,0x6e,0xaa,0xc4,0x74,0x9f}, 8333}, + {{0x26,0x00,0x3c,0x00,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0x28,0x9e,0x61}, 8333}, {{0x26,0x00,0x3c,0x00,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0x91,0x3e,0x49}, 8333}, - {{0x26,0x00,0x3c,0x00,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0xbb,0x98,0x1e}, 8333}, - {{0x26,0x00,0x3c,0x01,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0x69,0x89,0xe9}, 8333}, + {{0x26,0x00,0x3c,0x00,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0xb9,0x36,0xfc}, 8333}, + {{0x26,0x00,0x3c,0x01,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0x39,0x76,0x8b}, 8333}, + {{0x26,0x00,0x3c,0x01,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0x8e,0x8a,0xe1}, 8333}, {{0x26,0x00,0x3c,0x01,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0x91,0x6a,0x29}, 8333}, + {{0x26,0x00,0x3c,0x01,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0xa7,0xe0,0xf9}, 8333}, + {{0x26,0x00,0x3c,0x02,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0x8e,0xbc,0xd9}, 8333}, {{0x26,0x00,0x3c,0x03,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0x28,0x14,0x45}, 8333}, + {{0x26,0x00,0x3c,0x03,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0x7a,0x1e,0xb2}, 8333}, + {{0x26,0x00,0x3c,0x03,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0xb0,0x5f,0xc4}, 8333}, {{0x26,0x00,0x3c,0x03,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0xe0,0x23,0x3e}, 8333}, - {{0x26,0x00,0x6c,0x55,0x72,0x00,0x02,0x4d,0x0c,0xf4,0x81,0x1c,0x7c,0xb3,0xf7,0xa7}, 8333}, - {{0x26,0x00,0x88,0x05,0x24,0x00,0x01,0x4e,0x02,0x26,0x4a,0xff,0xfe,0x02,0x2b,0xa4}, 8333}, - {{0x26,0x01,0x01,0x8d,0x46,0x00,0x3c,0xc2,0x20,0xe7,0xb3,0xff,0xfe,0xcf,0x0a,0x99}, 8333}, - {{0x26,0x01,0x01,0xc2,0x17,0x02,0x52,0x41,0x04,0x7d,0x40,0x16,0xec,0x42,0x67,0x05}, 8333}, - {{0x26,0x01,0x04,0x41,0x41,0x01,0x70,0xcd,0x04,0xe3,0x8e,0x81,0x32,0x50,0x1f,0x0b}, 8333}, - {{0x26,0x01,0x06,0x02,0x99,0x80,0x0f,0x78,0x02,0x11,0x11,0xff,0xfe,0xc5,0x01,0xae}, 8333}, - {{0x26,0x01,0x06,0x46,0x41,0x03,0x17,0x9f,0x58,0x09,0x1b,0xff,0xfe,0x55,0x66,0x78}, 8333}, - {{0x26,0x02,0x00,0x4c,0x03,0x23,0xb1,0x01,0x35,0xa3,0x9d,0xe8,0x69,0x84,0xef,0x56}, 8333}, - {{0x26,0x02,0xff,0x62,0x01,0x04,0x0a,0xc1,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, - {{0x26,0x02,0xff,0xc5,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x71,0x1e}, 8333}, - {{0x26,0x02,0xff,0xc5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x30,0x1c,0x75}, 8333}, - {{0x26,0x04,0xa8,0x80,0x00,0x02,0x00,0xd0,0x00,0x00,0x00,0x00,0x17,0xe9,0x20,0x01}, 8333}, + {{0x26,0x00,0x6c,0x40,0x79,0x00,0x31,0x9f,0x83,0x90,0xe8,0xaf,0x5a,0x2c,0x9b,0x0b}, 8333}, + {{0x26,0x00,0x6c,0x44,0x46,0x7f,0xf8,0x9c,0x72,0x2d,0x84,0x24,0xd4,0x81,0xd1,0x55}, 8333}, + {{0x26,0x00,0x88,0x01,0x83,0x06,0xe9,0x00,0xdc,0xe8,0x6a,0x03,0x95,0x92,0xa0,0x53}, 8333}, + {{0x26,0x01,0x01,0x86,0xc1,0x00,0x6b,0xcd,0x16,0xbd,0xce,0xa1,0x23,0x5d,0x1c,0x19}, 8333}, + {{0x26,0x01,0x01,0x8d,0x46,0x00,0x5f,0x32,0x20,0xe7,0xb3,0xff,0xfe,0xcf,0x0a,0x99}, 8333}, + {{0x26,0x01,0x01,0xc2,0x0f,0x00,0x29,0xb0,0x92,0x2b,0x34,0xff,0xfe,0xa8,0x41,0x18}, 8333}, + {{0x26,0x01,0x02,0x82,0x80,0x00,0x20,0xb0,0x67,0xf8,0xfa,0x63,0xe0,0x56,0xdd,0x23}, 8333}, + {{0x26,0x01,0x04,0x0a,0xc2,0x00,0x37,0xe8,0x95,0x28,0xd4,0x53,0x63,0x58,0x9f,0x2a}, 8333}, + {{0x26,0x01,0x06,0x46,0x41,0x01,0x16,0x03,0x58,0x09,0x1b,0xff,0xfe,0x55,0x66,0x78}, 8333}, + {{0x26,0x01,0x00,0xc0,0xc1,0x00,0x18,0x80,0x02,0x1f,0x5b,0xff,0xfe,0x3c,0x6e,0x84}, 8333}, + {{0x26,0x01,0x00,0xc8,0x41,0x00,0x07,0x70,0x02,0x3e,0xe1,0xff,0xfe,0xbe,0x73,0x6d}, 8333}, + {{0x26,0x03,0x30,0x00,0x09,0x03,0xc5,0xf1,0x46,0x8a,0x5b,0xff,0xfe,0x9e,0x89,0xdc}, 8333}, + {{0x26,0x03,0x30,0x05,0x30,0x00,0x50,0x00,0xbc,0x5a,0x72,0xac,0x36,0xe9,0x17,0x5e}, 8333}, + {{0x26,0x03,0x30,0x22,0x05,0x01,0x78,0x00,0x49,0x5c,0x72,0x8c,0xed,0x5d,0x5d,0x75}, 8333}, + {{0x26,0x04,0x01,0x80,0x00,0x01,0x03,0x46,0x00,0x00,0x00,0x00,0x00,0x00,0x68,0x4d}, 8333}, + {{0x26,0x04,0x67,0xc0,0x20,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x26,0x04,0x8d,0x80,0x01,0x00,0x00,0x00,0x80,0x65,0x4c,0x57,0x66,0x7a,0xb7,0x0f}, 8333}, + {{0x26,0x04,0x8d,0x80,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xad,0xf3,0x40,0x31}, 8333}, {{0x26,0x04,0xa8,0x80,0x00,0x02,0x00,0xd0,0x00,0x00,0x00,0x00,0x22,0xf8,0xf0,0x01}, 8333}, {{0x26,0x04,0xa8,0x80,0x00,0x02,0x00,0xd0,0x00,0x00,0x00,0x00,0x22,0xf9,0x00,0x01}, 8333}, + {{0x26,0x04,0xa8,0x80,0x00,0x02,0x00,0xd0,0x00,0x00,0x00,0x00,0x22,0xf9,0x10,0x01}, 8333}, {{0x26,0x04,0xa8,0x80,0x00,0x02,0x00,0xd0,0x00,0x00,0x00,0x00,0x22,0xf9,0xc0,0x01}, 8333}, {{0x26,0x04,0xa8,0x80,0x00,0x02,0x00,0xd0,0x00,0x00,0x00,0x00,0x22,0xf9,0xd0,0x01}, 8333}, {{0x26,0x04,0xa8,0x80,0x00,0x02,0x00,0xd0,0x00,0x00,0x00,0x00,0x22,0xf9,0xe0,0x01}, 8333}, + {{0x26,0x04,0xa8,0x80,0x00,0x02,0x00,0xd0,0x00,0x00,0x00,0x00,0x22,0xfa,0x10,0x01}, 8333}, {{0x26,0x04,0xa8,0x80,0x00,0x02,0x00,0xd0,0x00,0x00,0x00,0x00,0x22,0xfa,0x20,0x01}, 8333}, {{0x26,0x04,0xa8,0x80,0x00,0x02,0x00,0xd0,0x00,0x00,0x00,0x00,0x22,0xfa,0x30,0x01}, 8333}, - {{0x26,0x04,0xa8,0x80,0x04,0x00,0x00,0xd0,0x00,0x00,0x00,0x00,0x16,0x84,0x50,0x01}, 8333}, + {{0x26,0x04,0xa8,0x80,0x00,0x02,0x00,0xd0,0x00,0x00,0x00,0x00,0x03,0x01,0x80,0x01}, 8333}, + {{0x26,0x04,0xa8,0x80,0x00,0x02,0x00,0xd0,0x00,0x00,0x00,0x00,0x00,0x38,0xf0,0x01}, 8333}, + {{0x26,0x04,0xa8,0x80,0x00,0x02,0x00,0xd0,0x00,0x00,0x00,0x00,0x00,0x46,0xf0,0x01}, 8333}, + {{0x26,0x04,0xa8,0x80,0x00,0x02,0x00,0xd0,0x00,0x00,0x00,0x00,0x00,0xb2,0x90,0x01}, 8333}, {{0x26,0x04,0xa8,0x80,0x04,0x00,0x00,0xd0,0x00,0x00,0x00,0x00,0x1a,0xc4,0xb0,0x01}, 8333}, {{0x26,0x04,0xa8,0x80,0x04,0x00,0x00,0xd0,0x00,0x00,0x00,0x00,0x20,0x04,0x40,0x01}, 8333}, {{0x26,0x04,0xa8,0x80,0x04,0x00,0x00,0xd0,0x00,0x00,0x00,0x00,0x20,0x04,0x50,0x01}, 8333}, @@ -1016,448 +1100,439 @@ static SeedSpec6 pnSeed6_main[] = { {{0x26,0x04,0xa8,0x80,0x04,0x00,0x00,0xd0,0x00,0x00,0x00,0x00,0x20,0x04,0xe0,0x01}, 8333}, {{0x26,0x04,0xa8,0x80,0x04,0x00,0x00,0xd0,0x00,0x00,0x00,0x00,0x20,0x04,0xf0,0x01}, 8333}, {{0x26,0x04,0xa8,0x80,0x04,0x00,0x00,0xd0,0x00,0x00,0x00,0x00,0x20,0x05,0x00,0x01}, 8333}, + {{0x26,0x04,0xa8,0x80,0x04,0x00,0x00,0xd0,0x00,0x00,0x00,0x00,0x20,0x05,0x20,0x01}, 8333}, {{0x26,0x04,0xa8,0x80,0x04,0x00,0x00,0xd0,0x00,0x00,0x00,0x00,0x20,0x05,0x30,0x01}, 8333}, {{0x26,0x04,0xa8,0x80,0x04,0x00,0x00,0xd0,0x00,0x00,0x00,0x00,0x26,0x1f,0x60,0x01}, 8333}, - {{0x26,0x04,0xa8,0x80,0x04,0x00,0x00,0xd0,0x00,0x00,0x00,0x00,0x28,0xb8,0x50,0x01}, 8333}, - {{0x26,0x04,0xa8,0x80,0x04,0x00,0x00,0xd0,0x00,0x00,0x00,0x00,0x0a,0xd7,0xe0,0x01}, 8333}, {{0x26,0x05,0x4d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x50}, 8333}, - {{0x26,0x05,0x5d,0x80,0x20,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x45}, 8333}, - {{0x26,0x05,0x98,0x80,0x00,0x00,0x09,0x53,0x02,0x25,0x90,0xff,0xfe,0xd2,0xc0,0xb4}, 8333}, - {{0x26,0x06,0xc3,0x80,0x00,0x00,0x00,0x00,0x02,0x15,0x17,0xff,0xfe,0xb3,0x03,0xec}, 8333}, - {{0x26,0x07,0x1c,0x00,0x00,0x0a,0x00,0x06,0x3c,0x1c,0x1b,0x0d,0x0b,0xa4,0x8e,0xa9}, 8333}, - {{0x26,0x07,0x1c,0x00,0x00,0x0a,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00}, 8333}, - {{0x26,0x07,0x44,0x80,0x00,0x02,0x20,0x00,0x02,0x50,0x56,0xff,0xfe,0x86,0x64,0x49}, 8333}, - {{0x26,0x07,0x53,0x00,0x01,0x20,0x06,0x71,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, - {{0x26,0x07,0x53,0x00,0x01,0x20,0x09,0x62,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, + {{0x26,0x05,0x60,0x00,0xe8,0xc8,0x67,0x01,0x75,0x62,0xde,0x11,0x24,0x5c,0xf6,0xba}, 8333}, + {{0x26,0x05,0x98,0x80,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x83,0x33}, 8333}, + {{0x26,0x05,0x98,0x80,0x02,0x01,0x00,0x17,0x00,0x00,0x00,0x00,0x00,0x00,0x4b,0x7c}, 8333}, + {{0x26,0x05,0x98,0x80,0x02,0x01,0x00,0x06,0x0e,0xc4,0x7a,0xff,0xfe,0x6c,0xa6,0x60}, 8333}, + {{0x26,0x05,0xa0,0x00,0xf3,0x43,0xb7,0x00,0x50,0x54,0x00,0xff,0xfe,0xa7,0x01,0x31}, 8333}, + {{0x26,0x05,0xae,0x00,0x02,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x03}, 8333}, + {{0x26,0x05,0xc0,0x00,0x2a,0x0a,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02}, 8333}, + {{0x26,0x05,0xf7,0x00,0x00,0x80,0x08,0x00,0x00,0x00,0x00,0x00,0x37,0x24,0x08,0x1c}, 8333}, + {{0x26,0x05,0xf7,0x00,0x00,0x80,0x08,0x00,0x00,0x00,0x00,0x00,0x38,0xc1,0x2b,0x84}, 8333}, + {{0x26,0x06,0xdf,0x00,0x00,0x07,0x00,0x04,0x4c,0xaa,0x2c,0x79,0xb6,0x19,0x27,0xc9}, 8333}, + {{0x26,0x07,0x44,0x80,0x00,0x02,0x00,0x01,0x00,0x38,0x01,0x02,0x00,0x69,0x00,0x70}, 8333}, + {{0x26,0x07,0x53,0x00,0x01,0x20,0x0b,0x7e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, {{0x26,0x07,0x53,0x00,0x02,0x01,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x05,0x56}, 8333}, - {{0x26,0x07,0x53,0x00,0x02,0x03,0x01,0x18,0x37,0x33,0x00,0x00,0x00,0x00,0x14,0x14}, 8333}, + {{0x26,0x07,0x53,0x00,0x02,0x03,0x12,0x45,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, + {{0x26,0x07,0x53,0x00,0x02,0x03,0x14,0xe7,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x0f}, 8333}, + {{0x26,0x07,0x53,0x00,0x02,0x03,0x19,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, + {{0x26,0x07,0x53,0x00,0x02,0x03,0x00,0xa3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, {{0x26,0x07,0x53,0x00,0x00,0x60,0x10,0xaa,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x26,0x07,0x53,0x00,0x00,0x60,0x1e,0x83,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, - {{0x26,0x07,0x53,0x00,0x00,0x60,0x1e,0x83,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00}, 8333}, - {{0x26,0x07,0x53,0x00,0x00,0x60,0x1e,0x83,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00}, 8333}, - {{0x26,0x07,0x53,0x00,0x00,0x60,0x02,0xd0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x26,0x07,0x53,0x00,0x00,0x60,0x13,0xbb,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x26,0x07,0x53,0x00,0x00,0x60,0x1b,0xa8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x26,0x07,0x53,0x00,0x00,0x60,0x22,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, + {{0x26,0x07,0x53,0x00,0x00,0x60,0x02,0x6f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x26,0x07,0x53,0x00,0x00,0x60,0x28,0x27,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, + {{0x26,0x07,0x53,0x00,0x00,0x60,0x2c,0x16,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, {{0x26,0x07,0x53,0x00,0x00,0x60,0x3d,0xdf,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, - {{0x26,0x07,0x53,0x00,0x00,0x60,0x3f,0x3c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, - {{0x26,0x07,0x53,0x00,0x00,0x60,0x54,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, + {{0x26,0x07,0x53,0x00,0x00,0x60,0x09,0xad,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, {{0x26,0x07,0x53,0x00,0x00,0x60,0x0a,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x26,0x07,0x53,0x00,0x00,0x61,0x0f,0x4b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x26,0x07,0x90,0x00,0x00,0x00,0x00,0x01,0x50,0x54,0x00,0xff,0xfe,0x5d,0x26,0x4e}, 8333}, + {{0x26,0x07,0x53,0x00,0x00,0x61,0x0c,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, + {{0x26,0x07,0x53,0x00,0x00,0x61,0x0f,0x5b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, + {{0x26,0x07,0x90,0x00,0x00,0x00,0x00,0x06,0x00,0x01,0x00,0x00,0x03,0x6b,0x05,0xa5}, 8333}, + {{0x26,0x07,0xf1,0x78,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x06}, 8333}, + {{0x26,0x07,0xf1,0xc0,0x08,0x23,0xaf,0x00,0x00,0x00,0x00,0x00,0x00,0x35,0xbb,0xd1}, 8333}, {{0x26,0x07,0xf1,0xc0,0x08,0x46,0x9a,0x00,0x00,0x00,0x00,0x00,0x00,0x87,0xd0,0x0e}, 8333}, {{0x26,0x07,0xf2,0xd8,0x40,0x05,0x00,0x0d,0xa8,0xa2,0xee,0xff,0xfe,0xe0,0xa8,0x59}, 8333}, - {{0x26,0x07,0xf9,0x48,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x40}, 8333}, - {{0x26,0x07,0xfa,0x18,0x3a,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x50}, 8333}, - {{0x26,0x07,0xfe,0xa8,0x3c,0xa0,0x09,0x26,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x26,0x07,0xfe,0xa8,0x4d,0xa0,0x03,0xb0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x26,0x07,0xff,0x10,0x00,0xc5,0x05,0x02,0x02,0x25,0x90,0xff,0xfe,0x32,0xd4,0x46}, 8333}, - {{0x26,0x07,0xff,0x28,0x90,0x05,0x00,0x01,0x00,0x00,0x00,0x00,0x25,0x67,0x57,0xe0}, 8333}, - {{0x26,0x20,0x00,0x71,0x40,0x00,0x00,0x00,0x01,0x92,0x00,0x30,0x01,0x20,0x01,0x10}, 8333}, - {{0x26,0x20,0x00,0xb8,0x40,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x93,0x00,0x01}, 8333}, - {{0x28,0x00,0x01,0xa0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x09}, 8333}, - {{0x28,0x01,0x00,0x84,0x00,0x00,0x10,0x34,0x76,0xd4,0x35,0xff,0xfe,0x7f,0x50,0x33}, 8333}, + {{0x26,0x07,0xf4,0x70,0x00,0x14,0x00,0x0a,0x02,0x1d,0x7d,0xff,0xfe,0x01,0xbc,0xee}, 8333}, + {{0x26,0x07,0xfa,0x18,0x00,0x00,0xbe,0xef,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x12}, 8333}, + {{0x26,0x07,0xfd,0x70,0x00,0x4a,0xba,0xbe,0xb0,0x0b,0x01,0xe5,0x00,0x00,0x00,0x01}, 8333}, + {{0x26,0x07,0xfe,0xa8,0xe2,0xdf,0xf8,0x7e,0x4b,0x8e,0x8a,0x8c,0x81,0x67,0xec,0x0d}, 8333}, + {{0x26,0x07,0xfe,0xa8,0x0e,0x60,0x05,0x74,0xfd,0xbc,0xad,0xd5,0xea,0xbd,0x4d,0x9e}, 8333}, + {{0x26,0x10,0x01,0xa0,0x01,0x03,0x00,0x4a,0xde,0xad,0xbe,0xaf,0x00,0x00,0xca,0xfe}, 8333}, + {{0x26,0x10,0x01,0xa0,0x01,0x03,0x00,0x4a,0xde,0xad,0xbe,0xef,0x00,0x01,0xca,0xfe}, 8333}, + {{0x28,0x01,0x00,0x80,0x09,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x63}, 8333}, + {{0x28,0x03,0x15,0x00,0x12,0x00,0xc4,0x87,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, {{0x2a,0x00,0x16,0xd8,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x5b,0x6a,0xc2,0x61}, 8333}, - {{0x2a,0x00,0x17,0x68,0x20,0x01,0x00,0x24,0x00,0x00,0x00,0x00,0x01,0x48,0x02,0x18}, 8333}, - {{0x2a,0x00,0x19,0xe0,0x00,0x01,0x00,0x01,0x02,0x25,0x90,0xff,0xfe,0xa5,0x0f,0xc0}, 8333}, {{0x2a,0x00,0x1a,0x48,0x78,0x10,0x01,0x01,0xbe,0x76,0x4e,0xff,0xfe,0x08,0xc7,0x74}, 8333}, - {{0x2a,0x00,0x63,0x40,0x20,0x04,0x00,0x00,0x50,0x54,0x00,0xff,0xfe,0x54,0x03,0x8c}, 8333}, - {{0x2a,0x00,0x7b,0x80,0x04,0x77,0x00,0x21,0x00,0x00,0x00,0x00,0x1c,0x8c,0x83,0xa6}, 8333}, - {{0x2a,0x00,0x7c,0x80,0x00,0x00,0x00,0x71,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08}, 8333}, + {{0x2a,0x00,0x1c,0x48,0x00,0x06,0x01,0x08,0xa6,0xbf,0x01,0xff,0xfe,0x16,0x35,0xc1}, 8333}, + {{0x2a,0x00,0x1c,0x60,0x00,0x00,0x00,0x12,0xe2,0xd5,0x5e,0xff,0xfe,0x09,0x25,0x7d}, 8333}, + {{0x2a,0x00,0x1c,0xa8,0x00,0x37,0x00,0x00,0x00,0x00,0x00,0x00,0x65,0xe9,0xf4,0x38}, 8333}, + {{0x2a,0x00,0x48,0x02,0x03,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0xf9}, 8333}, {{0x2a,0x00,0x7c,0x80,0x00,0x00,0x00,0x97,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07}, 8333}, - {{0x2a,0x01,0x02,0x38,0x43,0x63,0x49,0x00,0xd8,0x5e,0xc1,0xd9,0x2b,0x32,0x61,0xd0}, 8333}, - {{0x2a,0x01,0x04,0x88,0x00,0x66,0x10,0x00,0x53,0xa9,0x02,0x2b,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x01,0x04,0x88,0x00,0x67,0x10,0x00,0x5b,0xfa,0x55,0x26,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x01,0x04,0x88,0x00,0x67,0x10,0x00,0xb0,0x1c,0x33,0x79,0x00,0x00,0x00,0x01}, 8333}, + {{0x2a,0x00,0x8a,0x60,0xe0,0x12,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x21}, 8333}, + {{0x2a,0x00,0xbb,0xe0,0x00,0x00,0x00,0x42,0x02,0x22,0x64,0xff,0xfe,0x9a,0xe2,0x06}, 8333}, + {{0x2a,0x00,0xbb,0xe0,0x00,0xcc,0x00,0x00,0x66,0x51,0x06,0xff,0xfe,0x0e,0x94,0x18}, 8333}, + {{0x2a,0x00,0xc4,0x40,0x00,0x10,0x1c,0x62,0x12,0x34,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x2a,0x00,0xc4,0x40,0x00,0x40,0x03,0x3b,0x9d,0x1c,0x77,0x26,0x55,0x71,0xc8,0x62}, 8333}, + {{0x2a,0x00,0x0c,0x70,0x00,0x01,0x02,0x13,0x02,0x46,0x00,0x56,0x00,0x95,0x00,0x01}, 8333}, + {{0x2a,0x00,0x0e,0xe2,0x12,0x00,0x19,0x00,0x02,0x0c,0x29,0xff,0xfe,0x81,0xa0,0xa3}, 8333}, + {{0x2a,0x00,0xf9,0x40,0x00,0x02,0x00,0x01,0x00,0x02,0x00,0x00,0x00,0x00,0x10,0x86}, 8333}, + {{0x2a,0x00,0xf9,0x40,0x00,0x02,0x00,0x01,0x00,0x02,0x00,0x00,0x00,0x00,0x18,0x4b}, 8333}, + {{0x2a,0x01,0x02,0x38,0x43,0x43,0x77,0x00,0x03,0xe6,0xf6,0x5c,0x5e,0x57,0x51,0x1c}, 8333}, + {{0x2a,0x01,0x02,0x38,0x43,0xa6,0x65,0x00,0x5e,0x5c,0x24,0xbb,0x5e,0x39,0xd9,0x6f}, 8333}, + {{0x2a,0x01,0x42,0x40,0x0a,0x21,0x98,0x3b,0x00,0x00,0x00,0x00,0xc0,0xa8,0x00,0x32}, 8333}, + {{0x2a,0x01,0x04,0x88,0x00,0x66,0x10,0x00,0x2e,0xa3,0x76,0x33,0x00,0x00,0x00,0x01}, 8333}, {{0x2a,0x01,0x4d,0x60,0x00,0x03,0x00,0x01,0x00,0x05,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x0a,0x10,0xa8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, {{0x2a,0x01,0x04,0xf8,0x01,0x0a,0x1d,0x8f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x0a,0x1e,0x81,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x0a,0x22,0x61,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8833}, {{0x2a,0x01,0x04,0xf8,0x01,0x0a,0x23,0x9c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 9002}, - {{0x2a,0x01,0x04,0xf8,0x01,0x0a,0x29,0x4a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x0a,0x2a,0xe0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, {{0x2a,0x01,0x04,0xf8,0x01,0x0a,0x31,0xd3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x0a,0x3f,0xe6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x0a,0x0b,0x2e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x0b,0x12,0xd7,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x0a,0x37,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x0a,0x3f,0xe4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x0a,0x41,0xc1,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x0b,0x18,0xc2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x0b,0x2a,0x9b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x0b,0x2e,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x0b,0x2e,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x0b,0x2e,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03}, 8333}, {{0x2a,0x01,0x04,0xf8,0x01,0x0b,0x0d,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, {{0x2a,0x01,0x04,0xf8,0x01,0x0b,0x0e,0x2d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, {{0x2a,0x01,0x04,0xf8,0x01,0x0b,0x0e,0xe1,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x10,0x51,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x10,0x52,0x92,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x10,0x53,0x6e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x20,0x43,0xe4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x30,0x33,0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x30,0x43,0x0b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x0b,0x0f,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x0b,0x0f,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x10,0x41,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x20,0x13,0x91,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x20,0x62,0xe6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x20,0x70,0x2e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, {{0x2a,0x01,0x04,0xf8,0x01,0x30,0x61,0x8e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, {{0x2a,0x01,0x04,0xf8,0x01,0x30,0x71,0xd2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, {{0x2a,0x01,0x04,0xf8,0x01,0x30,0x74,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x31,0x33,0xad,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x31,0x33,0xad,0xfe,0xa1,0x00,0x00,0x00,0x00,0x06,0x66}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x31,0x34,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x40,0x13,0x26,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x3b,0x27,0x1c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x3b,0x38,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x40,0x21,0x23,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x40,0x31,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x40,0x42,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, {{0x2a,0x01,0x04,0xf8,0x01,0x40,0x52,0x4a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x40,0x60,0x55,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x40,0x74,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x40,0x53,0x29,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x40,0x62,0x4c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x40,0x71,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x40,0x82,0xb6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x40,0x90,0x82,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, {{0x2a,0x01,0x04,0xf8,0x01,0x40,0x93,0x1a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x41,0x22,0x54,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x41,0x13,0xb1,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, {{0x2a,0x01,0x04,0xf8,0x01,0x41,0x22,0xae,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x50,0x11,0xd4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x50,0x70,0xa4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x50,0x72,0x6b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x41,0x24,0x26,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x41,0x54,0x91,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x50,0x32,0xf2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x50,0x41,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 5001}, + {{0x2a,0x01,0x04,0xf8,0x01,0x50,0x42,0x26,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x50,0x53,0x27,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x50,0x53,0xa4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x50,0x53,0xa4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x50,0x72,0x8f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, {{0x2a,0x01,0x04,0xf8,0x01,0x50,0x72,0xee,0x00,0x00,0x00,0x00,0x00,0x00,0x42,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x50,0x90,0xca,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x51,0x30,0xc9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x51,0x33,0x4d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x51,0x71,0x75,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x50,0x73,0x31,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x51,0x82,0xd2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x60,0x33,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, {{0x2a,0x01,0x04,0xf8,0x01,0x60,0x41,0xf0,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x33}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x60,0x54,0x2e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, {{0x2a,0x01,0x04,0xf8,0x01,0x60,0x63,0x6e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x61,0x70,0x26,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x60,0x74,0xb2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x61,0x21,0x48,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x61,0x22,0xe7,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x61,0x60,0x91,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x61,0x61,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x61,0x00,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x62,0x12,0x8d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x62,0x14,0xee,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, {{0x2a,0x01,0x04,0xf8,0x01,0x62,0x21,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x62,0x31,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x50}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x62,0x33,0xac,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x62,0x34,0x62,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x62,0x41,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, {{0x2a,0x01,0x04,0xf8,0x01,0x62,0x42,0x4c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x71,0x1c,0x1b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, {{0x2a,0x01,0x04,0xf8,0x01,0x71,0x01,0xc3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x71,0x22,0x58,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x71,0x27,0xd6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x71,0x2f,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x71,0x0d,0x23,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x72,0x10,0xda,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x72,0x05,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x71,0x32,0x48,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x71,0x0d,0x4a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x72,0x15,0x68,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x72,0x18,0x23,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x72,0x29,0xef,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, {{0x2a,0x01,0x04,0xf8,0x01,0x73,0x16,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x73,0x00,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x73,0x1c,0x9c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x73,0x29,0x4f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x73,0x2d,0x9c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, {{0x2a,0x01,0x04,0xf8,0x01,0x90,0x24,0xeb,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, {{0x2a,0x01,0x04,0xf8,0x01,0x90,0x52,0x8d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x90,0x61,0xf3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x91,0x41,0x8f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 3333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x91,0x63,0xb4,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x91,0x22,0xee,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x91,0x30,0x68,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x91,0x40,0xef,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x91,0x60,0xa5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, {{0x2a,0x01,0x04,0xf8,0x01,0x91,0x81,0xb7,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x91,0x83,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x92,0x01,0xb2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x92,0x34,0xd0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, {{0x2a,0x01,0x04,0xf8,0x01,0x92,0x04,0xa5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x92,0x52,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x92,0x62,0x8a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x83}, 8333}, {{0x2a,0x01,0x04,0xf8,0x02,0x00,0x10,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x02,0x00,0x24,0xbb,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, {{0x2a,0x01,0x04,0xf8,0x02,0x00,0x32,0xa6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x02,0x00,0x41,0x4e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x02,0x00,0x41,0x6a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x02,0x00,0x44,0x2d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x02,0x00,0x63,0x46,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x02,0x00,0x72,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, {{0x2a,0x01,0x04,0xf8,0x02,0x00,0x90,0xc3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x02,0x01,0x14,0x8d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x02,0x01,0x02,0xcc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x02,0x01,0x03,0xe3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x02,0x01,0x53,0xcc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x02,0x01,0x60,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x02,0x01,0x40,0x17,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x02,0x01,0x60,0x16,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, {{0x2a,0x01,0x04,0xf8,0x02,0x02,0x30,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x02,0x02,0x31,0xe3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, {{0x2a,0x01,0x04,0xf8,0x02,0x02,0x32,0xc6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x02,0x02,0x60,0x35,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x02,0x02,0x53,0xc3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x02,0x02,0x72,0x27,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, {{0x2a,0x01,0x04,0xf8,0x02,0x10,0x54,0x88,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x02,0x11,0x13,0xcf,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x02,0x11,0x16,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x02,0x11,0x17,0xc6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, {{0x2a,0x01,0x04,0xf8,0x02,0x11,0x1e,0x17,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x02,0x11,0x1e,0xc5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x02,0x12,0x18,0x26,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x02,0x11,0x0d,0x99,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x33}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x02,0x11,0x0f,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x02,0x12,0x1e,0x16,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x02,0x12,0x03,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x02,0x21,0x13,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0x11}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x02,0x21,0x3c,0x82,0xfe,0xa1,0x00,0x00,0x00,0x00,0x06,0x66}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x02,0x21,0x08,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, {{0x2a,0x01,0x04,0xf8,0x02,0x21,0x0f,0x59,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x10,0x26,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x10,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x10,0x29,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x10,0x5f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x10,0x64,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x10,0x6b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x10,0x6d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x10,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x11,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x11,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x11,0x34,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x11,0x35,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x11,0x3c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x11,0x5c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x11,0x5e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x11,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x11,0x72,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x11,0x7b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x11,0x7c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x11,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x11,0x81,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x11,0x85,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x11,0x86,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x11,0x87,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x11,0x88,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x11,0x89,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x01,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x01,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x15,0xa8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x1d,0xa4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x00,0xa0,0x10,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x00,0xa0,0x22,0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x00,0xa0,0x43,0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x00,0xa0,0x61,0x47,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x00,0xa0,0x74,0x6a,0x01,0x01,0x00,0x01,0x00,0x01,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x00,0xa0,0x82,0x8a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x00,0xa0,0x91,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x0b,0x10,0x50,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x10,0xdc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x1f,0xf7,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x22,0x62,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x07,0x3d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x07,0x90,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x07,0xa8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x07,0xa9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x07,0xe9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x08,0x16,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x08,0x17,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x08,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x08,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x08,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x08,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x08,0x96,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x08,0xc6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x08,0xc9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x08,0xd1,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x08,0xd2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x08,0xd9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x08,0xda,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x08,0xdc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x08,0xf1,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x09,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x09,0x27,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x09,0x39,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x09,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x09,0x51,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x09,0x67,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x09,0x6f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x09,0x7d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x09,0x82,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x09,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x0b,0x35,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x0b,0x4c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x0b,0xfe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x0c,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x0c,0x13,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x0c,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x0c,0x16,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x0c,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x0c,0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x0c,0x36,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x0c,0x39,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x0c,0x58,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x0c,0x5e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x0c,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x0c,0x72,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x0c,0x79,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x0c,0xb1,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x0c,0xf5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x0c,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x0d,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x0d,0x1b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x0d,0x67,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x0d,0x68,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x0d,0x81,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x0e,0x2d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x0e,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x0e,0x4f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x0e,0x5b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x0e,0x88,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x0f,0x69,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x0f,0x76,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x0f,0x77,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x0f,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x0f,0x89,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x0f,0x8a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x0f,0xd6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x0f,0xea,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x35,0x4c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x42,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x48,0x16,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x0d,0xcc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, {{0x2a,0x01,0x04,0xf8,0x0c,0x17,0x24,0xee,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x17,0x2c,0x16,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, {{0x2a,0x01,0x04,0xf8,0x0c,0x17,0x33,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x17,0x34,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x17,0x39,0x86,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, {{0x2a,0x01,0x04,0xf8,0x0c,0x17,0x3b,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x17,0x3d,0x85,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x17,0x42,0x71,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, {{0x2a,0x01,0x04,0xf8,0x0c,0x17,0x5d,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x17,0x63,0xa0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, {{0x2a,0x01,0x04,0xf8,0x0c,0x17,0x67,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, {{0x2a,0x01,0x04,0xf8,0x0c,0x17,0x71,0x0b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x0c,0x17,0x07,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, {{0x2a,0x01,0x04,0xf8,0x0c,0x17,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x05,0xc0,0x00,0x10,0x6e,0xb1,0x89,0xb8,0xbb,0x58,0x02,0x5a,0x60,0x50}, 8333}, {{0x2a,0x01,0x06,0x80,0x00,0x10,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, {{0x2a,0x01,0x06,0xf0,0xff,0xff,0x01,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x8d,0xcb}, 8333}, - {{0x2a,0x01,0x07,0x9d,0xb7,0xdd,0xff,0xb4,0x5d,0x86,0x70,0xb8,0xfc,0x7f,0xf2,0x53}, 8333}, {{0x2a,0x01,0x07,0xa0,0x00,0x02,0x13,0x74,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04}, 8333}, {{0x2a,0x01,0x07,0xa0,0x00,0x02,0x13,0x74,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05}, 8333}, - {{0x2a,0x01,0x07,0xa0,0x00,0x02,0x13,0x7c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03}, 8333}, + {{0x2a,0x01,0x07,0xa0,0x00,0x02,0x13,0x74,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07}, 8333}, + {{0x2a,0x01,0x07,0xa7,0x00,0x02,0x12,0x18,0x0e,0xc4,0x7a,0xff,0xfe,0x83,0x83,0xc4}, 8333}, + {{0x2a,0x01,0x07,0xa7,0x00,0x02,0x12,0x88,0xea,0x39,0x35,0xff,0xfe,0xf0,0xc4,0x29}, 8333}, + {{0x2a,0x01,0x07,0xa7,0x00,0x02,0x15,0x5c,0x34,0x6c,0x08,0xf5,0x71,0x9f,0xa6,0xb6}, 8333}, + {{0x2a,0x01,0x07,0xa7,0x00,0x02,0x15,0x65,0x94,0x84,0x50,0x9b,0x2a,0x3b,0xa7,0x73}, 8333}, {{0x2a,0x01,0x07,0xc8,0xaa,0xaa,0x03,0x73,0x50,0x54,0x00,0xff,0xfe,0xb3,0x29,0x47}, 8333}, - {{0x2a,0x01,0x07,0xc8,0xaa,0xaa,0x03,0xa0,0x50,0x54,0x00,0xff,0xfe,0x8c,0x97,0x4c}, 8333}, - {{0x2a,0x01,0x07,0xc8,0xaa,0xb0,0x04,0xb7,0x91,0x0d,0x62,0x5e,0xa1,0x3e,0xc3,0x42}, 8333}, {{0x2a,0x01,0x07,0xc8,0xaa,0xb5,0x03,0xe6,0x50,0x54,0x00,0xff,0xfe,0xd7,0x4e,0x54}, 8333}, - {{0x2a,0x01,0x07,0xc8,0xaa,0xb5,0x04,0x1e,0x50,0x54,0x00,0xff,0xfe,0x38,0xf4,0xfb}, 8333}, {{0x2a,0x01,0x07,0xc8,0xaa,0xba,0x03,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x83,0x33}, 8333}, - {{0x2a,0x01,0x07,0xc8,0xaa,0xbc,0x01,0x8c,0x50,0x54,0x00,0xff,0xfe,0xfd,0x3b,0x49}, 8333}, {{0x2a,0x01,0x07,0xc8,0xaa,0xbd,0x03,0xd5,0x50,0x54,0x00,0xff,0xfe,0x95,0xf5,0x86}, 8333}, - {{0x2a,0x01,0x7e,0x00,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0x50,0x94,0xb8}, 8333}, - {{0x2a,0x01,0x8e,0x01,0xb9,0x43,0x3a,0x63,0xd2,0x50,0x99,0xff,0xfe,0x1f,0x4f,0xb2}, 8333}, - {{0x2a,0x01,0xb2,0xe0,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40}, 8333}, + {{0x2a,0x01,0x07,0xc8,0xaa,0xc1,0x04,0x53,0x0c,0x50,0xfa,0x3a,0x02,0x29,0x85,0x04}, 8333}, + {{0x2a,0x01,0x07,0xc8,0xaa,0xc7,0x00,0x5e,0x50,0x54,0x00,0xff,0xfe,0xe9,0xbd,0xf7}, 8333}, + {{0x2a,0x01,0xbe,0x00,0x00,0x10,0x02,0x01,0x00,0x00,0x00,0x80,0xce,0xce,0x00,0x01}, 8333}, + {{0x2a,0x01,0xcb,0x00,0x02,0xca,0xb7,0x00,0x20,0x79,0xb3,0x3f,0xcf,0x5a,0x59,0x58}, 8333}, + {{0x2a,0x01,0xcb,0x00,0x00,0xb3,0xd3,0x00,0x90,0xfd,0xe3,0xb1,0x28,0xde,0x11,0x6c}, 8333}, + {{0x2a,0x01,0xcb,0x14,0x00,0xb8,0xa5,0x00,0xdd,0x9d,0x80,0xf5,0xd3,0x05,0x68,0xf9}, 8333}, {{0x2a,0x01,0x00,0xd0,0x00,0x00,0x00,0x1c,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x45}, 8333}, - {{0x2a,0x01,0x00,0xd0,0x8f,0xc3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x0e,0x34,0xec,0x29,0xe8,0xd0,0x25,0xc7,0xc1,0xce,0xb7,0xa3,0xd2,0x38}, 8333}, - {{0x2a,0x01,0x0e,0x34,0xec,0x4a,0xc2,0xd0,0x1c,0xf3,0x40,0xd2,0xa7,0x9f,0x39,0x01}, 8333}, - {{0x2a,0x01,0x0e,0x34,0xee,0xd7,0x66,0x70,0xec,0x1b,0xbf,0x7c,0xb0,0x12,0x60,0x69}, 8333}, + {{0x2a,0x01,0x0e,0x0a,0x00,0x0d,0x6e,0xa0,0x00,0x56,0xde,0xab,0x1b,0x2f,0x30,0x0b}, 8333}, + {{0x2a,0x01,0x0e,0x34,0xec,0xfd,0x19,0x10,0x58,0xfb,0xc2,0xff,0xfe,0xac,0x57,0x1f}, 8333}, + {{0x2a,0x01,0x0e,0x34,0xee,0xd7,0x66,0x70,0xe1,0x50,0x6b,0xb0,0xf1,0x1b,0xd6,0xd8}, 8333}, {{0x2a,0x01,0x0e,0x35,0x24,0x33,0xe3,0x20,0x9c,0x8e,0x6f,0xf0,0x99,0x0f,0xf0,0x6e}, 8333}, {{0x2a,0x01,0x0e,0x35,0x2e,0xe5,0x06,0x10,0x02,0x1f,0xd0,0xff,0xfe,0x4e,0x74,0x60}, 8333}, - {{0x2a,0x02,0x12,0x05,0x50,0x51,0xa6,0x40,0xd6,0xae,0x52,0xff,0xfe,0xa3,0x00,0xac}, 8333}, + {{0x2a,0x01,0x0e,0x35,0x8b,0xe7,0x53,0xd0,0xb8,0xd5,0xde,0x58,0x95,0xb5,0xdd,0x16}, 8333}, + {{0x2a,0x01,0x0e,0x35,0x8b,0xff,0x70,0xb0,0x1e,0x1b,0x0d,0xff,0xfe,0x0b,0x23,0x6d}, 8333}, + {{0x2a,0x02,0x12,0x05,0x34,0xc3,0xba,0xe0,0xba,0xae,0xed,0xff,0xfe,0xea,0x94,0x45}, 8333}, + {{0x2a,0x02,0x12,0x05,0x50,0x04,0xde,0x00,0x0c,0x84,0x04,0xa1,0xe7,0x60,0xcf,0x90}, 8333}, + {{0x2a,0x02,0x12,0x05,0x50,0x76,0xee,0x00,0xd6,0xc9,0xef,0xff,0xfe,0x65,0xfb,0xfb}, 8333}, + {{0x2a,0x02,0x12,0x05,0xc6,0xbe,0x84,0xe0,0xca,0x2a,0x14,0xff,0xfe,0x0b,0x80,0x3b}, 8333}, + {{0x2a,0x02,0x12,0x06,0x45,0xc3,0xbe,0x80,0xd4,0xa4,0x32,0x15,0xaa,0xf0,0x85,0xaa}, 8333}, {{0x2a,0x02,0x12,0x0b,0x2c,0x2a,0x5e,0xc0,0x10,0xdd,0x31,0xff,0xfe,0x42,0x50,0x79}, 8333}, - {{0x2a,0x02,0x01,0x68,0x62,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x14}, 8333}, + {{0x2a,0x02,0x12,0x0b,0x2c,0x3f,0x3f,0xc0,0x10,0xdd,0x31,0xff,0xfe,0x42,0x50,0x79}, 8333}, + {{0x2a,0x02,0x12,0x1e,0x3e,0x87,0x00,0x00,0x7d,0x3a,0xfe,0x09,0xb6,0x19,0x6b,0x4b}, 8333}, + {{0x2a,0x02,0x01,0x68,0x42,0x0b,0x00,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20}, 8333}, + {{0x2a,0x02,0x01,0x68,0x4a,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x39}, 8333}, + {{0x2a,0x02,0x01,0x68,0x4a,0x35,0x00,0x00,0x2e,0x44,0xfd,0xff,0xfe,0x9a,0x46,0xdc}, 8333}, + {{0x2a,0x02,0x01,0x80,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x05,0x17,0x10,0xb6}, 8333}, {{0x2a,0x02,0x01,0x80,0x00,0x06,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18}, 8333}, - {{0x2a,0x02,0x01,0x80,0x00,0x06,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xed}, 8333}, - {{0x2a,0x02,0x18,0x11,0xb7,0x07,0x01,0x16,0x8c,0x1f,0xc5,0xbe,0xbf,0x3a,0x54,0xdf}, 8333}, + {{0x2a,0x02,0x18,0x10,0x1d,0x13,0x72,0x00,0x84,0x8b,0xc4,0xc4,0x52,0x6b,0xe6,0x57}, 8333}, + {{0x2a,0x02,0x18,0x1f,0x00,0x00,0x21,0x61,0x08,0xf0,0x54,0xb2,0x22,0x2c,0xb3,0x15}, 8333}, {{0x2a,0x02,0x20,0xc8,0x14,0x22,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa3}, 8333}, + {{0x2a,0x02,0x21,0x68,0x08,0x0d,0x06,0xe8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, {{0x2a,0x02,0x21,0x68,0x0d,0x05,0x2c,0x00,0x02,0x16,0x3e,0xff,0xfe,0xf7,0xa0,0x99}, 8333}, - {{0x2a,0x02,0x27,0xf8,0x20,0x12,0x00,0x00,0xe9,0xf7,0x26,0x8f,0xc4,0x41,0x61,0x29}, 8333}, + {{0x2a,0x02,0x25,0x28,0x05,0x03,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14}, 8333}, {{0x2a,0x02,0x28,0x08,0x54,0x01,0x00,0x00,0x02,0x25,0x90,0xff,0xfe,0x4e,0xee,0x42}, 8333}, {{0x2a,0x02,0x03,0x90,0x90,0x00,0x00,0x00,0x02,0x18,0x7d,0xff,0xfe,0x10,0xbe,0x33}, 8333}, {{0x2a,0x02,0x7a,0xa0,0x12,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0xbd,0x4e,0x12,0x19}, 8333}, {{0x2a,0x02,0x7a,0xa0,0x16,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x90,0xeb,0xa2}, 8333}, - {{0x2a,0x02,0x7a,0xa0,0x16,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0xa7,0xa2,0x7e,0x86}, 8333}, + {{0x2a,0x02,0x7b,0x40,0x50,0xd0,0xe0,0xd9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x2a,0x02,0x7b,0x40,0x50,0xd0,0xe3,0x35,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x2a,0x02,0x7b,0x40,0xc2,0x87,0x53,0xaf,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x2a,0x02,0x7b,0x40,0xd4,0x18,0x60,0xc5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x2a,0x02,0x7b,0x40,0xd4,0x18,0x6a,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x2a,0x02,0x81,0x08,0x9c,0x3f,0xdd,0x18,0x92,0x2b,0x34,0xff,0xfe,0x30,0xac,0x42}, 8333}, + {{0x2a,0x02,0x81,0x09,0x9a,0xc0,0x2a,0x2b,0x70,0x7a,0xad,0x1a,0x07,0x0c,0x84,0xa9}, 8333}, + {{0x2a,0x02,0x81,0x0d,0x8a,0x40,0x36,0xf8,0x9a,0xf2,0xb3,0xff,0xfe,0xe8,0x6d,0x7a}, 8333}, + {{0x2a,0x02,0x81,0x0d,0x98,0x40,0x7e,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x27}, 8333}, + {{0x2a,0x02,0x09,0x30,0x00,0x01,0x00,0x00,0x02,0x50,0x56,0xff,0xfe,0x8e,0x28,0x19}, 8333}, + {{0x2a,0x02,0xc2,0x00,0x00,0x01,0x00,0x10,0x00,0x02,0x00,0x04,0x03,0x34,0x00,0x01}, 8333}, + {{0x2a,0x02,0xc2,0x00,0x00,0x01,0x00,0x10,0x00,0x02,0x00,0x05,0x02,0x27,0x00,0x01}, 8333}, {{0x2a,0x02,0xc2,0x00,0x00,0x01,0x00,0x10,0x00,0x02,0x00,0x05,0x08,0x00,0x00,0x01}, 8333}, - {{0x2a,0x02,0xc2,0x05,0x20,0x02,0x25,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x17}, 8333}, + {{0x2a,0x02,0xc2,0x05,0x00,0x00,0x51,0x45,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, {{0x2a,0x02,0xc2,0x05,0x20,0x08,0x02,0x72,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x02,0xc2,0x05,0x20,0x10,0x54,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x02,0xc2,0x05,0x30,0x01,0x67,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x02,0xc2,0x05,0x30,0x01,0x77,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x02,0xc2,0x05,0x30,0x02,0x08,0x88,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x2a,0x02,0xc2,0x05,0x20,0x08,0x71,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x2a,0x02,0xc2,0x05,0x20,0x09,0x78,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x2a,0x02,0xc2,0x05,0x20,0x14,0x19,0x81,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x2a,0x02,0xc2,0x05,0x20,0x14,0x35,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x2a,0x02,0xc2,0x05,0x20,0x15,0x24,0x75,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x2a,0x02,0xc2,0x05,0x30,0x02,0x27,0x87,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, {{0x2a,0x02,0xc2,0x07,0x20,0x02,0x90,0x13,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x02,0xc2,0x07,0x20,0x08,0x33,0x92,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x02,0xc2,0x07,0x20,0x08,0x83,0x37,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x2a,0x02,0xc2,0x07,0x20,0x07,0x46,0x99,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x2a,0x02,0xc2,0x07,0x20,0x08,0x65,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, {{0x2a,0x02,0xc2,0x07,0x20,0x09,0x02,0x13,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x02,0xc2,0x07,0x20,0x10,0x77,0x51,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x02,0xc2,0x07,0x20,0x10,0x79,0x86,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x02,0xc2,0x07,0x20,0x11,0x78,0x29,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x02,0xc2,0x07,0x20,0x11,0x82,0x99,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x02,0xc2,0x07,0x20,0x12,0x21,0x33,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x2a,0x02,0xc2,0x07,0x20,0x11,0x25,0x83,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, {{0x2a,0x02,0xc2,0x07,0x20,0x12,0x02,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x02,0xc2,0x07,0x20,0x12,0x26,0x82,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x02,0xc2,0x07,0x20,0x12,0x36,0x35,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x2a,0x02,0xc2,0x07,0x20,0x12,0x29,0x17,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, {{0x2a,0x02,0xc2,0x07,0x20,0x12,0x48,0x26,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x02,0xc2,0x07,0x20,0x12,0x56,0x68,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x2a,0x02,0xc2,0x07,0x20,0x13,0x31,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x2a,0x02,0xc2,0x07,0x20,0x14,0x41,0x99,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x2a,0x02,0xc2,0x07,0x20,0x14,0x56,0x39,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x2a,0x02,0xc2,0x07,0x20,0x14,0x71,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x2a,0x02,0xc2,0x07,0x20,0x14,0x81,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x2a,0x02,0xc2,0x07,0x20,0x14,0x85,0x36,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x2a,0x02,0xc2,0x07,0x20,0x14,0x94,0x33,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x2a,0x02,0xc2,0x07,0x20,0x15,0x49,0x97,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x2a,0x02,0xc2,0x07,0x20,0x15,0x59,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, {{0x2a,0x02,0xc2,0x07,0x30,0x01,0x58,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x2a,0x02,0xc2,0x07,0x30,0x01,0x76,0x45,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, {{0x2a,0x02,0xc2,0x07,0x30,0x01,0x77,0x76,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x02,0xc2,0x07,0x30,0x02,0x06,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x2a,0x02,0xc2,0x07,0x30,0x01,0x93,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x2a,0x02,0xc2,0x07,0x30,0x02,0x12,0x87,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x2a,0x02,0xc2,0x07,0x30,0x02,0x15,0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x2a,0x02,0xc2,0x07,0x30,0x02,0x24,0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x2a,0x02,0xc2,0x07,0x30,0x02,0x44,0x31,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x2a,0x02,0xc2,0x07,0x30,0x02,0x08,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x2a,0x02,0x0c,0x7f,0x7c,0x2c,0xa8,0x00,0x42,0x8d,0x5c,0xff,0xfe,0x74,0x14,0x55}, 8333}, + {{0x2a,0x02,0x0c,0x7f,0xd8,0x26,0x19,0x01,0x02,0x0c,0x29,0xff,0xfe,0x11,0x9d,0x0e}, 8333}, {{0x2a,0x02,0xce,0x80,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x03,0x22,0x60,0x01,0x1e,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08}, 8333}, - {{0x2a,0x03,0x22,0x60,0x01,0x1e,0x03,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03}, 8333}, {{0x2a,0x03,0x40,0x00,0x00,0x02,0x04,0x96,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08}, 8333}, - {{0x2a,0x03,0x40,0x00,0x00,0x06,0x12,0xe7,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x03,0x40,0x00,0x00,0x06,0x41,0x6c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x53}, 8333}, + {{0x2a,0x03,0x73,0x80,0x03,0x00,0x00,0x16,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, + {{0x2a,0x03,0x73,0x80,0x03,0x00,0x00,0x07,0xa1,0x9f,0xeb,0x0b,0x0a,0xe0,0x6a,0xad}, 8333}, {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x12,0x19,0x60,0x01}, 8333}, - {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x1b,0x99,0xc0,0x01}, 8333}, - {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x1b,0x99,0xe0,0x01}, 8333}, - {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x1b,0x9a,0x30,0x01}, 8333}, - {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x23,0xf7,0x10,0x01}, 8333}, - {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x23,0xf7,0x20,0x01}, 8333}, - {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x23,0xf7,0x40,0x01}, 8333}, - {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x23,0xf7,0x50,0x01}, 8333}, - {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x23,0xf7,0x70,0x01}, 8333}, - {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x23,0xf7,0x90,0x01}, 8333}, - {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x23,0xfb,0x10,0x01}, 8333}, - {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x23,0xfb,0x20,0x01}, 8333}, - {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x23,0xfb,0x30,0x01}, 8333}, - {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x23,0xfb,0x50,0x01}, 8333}, {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x23,0xfb,0x60,0x01}, 8333}, - {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x23,0xfb,0x80,0x01}, 8333}, - {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x23,0xff,0xb0,0x01}, 8333}, - {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x24,0x00,0x00,0x01}, 8333}, - {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x24,0x00,0x30,0x01}, 8333}, - {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x24,0x00,0x40,0x01}, 8333}, - {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x24,0x00,0xe0,0x01}, 8333}, - {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x24,0x00,0xf0,0x01}, 8333}, - {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x24,0x01,0xe0,0x01}, 8333}, - {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x01}, 8333}, - {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x24,0x02,0x20,0x01}, 8333}, - {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x24,0x02,0x80,0x01}, 8333}, - {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x24,0x02,0x90,0x01}, 8333}, - {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x24,0x02,0xb0,0x01}, 8333}, - {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x24,0x02,0xd0,0x01}, 8333}, - {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x24,0x02,0xe0,0x01}, 8333}, - {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x24,0x03,0x10,0x01}, 8333}, - {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x24,0x03,0x20,0x01}, 8333}, - {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x24,0x03,0x30,0x01}, 8333}, - {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x24,0x03,0x40,0x01}, 8333}, - {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x24,0x03,0x60,0x01}, 8333}, - {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x24,0x03,0xa0,0x01}, 8333}, - {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x24,0x03,0xb0,0x01}, 8333}, - {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x24,0x03,0xe0,0x01}, 8333}, - {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x24,0x03,0xf0,0x01}, 8333}, - {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x24,0x04,0x00,0x01}, 8333}, - {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x24,0x04,0x30,0x01}, 8333}, - {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x24,0x04,0x40,0x01}, 8333}, - {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x24,0x04,0x60,0x01}, 8333}, - {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x24,0x04,0x80,0x01}, 8333}, - {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x24,0x04,0x90,0x01}, 8333}, - {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x24,0x04,0xb0,0x01}, 8333}, - {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x24,0x05,0x20,0x01}, 8333}, - {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x24,0x05,0x30,0x01}, 8333}, - {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x24,0x05,0x80,0x01}, 8333}, - {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x24,0x05,0x90,0x01}, 8333}, - {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x24,0x05,0xa0,0x01}, 8333}, {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x44,0xb8,0x90,0x01}, 8333}, + {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x44,0xb8,0xa0,0x01}, 8333}, + {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x44,0xb8,0xb0,0x01}, 8333}, {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x44,0xb8,0xe0,0x01}, 8333}, {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x44,0xb8,0xf0,0x01}, 8333}, {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x44,0xb9,0x00,0x01}, 8333}, {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x44,0xb9,0x10,0x01}, 8333}, {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x44,0xb9,0x20,0x01}, 8333}, {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x44,0xb9,0x40,0x01}, 8333}, + {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x01}, 8333}, + {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x5e,0x48,0xd0,0x01}, 8333}, + {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x00,0xc7,0xf0,0x01}, 8333}, + {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x00,0xe9,0xf0,0x01}, 8333}, + {{0x2a,0x03,0xff,0x40,0x4e,0xd1,0x10,0x04,0xa2,0x36,0x9f,0xff,0xfe,0xb4,0xf9,0xf8}, 8333}, {{0x2a,0x04,0x21,0x80,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x94}, 8333}, - {{0x2a,0x04,0x35,0x42,0x10,0x00,0x09,0x10,0x84,0x92,0xb8,0xff,0xfe,0x91,0x71,0x1d}, 8333}, - {{0x2a,0x04,0x52,0xc0,0x01,0x01,0x01,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0xba,0x8e}, 8333}, + {{0x2a,0x04,0x21,0x80,0x00,0x01,0x00,0x06,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x14}, 8333}, + {{0x2a,0x04,0x52,0xc0,0x01,0x01,0x01,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x49,0x6d}, 8333}, + {{0x2a,0x04,0xdb,0xc3,0xff,0xfe,0x00,0x00,0xe6,0x1f,0x13,0xff,0xfe,0x95,0x84,0x01}, 8333}, {{0x2a,0x05,0x35,0x80,0xd4,0x00,0x14,0x0d,0xda,0x6e,0x82,0x6e,0xe7,0x71,0x41,0x00}, 8333}, - {{0x2a,0x06,0x9f,0xc0,0x2a,0x06,0x9f,0xc0,0x2a,0x06,0x9f,0xc1,0x06,0x7c,0xe7,0x06}, 8333}, + {{0x2a,0x05,0xbe,0xc0,0x00,0x01,0x00,0x01,0x02,0x16,0x3e,0xff,0xfe,0x73,0xd2,0x0a}, 8333}, + {{0x2a,0x06,0x3d,0x80,0x00,0x0b,0x00,0x01,0x48,0xb4,0xbe,0xdd,0x69,0x64,0x54,0xac}, 8333}, + {{0x2a,0x06,0x3d,0x80,0x00,0x0b,0x00,0x01,0xae,0x1f,0x6b,0xff,0xfe,0x13,0xc1,0x3e}, 8333}, + {{0x2a,0x06,0x3d,0x80,0x00,0x0b,0x00,0x02,0xae,0x1f,0x6b,0xff,0xfe,0x13,0xc1,0x3e}, 8333}, + {{0x2a,0x06,0x3d,0x80,0x00,0x0b,0x00,0x02,0x0e,0xc4,0x7a,0xff,0xfe,0x96,0xb5,0x70}, 8333}, + {{0x2a,0x07,0x57,0x40,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0xad,0x9c,0xec}, 8333}, + {{0x2a,0x07,0x57,0x40,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xb5,0x30,0x82}, 8333}, + {{0x2a,0x07,0x57,0x41,0x00,0x00,0x0d,0x8b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xd6,0xbc,0x4a,0x3c,0x6d,0x03,0xa9,0x4e,0x1f,0x55}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xd1,0x62,0x6b,0xbc,0x9d,0x61,0xc8,0x63,0xe1,0xcc}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xda,0x0e,0x96,0xca,0xb6,0x16,0xef,0xe1,0xbf,0x4e}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xdd,0xbf,0xf3,0xc5,0x0b,0x37,0xa1,0xee,0x39,0xeb}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xe2,0xe5,0xc7,0x79,0x12,0xc8,0x87,0xf6,0x28,0xb6}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xe3,0xf6,0x00,0xa6,0xf0,0x7b,0xf3,0x74,0x7e,0x08}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xd1,0x13,0xd8,0x3b,0x11,0xa3,0x88,0x84,0x80,0x61}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xd1,0x79,0x73,0x7d,0x9b,0x37,0xab,0x3b,0xc0,0x43}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xda,0x0d,0xe1,0xd2,0x65,0x18,0xfc,0xf5,0x2a,0xdc}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xdc,0x79,0xc1,0x8f,0x29,0x44,0xf2,0xdc,0x00,0xf6}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xee,0xe7,0x24,0xcf,0xd9,0x86,0xd0,0x09,0x57,0xb0}, 8333}, {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xef,0x3c,0x49,0x0b,0xc1,0x74,0xc2,0x92,0x86,0xe1}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xeb,0x24,0x59,0xe2,0x79,0x5c,0xa4,0xa8,0xf2,0x93}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xec,0xf1,0xe8,0xdd,0xe6,0x8a,0x98,0x36,0xab,0x80}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x02,0x99,0x0c,0x51,0x03,0x89,0x7b,0xe4,0x3f,0x5e}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xe9,0x17,0x9b,0x08,0xdc,0xbe,0x24,0xe3,0x01,0x6e}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xee,0x0d,0x2c,0x85,0x41,0x08,0x29,0x94,0xdf,0xec}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xf7,0x21,0x13,0xe2,0xe6,0x5e,0x12,0x93,0xa9,0xa4}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xf7,0x88,0x7c,0x41,0x55,0x51,0x3d,0x31,0xf0,0xb8}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xf4,0x69,0x87,0x6d,0x58,0x95,0x47,0xaf,0x8d,0x65}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xf4,0xe3,0xf1,0x48,0xf5,0xbf,0x41,0x86,0x66,0x67}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xfb,0x68,0x1a,0x6a,0xd8,0xdd,0xd1,0x93,0x5b,0x34}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xfb,0x68,0x8f,0x10,0x92,0x98,0x2d,0xa2,0xfe,0xec}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xfc,0x0d,0xe4,0x8d,0x80,0x39,0x6e,0x06,0x03,0x1d}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x00,0x7e,0x59,0x8c,0xb6,0xf4,0x0e,0x3b,0xee,0x24}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x02,0x61,0x59,0x61,0x66,0xed,0xc7,0xda,0xcb,0x78}, 8333}, {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x02,0xce,0xb2,0x1a,0x69,0x50,0xd8,0x18,0x4a,0xb3}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x08,0x0a,0xae,0xa1,0xc0,0x9a,0xcd,0x3f,0x8c,0xcb}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x0f,0x47,0xe2,0x4c,0xab,0x4b,0x34,0xb4,0x93,0xb8}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x0f,0xee,0x48,0xfd,0x8e,0x22,0x11,0x9e,0xf8,0x4f}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x0c,0x6d,0x02,0x65,0xbe,0x59,0x3b,0xcb,0x68,0x21}, 8333}, {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x0d,0x1f,0xd6,0xf4,0x9b,0x55,0x23,0x54,0xe4,0xbb}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x12,0x70,0x61,0xfd,0xf4,0xea,0xe0,0xa5,0x63,0xa9}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x0d,0x41,0x8f,0x78,0x99,0x35,0xec,0xef,0xd9,0x3c}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x11,0x95,0xca,0x69,0x77,0x8d,0x58,0xbe,0x26,0xa1}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x13,0xf0,0x58,0x06,0x5c,0x2c,0xb7,0x56,0x85,0xe5}, 8333}, {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x16,0x2a,0xf3,0x4f,0x5d,0xd7,0xf8,0x8e,0x87,0xe2}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x1e,0xbd,0x3a,0x3d,0x81,0x38,0xd2,0xcb,0xe6,0xcc}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x1f,0xad,0x40,0xc8,0x73,0x8f,0x3c,0x31,0xf5,0x48}, 8333}, {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x19,0x14,0x9e,0x58,0x02,0xc5,0x9f,0x09,0x00,0x7b}, 8333}, {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x1c,0x1f,0x7b,0x2d,0xed,0xae,0xf3,0xb3,0xe5,0xab}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x1c,0x41,0x1c,0xbf,0x02,0x0c,0xef,0x60,0x89,0x63}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x1c,0x5f,0xc7,0xd4,0x89,0xc0,0x6f,0xa2,0x24,0x71}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x1c,0xa3,0x68,0x59,0x09,0x9c,0xaa,0x8e,0x0c,0xaa}, 42434}, {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x1d,0xd4,0xc9,0xb2,0xc8,0x87,0xc6,0x39,0x9a,0x8b}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x27,0x93,0xdf,0xe5,0x58,0x40,0x69,0xa9,0x30,0x03}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x26,0xf2,0x12,0x3c,0xf5,0x14,0x19,0x91,0x41,0x51}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x20,0x03,0xd7,0x3f,0x79,0xd7,0x1b,0xf2,0x40,0x7d}, 8333}, {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x22,0x45,0x02,0x56,0x89,0x14,0x17,0x38,0x37,0xe3}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x24,0x0c,0x19,0xe8,0xc7,0x2d,0x65,0x23,0x86,0xae}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x29,0x91,0x93,0x28,0x6d,0x68,0xd0,0xb7,0x79,0x40}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x2c,0x2f,0x47,0xf1,0xc4,0xae,0xf6,0x42,0x20,0x66}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x30,0x7b,0x87,0xc2,0x7e,0xd8,0xe9,0xbb,0x14,0xed}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x31,0x87,0x8d,0x3c,0x3a,0x05,0x56,0x19,0xa6,0xd0}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x23,0xf4,0xc4,0xe5,0xd7,0xda,0xaa,0x1f,0x02,0xfc}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x2e,0xf8,0x29,0x1c,0xe0,0x5e,0x9b,0x45,0xa6,0x42}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x2e,0xda,0x54,0x38,0xfa,0xfa,0x75,0x75,0x94,0x9d}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x2f,0x8f,0xfa,0x2b,0x18,0x40,0xb2,0xbc,0x55,0x8b}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x28,0x09,0x61,0x65,0x34,0xcc,0xb9,0x62,0xdc,0xf5}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x2b,0x55,0xb1,0xa1,0xce,0x35,0xc0,0xb9,0x7e,0x3c}, 8333}, {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x38,0x0e,0x75,0xb8,0x99,0xc1,0x60,0x7d,0x9c,0x48}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x41,0xc7,0x5f,0x07,0x39,0xd1,0xaf,0xfd,0x16,0x5f}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x41,0x63,0x48,0x37,0x97,0xfb,0x42,0xde,0xbc,0x20}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x42,0x58,0x16,0x65,0x14,0x68,0x65,0x9c,0xde,0x69}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x43,0x1e,0x48,0xa0,0x0b,0x6e,0x41,0xb9,0xc0,0xc7}, 8333}, {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x43,0x7f,0x1e,0xa0,0x8e,0xfb,0x8c,0xab,0x85,0xa4}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x45,0x08,0xd5,0x88,0x11,0x93,0x65,0x29,0xa1,0x17}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x4c,0xd5,0x26,0xb9,0x54,0x90,0x72,0xc9,0x7e,0xcb}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x57,0x84,0xf2,0x6c,0xe0,0x9c,0x63,0x7a,0xb7,0x3e}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x54,0xac,0x5c,0x52,0x2d,0x32,0xd9,0xee,0xd3,0xe1}, 8333}, {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x55,0x47,0xce,0x4a,0xdf,0x92,0x83,0xd2,0xb9,0x76}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x63,0x7f,0xce,0x1c,0x28,0x70,0x30,0xdd,0xb9,0x32}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x64,0xb8,0xd9,0xc6,0x28,0x91,0x6f,0x97,0xd5,0x98}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x6f,0x57,0x0b,0x3d,0x20,0x0c,0x0d,0xed,0x20,0xf7}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x5e,0x9f,0x1a,0x66,0x3b,0x63,0x4e,0x82,0x52,0x86}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x5f,0x5c,0x31,0xa7,0x9e,0x7d,0x5c,0x31,0xe4,0x7c}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x59,0x95,0x50,0xd6,0x2e,0xf7,0xd2,0xe6,0x3a,0x56}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x5b,0x8a,0xb2,0x86,0xf4,0x65,0xd9,0xde,0x85,0x10}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x67,0x93,0x13,0xc6,0x15,0x48,0x5b,0x95,0x83,0x71}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x65,0x5c,0xcb,0x14,0x63,0x1c,0x0b,0x03,0x6d,0x70}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x77,0x06,0x50,0xfa,0x6f,0xde,0xca,0x5d,0x2e,0x1f}, 8333}, {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x77,0x24,0xbe,0xb4,0x1e,0x49,0x20,0x64,0x6d,0x7e}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x73,0x13,0x5d,0x71,0xa1,0x12,0xb8,0xae,0xd0,0x7e}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x7b,0xb6,0x9d,0x1c,0xaa,0x61,0x7f,0x23,0xef,0xce}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x7c,0x84,0xef,0x06,0xe9,0x25,0x96,0x98,0x8b,0x37}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x82,0x3b,0x88,0xf9,0x75,0x58,0x95,0x92,0x95,0xd1}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x77,0xf5,0x9c,0x66,0x35,0xff,0xc8,0x0d,0x06,0xd4}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x73,0x27,0x2e,0x38,0xa7,0xb4,0x12,0x3a,0x2e,0x3e}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x78,0x5a,0xb7,0xfd,0x9c,0x55,0x12,0xc0,0x79,0x19}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x78,0x8a,0x79,0x0e,0x19,0x97,0xa1,0xed,0xc7,0x14}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x7a,0x4c,0x71,0x22,0xb9,0x53,0x89,0x19,0x12,0x43}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x7e,0x75,0x7e,0xb4,0xa7,0x4a,0x1f,0x23,0x83,0x3b}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x80,0x2e,0xce,0xc9,0xec,0xbf,0x47,0xa5,0x6e,0x8f}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x81,0x1f,0x33,0xf7,0x83,0x06,0x24,0xc7,0xe3,0xb8}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x81,0xad,0xc4,0x87,0xd8,0x42,0x9f,0xce,0x61,0xe0}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x82,0x7c,0x88,0xc1,0xba,0x47,0xf6,0x41,0x94,0xbd}, 8333}, {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x82,0xeb,0xe7,0xe3,0xc7,0x1c,0xf2,0x87,0xb6,0x6d}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x86,0x1a,0xc7,0x98,0x61,0x7e,0xb7,0x7c,0x15,0xa9}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x89,0xe6,0x0b,0x0a,0x5f,0xb8,0x15,0xc3,0x23,0x73}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x85,0x78,0x78,0x7f,0xa0,0x96,0x11,0x35,0x30,0x12}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x8e,0xc7,0x27,0x24,0xa7,0xb0,0x99,0xfb,0xfd,0xfe}, 8333}, {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x8a,0x40,0x2b,0x4b,0xfd,0xf8,0x11,0xef,0x2e,0x24}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x8a,0x56,0xd7,0xec,0xf6,0xac,0x64,0xc0,0x3f,0xc4}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x8a,0x87,0x58,0x0a,0x33,0x2d,0x7d,0x89,0xf1,0xd8}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x8a,0xc0,0x54,0x31,0x42,0x9d,0x73,0xed,0xad,0x66}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x8a,0xd3,0xc7,0xbd,0xca,0xe0,0xdb,0x21,0xd3,0xad}, 8333}, {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x91,0x1d,0x25,0x50,0x79,0x57,0xaa,0xdf,0x32,0x19}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x98,0x31,0x04,0x77,0xf3,0x2a,0x31,0xfb,0xee,0xaa}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x93,0x26,0xc3,0x88,0x96,0xa5,0x7d,0x34,0xe1,0xb5}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x94,0xd0,0xbd,0xc8,0x55,0x80,0x6a,0x77,0x5a,0xa1}, 8333}, {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x98,0x8e,0xe7,0xfb,0xfe,0x4f,0xb0,0xf7,0xda,0xcc}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x9b,0x8d,0x4a,0xe3,0xb4,0x7e,0x28,0x29,0xd0,0x77}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x9b,0xef,0xc4,0x81,0xbd,0x6e,0x81,0xa1,0x09,0x1a}, 8333}, {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x9c,0x63,0x3c,0x3f,0x72,0x44,0x59,0x69,0xcf,0x14}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x9d,0xf9,0x91,0xfc,0x7d,0x25,0xdc,0xd6,0x85,0x67}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xa7,0x08,0x20,0xfe,0x77,0xba,0x3c,0xbd,0x99,0x17}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xa3,0x05,0x71,0x30,0xb8,0x15,0x48,0x9b,0x6b,0xdc}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xaf,0xef,0x01,0xf3,0x4e,0x11,0x18,0x05,0xd2,0x23}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xa8,0x75,0xef,0xb2,0x7b,0x5b,0x6c,0x51,0xb0,0x61}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xa7,0xd8,0xfa,0xdd,0xd3,0x63,0x60,0xd9,0xe1,0xbd}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xa1,0x1d,0xe8,0xbb,0x02,0xdf,0xff,0xd4,0x3a,0x1f}, 8333}, {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xa9,0x2b,0xb6,0xf4,0xb7,0x2c,0x67,0x04,0xf8,0x9d}, 8333}, {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xaa,0x24,0x4a,0xc5,0x19,0xce,0xe1,0x4c,0x00,0xc9}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xab,0xcd,0xe7,0xf4,0x9d,0x5b,0x77,0xb1,0xc2,0x6f}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xac,0x75,0x1a,0x02,0x48,0x68,0x0a,0xec,0x6c,0xab}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xbf,0x9f,0x33,0xd4,0x7d,0xbf,0x80,0x1c,0x15,0xdf}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xb8,0x6c,0x1c,0xc6,0x4f,0xa8,0x2b,0xfa,0x75,0x04}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xb9,0x44,0x4a,0xb6,0x0b,0xd0,0x8e,0xd0,0x59,0x4e}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xc0,0x91,0x56,0xb9,0x9c,0xe0,0xd9,0x7b,0xf1,0xc1}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xc6,0x47,0x55,0xd7,0xa3,0x02,0x26,0x02,0x91,0x4d}, 8333} + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xab,0x72,0x51,0x38,0x35,0x04,0x00,0x77,0x3a,0x8d}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xb6,0x87,0x3a,0x47,0xaa,0xa1,0x80,0xfb,0x6e,0x2f}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xb1,0xbd,0x5b,0x30,0x31,0xce,0x31,0x90,0x3e,0x8d}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xb3,0x2e,0x2f,0x02,0x4a,0xe0,0x3b,0x7c,0x02,0xe7}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xbe,0x76,0x19,0x14,0xe8,0x85,0x04,0xdd,0xfc,0xc3}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xc3,0xf2,0xb1,0xea,0xf8,0x40,0xe9,0xec,0x32,0x02}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xc6,0x29,0x70,0x15,0x68,0xf9,0x60,0x34,0x64,0xf0}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xca,0x09,0x6f,0xc9,0x91,0xd0,0xd7,0xa3,0x9b,0x50}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xcc,0xa1,0xd8,0x38,0xd3,0x74,0x8f,0x95,0x40,0x03}, 8333} }; static SeedSpec6 pnSeed6_test[] = { diff --git a/src/checkpoints.cpp b/src/checkpoints.cpp index 2ef4dd8330..9189c9a8ad 100644 --- a/src/checkpoints.cpp +++ b/src/checkpoints.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -8,7 +8,6 @@ #include <chainparams.h> #include <reverse_iterator.h> #include <validation.h> -#include <uint256.h> #include <stdint.h> diff --git a/src/checkpoints.h b/src/checkpoints.h index df97a674a8..bf935f80a7 100644 --- a/src/checkpoints.h +++ b/src/checkpoints.h @@ -1,4 +1,4 @@ -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/checkqueue.h b/src/checkqueue.h index 08de336079..7500bae60e 100644 --- a/src/checkqueue.h +++ b/src/checkqueue.h @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2015 The Bitcoin Core developers +// Copyright (c) 2012-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -59,9 +59,6 @@ private: */ unsigned int nTodo; - //! Whether we're shutting down. - bool fQuit; - //! The maximum number of elements to be processed in one batch unsigned int nBatchSize; @@ -89,7 +86,7 @@ private: } // logically, the do loop starts here while (queue.empty()) { - if ((fMaster || fQuit) && nTodo == 0) { + if (fMaster && nTodo == 0) { nTotal--; bool fRet = fAllOk; // reset the status for new work later @@ -131,7 +128,7 @@ public: boost::mutex ControlMutex; //! Create a new check queue - explicit CCheckQueue(unsigned int nBatchSizeIn) : nIdle(0), nTotal(0), fAllOk(true), nTodo(0), fQuit(false), nBatchSize(nBatchSizeIn) {} + explicit CCheckQueue(unsigned int nBatchSizeIn) : nIdle(0), nTotal(0), fAllOk(true), nTodo(0), nBatchSize(nBatchSizeIn) {} //! Worker thread void Thread() diff --git a/src/clientversion.cpp b/src/clientversion.cpp index f7ded63e6a..7aa0a8d660 100644 --- a/src/clientversion.cpp +++ b/src/clientversion.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2016 The Bitcoin Core developers +// Copyright (c) 2012-2017 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,7 +6,6 @@ #include <tinyformat.h> -#include <string> /** * Name of client reported in the 'version' message. Report the same name diff --git a/src/clientversion.h b/src/clientversion.h index 3a3d117d53..d7321fad86 100644 --- a/src/clientversion.h +++ b/src/clientversion.h @@ -1,4 +1,4 @@ -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/coins.cpp b/src/coins.cpp index 03138ef878..8dfb35c2eb 100644 --- a/src/coins.cpp +++ b/src/coins.cpp @@ -1,15 +1,12 @@ -// Copyright (c) 2012-2016 The Bitcoin Core developers +// Copyright (c) 2012-2017 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 <coins.h> #include <consensus/consensus.h> -#include <memusage.h> #include <random.h> -#include <assert.h> - bool CCoinsView::GetCoin(const COutPoint &outpoint, Coin &coin) const { return false; } uint256 CCoinsView::GetBestBlock() const { return uint256(); } std::vector<uint256> CCoinsView::GetHeadBlocks() const { return std::vector<uint256>(); } diff --git a/src/coins.h b/src/coins.h index 0280abb56c..c6850947e2 100644 --- a/src/coins.h +++ b/src/coins.h @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/compat.h b/src/compat.h index 2d699159b7..aae84b1181 100644 --- a/src/compat.h +++ b/src/compat.h @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -31,8 +31,9 @@ #include <mswsock.h> #include <windows.h> #include <ws2tcpip.h> +#include <stdint.h> #else -#include <sys/fcntl.h> +#include <fcntl.h> #include <sys/mman.h> #include <sys/select.h> #include <sys/socket.h> @@ -71,6 +72,15 @@ typedef unsigned int SOCKET; #else #define MAX_PATH 1024 #endif +#ifdef _MSC_VER +#if !defined(ssize_t) +#ifdef _WIN64 +typedef int64_t ssize_t; +#else +typedef int32_t ssize_t; +#endif +#endif +#endif #if HAVE_DECL_STRNLEN == 0 size_t strnlen( const char *start, size_t max_len); diff --git a/src/compat/byteswap.h b/src/compat/byteswap.h index 8930534721..c331af2b5e 100644 --- a/src/compat/byteswap.h +++ b/src/compat/byteswap.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2016 The Bitcoin Core developers +// Copyright (c) 2014-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -37,7 +37,7 @@ inline uint16_t bswap_16(uint16_t x) { return (x >> 8) | (x << 8); } -#endif // HAVE_DECL_BSWAP16 +#endif // HAVE_DECL_BSWAP16 == 0 #if HAVE_DECL_BSWAP_32 == 0 inline uint32_t bswap_32(uint32_t x) @@ -45,7 +45,7 @@ inline uint32_t bswap_32(uint32_t x) return (((x & 0xff000000U) >> 24) | ((x & 0x00ff0000U) >> 8) | ((x & 0x0000ff00U) << 8) | ((x & 0x000000ffU) << 24)); } -#endif // HAVE_DECL_BSWAP32 +#endif // HAVE_DECL_BSWAP32 == 0 #if HAVE_DECL_BSWAP_64 == 0 inline uint64_t bswap_64(uint64_t x) @@ -59,7 +59,7 @@ inline uint64_t bswap_64(uint64_t x) | ((x & 0x000000000000ff00ull) << 40) | ((x & 0x00000000000000ffull) << 56)); } -#endif // HAVE_DECL_BSWAP64 +#endif // HAVE_DECL_BSWAP64 == 0 #endif // defined(__APPLE__) diff --git a/src/compat/endian.h b/src/compat/endian.h index 9fabbd0bfb..e5c7e50223 100644 --- a/src/compat/endian.h +++ b/src/compat/endian.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2016 The Bitcoin Core developers +// Copyright (c) 2014-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/compat/glibc_compat.cpp b/src/compat/glibc_compat.cpp index 6633658c16..55da5ef63f 100644 --- a/src/compat/glibc_compat.cpp +++ b/src/compat/glibc_compat.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2009-2014 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/compat/glibc_sanity.cpp b/src/compat/glibc_sanity.cpp index 20d2ad3cb6..1c22dc073c 100644 --- a/src/compat/glibc_sanity.cpp +++ b/src/compat/glibc_sanity.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2009-2014 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/compat/glibcxx_sanity.cpp b/src/compat/glibcxx_sanity.cpp index 569fb1bbe8..257665a061 100644 --- a/src/compat/glibcxx_sanity.cpp +++ b/src/compat/glibcxx_sanity.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2009-2014 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/compat/strnlen.cpp b/src/compat/strnlen.cpp index 313435a222..f7344d39f5 100644 --- a/src/compat/strnlen.cpp +++ b/src/compat/strnlen.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2009-2014 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/compressor.cpp b/src/compressor.cpp index a729e28f07..86de2900e9 100644 --- a/src/compressor.cpp +++ b/src/compressor.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2014 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/compressor.h b/src/compressor.h index 8731eef9f7..ee26f4c533 100644 --- a/src/compressor.h +++ b/src/compressor.h @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/consensus/consensus.h b/src/consensus/consensus.h index 6e3bac2d0e..650635a766 100644 --- a/src/consensus/consensus.h +++ b/src/consensus/consensus.h @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/consensus/merkle.cpp b/src/consensus/merkle.cpp index fef4a5d560..74a9ebb2e3 100644 --- a/src/consensus/merkle.cpp +++ b/src/consensus/merkle.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2016 The Bitcoin Core developers +// Copyright (c) 2015-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/consensus/merkle.h b/src/consensus/merkle.h index c1573cc214..d57bb3412e 100644 --- a/src/consensus/merkle.h +++ b/src/consensus/merkle.h @@ -1,4 +1,4 @@ -// Copyright (c) 2015 The Bitcoin Core developers +// Copyright (c) 2015-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/consensus/params.h b/src/consensus/params.h index c9fbba12a2..4ef808c856 100644 --- a/src/consensus/params.h +++ b/src/consensus/params.h @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/consensus/validation.h b/src/consensus/validation.h index 55f6c363fc..c2a343c155 100644 --- a/src/consensus/validation.h +++ b/src/consensus/validation.h @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/core_io.h b/src/core_io.h index 7ed84d6665..377633ac77 100644 --- a/src/core_io.h +++ b/src/core_io.h @@ -1,4 +1,4 @@ -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -20,7 +20,7 @@ class UniValue; // core_read.cpp CScript ParseScript(const std::string& s); std::string ScriptToAsmStr(const CScript& script, const bool fAttemptSighashDecode = false); -bool DecodeHexTx(CMutableTransaction& tx, const std::string& strHexTx, bool fTryNoWitness = false); +bool DecodeHexTx(CMutableTransaction& tx, const std::string& hex_tx, bool try_no_witness = false, bool try_witness = true); bool DecodeHexBlk(CBlock&, const std::string& strHexBlk); uint256 ParseHashUV(const UniValue& v, const std::string& strName); uint256 ParseHashStr(const std::string&, const std::string& strName); diff --git a/src/core_memusage.h b/src/core_memusage.h index d234f0a9d0..6c03938d0c 100644 --- a/src/core_memusage.h +++ b/src/core_memusage.h @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2016 The Bitcoin Core developers +// Copyright (c) 2015-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/core_read.cpp b/src/core_read.cpp index 2f5b67b5c7..4ccb967087 100644 --- a/src/core_read.cpp +++ b/src/core_read.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -108,39 +108,39 @@ bool CheckTxScriptsSanity(const CMutableTransaction& tx) return true; } -bool DecodeHexTx(CMutableTransaction& tx, const std::string& strHexTx, bool fTryNoWitness) +bool DecodeHexTx(CMutableTransaction& tx, const std::string& hex_tx, bool try_no_witness, bool try_witness) { - if (!IsHex(strHexTx)) { + if (!IsHex(hex_tx)) { return false; } - std::vector<unsigned char> txData(ParseHex(strHexTx)); + std::vector<unsigned char> txData(ParseHex(hex_tx)); - if (fTryNoWitness) { + if (try_no_witness) { CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS); try { ssData >> tx; - if (ssData.eof() && CheckTxScriptsSanity(tx)) { + if (ssData.eof() && (!try_witness || CheckTxScriptsSanity(tx))) { return true; } - } - catch (const std::exception&) { + } catch (const std::exception&) { // Fall through. } } - CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION); - try { - ssData >> tx; - if (!ssData.empty()) { - return false; + if (try_witness) { + CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION); + try { + ssData >> tx; + if (ssData.empty()) { + return true; + } + } catch (const std::exception&) { + // Fall through. } } - catch (const std::exception&) { - return false; - } - - return true; + + return false; } bool DecodeHexBlk(CBlock& block, const std::string& strHexBlk) diff --git a/src/core_write.cpp b/src/core_write.cpp index e97876bef3..ab6918e41d 100644 --- a/src/core_write.cpp +++ b/src/core_write.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/crypto/aes.cpp b/src/crypto/aes.cpp index baba8bcad0..bf7a252349 100644 --- a/src/crypto/aes.cpp +++ b/src/crypto/aes.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2016 The Bitcoin Core developers +// Copyright (c) 2016-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/crypto/aes.h b/src/crypto/aes.h index 7dda94d291..2dec8d9558 100644 --- a/src/crypto/aes.h +++ b/src/crypto/aes.h @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2016 The Bitcoin Core developers +// Copyright (c) 2015-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. // diff --git a/src/crypto/common.h b/src/crypto/common.h index 5a193a4e64..825b430978 100644 --- a/src/crypto/common.h +++ b/src/crypto/common.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014 The Bitcoin Core developers +// Copyright (c) 2014-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/crypto/hmac_sha256.cpp b/src/crypto/hmac_sha256.cpp index 9366e216c2..d4afe1439f 100644 --- a/src/crypto/hmac_sha256.cpp +++ b/src/crypto/hmac_sha256.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014 The Bitcoin Core developers +// Copyright (c) 2014-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/crypto/hmac_sha256.h b/src/crypto/hmac_sha256.h index 40d40f9fb2..4fb30b7ac0 100644 --- a/src/crypto/hmac_sha256.h +++ b/src/crypto/hmac_sha256.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014 The Bitcoin Core developers +// Copyright (c) 2014-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/crypto/hmac_sha512.cpp b/src/crypto/hmac_sha512.cpp index f984201f6a..d9c4d04100 100644 --- a/src/crypto/hmac_sha512.cpp +++ b/src/crypto/hmac_sha512.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014 The Bitcoin Core developers +// Copyright (c) 2014-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/crypto/hmac_sha512.h b/src/crypto/hmac_sha512.h index 6d3fd59f27..ab84ee7652 100644 --- a/src/crypto/hmac_sha512.h +++ b/src/crypto/hmac_sha512.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014 The Bitcoin Core developers +// Copyright (c) 2014-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/crypto/ripemd160.cpp b/src/crypto/ripemd160.cpp index 4afa9abd1e..51468ec8d0 100644 --- a/src/crypto/ripemd160.cpp +++ b/src/crypto/ripemd160.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014 The Bitcoin Core developers +// Copyright (c) 2014-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/crypto/sha1.cpp b/src/crypto/sha1.cpp index 8ccc5e112a..dc96ac507a 100644 --- a/src/crypto/sha1.cpp +++ b/src/crypto/sha1.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014 The Bitcoin Core developers +// Copyright (c) 2014-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/crypto/sha256.cpp b/src/crypto/sha256.cpp index 9a21aec20e..f3245b8dea 100644 --- a/src/crypto/sha256.cpp +++ b/src/crypto/sha256.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014 The Bitcoin Core developers +// Copyright (c) 2014-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/crypto/sha256.h b/src/crypto/sha256.h index aa4f3972cc..dd30fe396f 100644 --- a/src/crypto/sha256.h +++ b/src/crypto/sha256.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2016 The Bitcoin Core developers +// Copyright (c) 2014-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/crypto/sha512.cpp b/src/crypto/sha512.cpp index aa46e7ba86..dff4d8da1a 100644 --- a/src/crypto/sha512.cpp +++ b/src/crypto/sha512.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014 The Bitcoin Core developers +// Copyright (c) 2014-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/dbwrapper.cpp b/src/dbwrapper.cpp index 92c4fe363c..4e1e403f69 100644 --- a/src/dbwrapper.cpp +++ b/src/dbwrapper.cpp @@ -1,11 +1,9 @@ -// Copyright (c) 2012-2016 The Bitcoin Core developers +// Copyright (c) 2012-2017 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 <dbwrapper.h> -#include <fs.h> -#include <util.h> #include <random.h> #include <leveldb/cache.h> @@ -64,7 +62,7 @@ public: assert(p <= limit); base[std::min(bufsize - 1, (int)(p - base))] = '\0'; - LogPrintStr(base); + LogPrintf("leveldb: %s", base); if (base != buffer) { delete[] base; } diff --git a/src/dbwrapper.h b/src/dbwrapper.h index 9f4d4814eb..a29938ce33 100644 --- a/src/dbwrapper.h +++ b/src/dbwrapper.h @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2016 The Bitcoin Core developers +// Copyright (c) 2012-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/hash.cpp b/src/hash.cpp index 1363d32cf4..d31e094540 100644 --- a/src/hash.cpp +++ b/src/hash.cpp @@ -1,11 +1,10 @@ -// Copyright (c) 2013-2016 The Bitcoin Core developers +// Copyright (c) 2013-2017 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 <hash.h> #include <crypto/common.h> #include <crypto/hmac_sha512.h> -#include <pubkey.h> inline uint32_t ROTL32(uint32_t x, int8_t r) diff --git a/src/hash.h b/src/hash.h index 55724fb636..35995a2d15 100644 --- a/src/hash.h +++ b/src/hash.h @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/httprpc.cpp b/src/httprpc.cpp index 6b6849e59b..5e9e419744 100644 --- a/src/httprpc.cpp +++ b/src/httprpc.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2016 The Bitcoin Core developers +// Copyright (c) 2015-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -85,11 +85,11 @@ static void JSONErrorReply(HTTPRequest* req, const UniValue& objError, const Uni //entries from config file. static bool multiUserAuthorized(std::string strUserPass) { - if (strUserPass.find(":") == std::string::npos) { + if (strUserPass.find(':') == std::string::npos) { return false; } - std::string strUser = strUserPass.substr(0, strUserPass.find(":")); - std::string strPass = strUserPass.substr(strUserPass.find(":") + 1); + std::string strUser = strUserPass.substr(0, strUserPass.find(':')); + std::string strPass = strUserPass.substr(strUserPass.find(':') + 1); for (const std::string& strRPCAuth : gArgs.GetArgs("-rpcauth")) { //Search for multi-user login/pass "rpcauth" from config @@ -132,8 +132,8 @@ static bool RPCAuthorized(const std::string& strAuth, std::string& strAuthUserna boost::trim(strUserPass64); std::string strUserPass = DecodeBase64(strUserPass64); - if (strUserPass.find(":") != std::string::npos) - strAuthUsernameOut = strUserPass.substr(0, strUserPass.find(":")); + if (strUserPass.find(':') != std::string::npos) + strAuthUsernameOut = strUserPass.substr(0, strUserPass.find(':')); //Check if authorized under single-user field if (TimingResistantEqual(strUserPass, strRPCUserColonPass)) { diff --git a/src/httprpc.h b/src/httprpc.h index a89a8f0fbf..ccae29b45d 100644 --- a/src/httprpc.h +++ b/src/httprpc.h @@ -1,4 +1,4 @@ -// Copyright (c) 2015 The Bitcoin Core developers +// Copyright (c) 2015-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/httpserver.cpp b/src/httpserver.cpp index 7d590f8e1f..a022d220e0 100644 --- a/src/httpserver.cpp +++ b/src/httpserver.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2016 The Bitcoin Core developers +// Copyright (c) 2015-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/httpserver.h b/src/httpserver.h index 91ce5b4e00..f17be65962 100644 --- a/src/httpserver.h +++ b/src/httpserver.h @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2016 The Bitcoin Core developers +// Copyright (c) 2015-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/init.cpp b/src/init.cpp index 439eaacfcc..94702301a6 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -193,8 +193,8 @@ void Shutdown() // Because these depend on each-other, we make sure that neither can be // using the other before destroying them. - UnregisterValidationInterface(peerLogic.get()); - if(g_connman) g_connman->Stop(); + if (peerLogic) UnregisterValidationInterface(peerLogic.get()); + if (g_connman) g_connman->Stop(); peerLogic.reset(); g_connman.reset(); @@ -342,6 +342,7 @@ std::string HelpMessage(HelpMessageMode mode) if (showDebug) strUsage += HelpMessageOpt("-feefilter", strprintf("Tell other nodes to filter invs to us by our mempool min fee (default: %u)", DEFAULT_FEEFILTER)); strUsage += HelpMessageOpt("-loadblock=<file>", _("Imports blocks from external blk000??.dat file on startup")); + strUsage += HelpMessageOpt("-debuglogfile=<file>", strprintf(_("Specify location of debug log file: this can be an absolute path or a path relative to the data directory (default: %s)"), DEFAULT_DEBUGLOGFILE)); strUsage += HelpMessageOpt("-maxorphantx=<n>", strprintf(_("Keep at most <n> unconnectable transactions in memory (default: %u)"), DEFAULT_MAX_ORPHAN_TRANSACTIONS)); strUsage += HelpMessageOpt("-maxmempool=<n>", strprintf(_("Keep the transaction memory pool below <n> megabytes (default: %u)"), DEFAULT_MAX_MEMPOOL_SIZE)); strUsage += HelpMessageOpt("-mempoolexpiry=<n>", strprintf(_("Do not keep transactions in the mempool longer than <n> hours (default: %u)"), DEFAULT_MEMPOOL_EXPIRY)); @@ -807,7 +808,13 @@ void InitLogging() fLogIPs = gArgs.GetBoolArg("-logips", DEFAULT_LOGIPS); LogPrintf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"); - LogPrintf("Bitcoin version %s\n", FormatFullVersion()); + std::string version_string = FormatFullVersion(); +#ifdef DEBUG + version_string += " (debug build)"; +#else + version_string += " (release build)"; +#endif + LogPrintf(PACKAGE_NAME " version %s\n", version_string); } namespace { // Variables internal to initialization process only @@ -815,7 +822,7 @@ namespace { // Variables internal to initialization process only int nMaxConnections; int nUserMaxConnections; int nFD; -ServiceFlags nLocalServices = NODE_NETWORK; +ServiceFlags nLocalServices = ServiceFlags(NODE_NETWORK | NODE_NETWORK_LIMITED); } // namespace @@ -919,7 +926,8 @@ bool AppInitParameterInteraction() // Special-case: if -debug=0/-nodebug is set, turn off debugging messages const std::vector<std::string> categories = gArgs.GetArgs("-debug"); - if (find(categories.begin(), categories.end(), std::string("0")) == categories.end()) { + if (std::none_of(categories.begin(), categories.end(), + [](std::string cat){return cat == "0" || cat == "none";})) { for (const auto& cat : categories) { uint32_t flag = 0; if (!GetLogCategory(&flag, &cat)) { @@ -1030,11 +1038,6 @@ bool AppInitParameterInteraction() fPruneMode = true; } - RegisterAllCoreRPCCommands(tableRPC); -#ifdef ENABLE_WALLET - RegisterWalletRPC(tableRPC); -#endif - nConnectTimeout = gArgs.GetArg("-timeout", DEFAULT_CONNECT_TIMEOUT); if (nConnectTimeout <= 0) nConnectTimeout = DEFAULT_CONNECT_TIMEOUT; @@ -1146,23 +1149,10 @@ bool AppInitParameterInteraction() static bool LockDataDirectory(bool probeOnly) { - std::string strDataDir = GetDataDir().string(); - // Make sure only a single Bitcoin process is using the data directory. - fs::path pathLockFile = GetDataDir() / ".lock"; - FILE* file = fsbridge::fopen(pathLockFile, "a"); // empty lock file; created if it doesn't exist. - if (file) fclose(file); - - try { - static boost::interprocess::file_lock lock(pathLockFile.string().c_str()); - if (!lock.try_lock()) { - return InitError(strprintf(_("Cannot obtain a lock on data directory %s. %s is probably already running."), strDataDir, _(PACKAGE_NAME))); - } - if (probeOnly) { - lock.unlock(); - } - } catch(const boost::interprocess::interprocess_exception& e) { - return InitError(strprintf(_("Cannot obtain a lock on data directory %s. %s is probably already running.") + " %s.", strDataDir, _(PACKAGE_NAME), e.what())); + fs::path datadir = GetDataDir(); + if (!LockDirectory(datadir, ".lock", probeOnly)) { + return InitError(strprintf(_("Cannot obtain a lock on data directory %s. %s is probably already running."), datadir.string(), _(PACKAGE_NAME))); } return true; } @@ -1213,8 +1203,11 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) ShrinkDebugFile(); } - if (fPrintToDebugLog) - OpenDebugLog(); + if (fPrintToDebugLog) { + if (!OpenDebugLog()) { + return InitError(strprintf("Could not open debug log file %s", GetDebugLogPath().string())); + } + } if (!fLogTimestamps) LogPrintf("Startup time: %s\n", DateTimeStrFormat("%Y-%m-%d %H:%M:%S", GetTime())); @@ -1223,6 +1216,15 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) LogPrintf("Using config file %s\n", GetConfigFile(gArgs.GetArg("-conf", BITCOIN_CONF_FILENAME)).string()); LogPrintf("Using at most %i automatic connections (%i file descriptors available)\n", nMaxConnections, nFD); + // Warn about relative -datadir path. + if (gArgs.IsArgSet("-datadir") && !fs::path(gArgs.GetArg("-datadir", "")).is_absolute()) { + LogPrintf("Warning: relative datadir option '%s' specified, which will be interpreted relative to the " + "current working directory '%s'. This is fragile, because if bitcoin is started in the future " + "from a different location, it will be unable to locate the current data files. There could " + "also be data loss if bitcoin is started while in a temporary directory.\n", + gArgs.GetArg("-datadir", ""), fs::current_path().string()); + } + InitSignatureCache(); InitScriptExecutionCache(); @@ -1239,6 +1241,14 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) GetMainSignals().RegisterBackgroundSignalScheduler(scheduler); GetMainSignals().RegisterWithMempoolSignals(mempool); + /* Register RPC commands regardless of -server setting so they will be + * available in the GUI RPC console even if external calls are disabled. + */ + RegisterAllCoreRPCCommands(tableRPC); +#ifdef ENABLE_WALLET + RegisterWalletRPC(tableRPC); +#endif + /* Start the RPC server already. It will be started in "warmup" mode * and not really process calls already (but it will signify connections * that the server is there and will be ready later). Warmup mode will @@ -1718,5 +1728,5 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) StartWallets(scheduler); #endif - return !fRequestShutdown; + return true; } diff --git a/src/init.h b/src/init.h index a0a824738c..843024f02b 100644 --- a/src/init.h +++ b/src/init.h @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/key.cpp b/src/key.cpp index 73983caf41..e998e3db6e 100644 --- a/src/key.cpp +++ b/src/key.cpp @@ -1,4 +1,5 @@ -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers +// Copyright (c) 2017 The Zcash developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -7,7 +8,6 @@ #include <arith_uint256.h> #include <crypto/common.h> #include <crypto/hmac_sha512.h> -#include <pubkey.h> #include <random.h> #include <secp256k1.h> @@ -16,43 +16,62 @@ static secp256k1_context* secp256k1_context_sign = nullptr; /** These functions are taken from the libsecp256k1 distribution and are very ugly. */ + +/** + * This parses a format loosely based on a DER encoding of the ECPrivateKey type from + * section C.4 of SEC 1 <http://www.secg.org/sec1-v2.pdf>, with the following caveats: + * + * * The octet-length of the SEQUENCE must be encoded as 1 or 2 octets. It is not + * required to be encoded as one octet if it is less than 256, as DER would require. + * * The octet-length of the SEQUENCE must not be greater than the remaining + * length of the key encoding, but need not match it (i.e. the encoding may contain + * junk after the encoded SEQUENCE). + * * The privateKey OCTET STRING is zero-filled on the left to 32 octets. + * * Anything after the encoding of the privateKey OCTET STRING is ignored, whether + * or not it is validly encoded DER. + * + * out32 must point to an output buffer of length at least 32 bytes. + */ static int ec_privkey_import_der(const secp256k1_context* ctx, unsigned char *out32, const unsigned char *privkey, size_t privkeylen) { const unsigned char *end = privkey + privkeylen; - int lenb = 0; - int len = 0; memset(out32, 0, 32); /* sequence header */ - if (end < privkey+1 || *privkey != 0x30) { + if (end - privkey < 1 || *privkey != 0x30u) { return 0; } privkey++; /* sequence length constructor */ - if (end < privkey+1 || !(*privkey & 0x80)) { + if (end - privkey < 1 || !(*privkey & 0x80u)) { return 0; } - lenb = *privkey & ~0x80; privkey++; + size_t lenb = *privkey & ~0x80u; privkey++; if (lenb < 1 || lenb > 2) { return 0; } - if (end < privkey+lenb) { + if (end - privkey < lenb) { return 0; } /* sequence length */ - len = privkey[lenb-1] | (lenb > 1 ? privkey[lenb-2] << 8 : 0); + size_t len = privkey[lenb-1] | (lenb > 1 ? privkey[lenb-2] << 8 : 0u); privkey += lenb; - if (end < privkey+len) { + if (end - privkey < len) { return 0; } /* sequence element 0: version number (=1) */ - if (end < privkey+3 || privkey[0] != 0x02 || privkey[1] != 0x01 || privkey[2] != 0x01) { + if (end - privkey < 3 || privkey[0] != 0x02u || privkey[1] != 0x01u || privkey[2] != 0x01u) { return 0; } privkey += 3; /* sequence element 1: octet string, up to 32 bytes */ - if (end < privkey+2 || privkey[0] != 0x04 || privkey[1] > 0x20 || end < privkey+2+privkey[1]) { + if (end - privkey < 2 || privkey[0] != 0x04u) { + return 0; + } + size_t oslen = privkey[1]; + privkey += 2; + if (oslen > 32 || end - privkey < oslen) { return 0; } - memcpy(out32 + 32 - privkey[1], privkey + 2, privkey[1]); + memcpy(out32 + (32 - oslen), privkey, oslen); if (!secp256k1_ec_seckey_verify(ctx, out32)) { memset(out32, 0, 32); return 0; @@ -60,7 +79,18 @@ static int ec_privkey_import_der(const secp256k1_context* ctx, unsigned char *ou return 1; } +/** + * This serializes to a DER encoding of the ECPrivateKey type from section C.4 of SEC 1 + * <http://www.secg.org/sec1-v2.pdf>. The optional parameters and publicKey fields are + * included. + * + * privkey must point to an output buffer of length at least CKey::PRIVATE_KEY_SIZE bytes. + * privkeylen must initially be set to the size of the privkey buffer. Upon return it + * will be set to the number of bytes used in the buffer. + * key32 must point to a 32-byte raw private key. + */ static int ec_privkey_export_der(const secp256k1_context *ctx, unsigned char *privkey, size_t *privkeylen, const unsigned char *key32, int compressed) { + assert(*privkeylen >= CKey::PRIVATE_KEY_SIZE); secp256k1_pubkey pubkey; size_t pubkeylen = 0; if (!secp256k1_ec_pubkey_create(ctx, &pubkey, key32)) { @@ -86,10 +116,11 @@ static int ec_privkey_export_der(const secp256k1_context *ctx, unsigned char *pr memcpy(ptr, begin, sizeof(begin)); ptr += sizeof(begin); memcpy(ptr, key32, 32); ptr += 32; memcpy(ptr, middle, sizeof(middle)); ptr += sizeof(middle); - pubkeylen = 33; + pubkeylen = CPubKey::COMPRESSED_PUBLIC_KEY_SIZE; secp256k1_ec_pubkey_serialize(ctx, ptr, &pubkeylen, &pubkey, SECP256K1_EC_COMPRESSED); ptr += pubkeylen; *privkeylen = ptr - privkey; + assert(*privkeylen == CKey::COMPRESSED_PRIVATE_KEY_SIZE); } else { static const unsigned char begin[] = { 0x30,0x82,0x01,0x13,0x02,0x01,0x01,0x04,0x20 @@ -111,10 +142,11 @@ static int ec_privkey_export_der(const secp256k1_context *ctx, unsigned char *pr memcpy(ptr, begin, sizeof(begin)); ptr += sizeof(begin); memcpy(ptr, key32, 32); ptr += 32; memcpy(ptr, middle, sizeof(middle)); ptr += sizeof(middle); - pubkeylen = 65; + pubkeylen = CPubKey::PUBLIC_KEY_SIZE; secp256k1_ec_pubkey_serialize(ctx, ptr, &pubkeylen, &pubkey, SECP256K1_EC_UNCOMPRESSED); ptr += pubkeylen; *privkeylen = ptr - privkey; + assert(*privkeylen == CKey::PRIVATE_KEY_SIZE); } return 1; } @@ -136,8 +168,8 @@ CPrivKey CKey::GetPrivKey() const { CPrivKey privkey; int ret; size_t privkeylen; - privkey.resize(279); - privkeylen = 279; + privkey.resize(PRIVATE_KEY_SIZE); + privkeylen = PRIVATE_KEY_SIZE; ret = ec_privkey_export_der(secp256k1_context_sign, (unsigned char*) privkey.data(), &privkeylen, begin(), fCompressed ? SECP256K1_EC_COMPRESSED : SECP256K1_EC_UNCOMPRESSED); assert(ret); privkey.resize(privkeylen); @@ -147,7 +179,7 @@ CPrivKey CKey::GetPrivKey() const { CPubKey CKey::GetPubKey() const { assert(fValid); secp256k1_pubkey pubkey; - size_t clen = 65; + size_t clen = CPubKey::PUBLIC_KEY_SIZE; CPubKey result; int ret = secp256k1_ec_pubkey_create(secp256k1_context_sign, &pubkey, begin()); assert(ret); @@ -160,8 +192,8 @@ CPubKey CKey::GetPubKey() const { bool CKey::Sign(const uint256 &hash, std::vector<unsigned char>& vchSig, uint32_t test_case) const { if (!fValid) return false; - vchSig.resize(72); - size_t nSigLen = 72; + vchSig.resize(CPubKey::SIGNATURE_SIZE); + size_t nSigLen = CPubKey::SIGNATURE_SIZE; unsigned char extra_entropy[32] = {0}; WriteLE32(extra_entropy, test_case); secp256k1_ecdsa_signature sig; @@ -189,7 +221,7 @@ bool CKey::VerifyPubKey(const CPubKey& pubkey) const { bool CKey::SignCompact(const uint256 &hash, std::vector<unsigned char>& vchSig) const { if (!fValid) return false; - vchSig.resize(65); + vchSig.resize(CPubKey::COMPACT_SIGNATURE_SIZE); int rec = -1; secp256k1_ecdsa_recoverable_signature sig; int ret = secp256k1_ecdsa_sign_recoverable(secp256k1_context_sign, &sig, hash.begin(), begin(), secp256k1_nonce_function_rfc6979, nullptr); @@ -201,7 +233,7 @@ bool CKey::SignCompact(const uint256 &hash, std::vector<unsigned char>& vchSig) return true; } -bool CKey::Load(CPrivKey &privkey, CPubKey &vchPubKey, bool fSkipCheck=false) { +bool CKey::Load(const CPrivKey &privkey, const CPubKey &vchPubKey, bool fSkipCheck=false) { if (!ec_privkey_import_der(secp256k1_context_sign, (unsigned char*)begin(), privkey.data(), privkey.size())) return false; fCompressed = vchPubKey.IsCompressed(); @@ -219,10 +251,10 @@ bool CKey::Derive(CKey& keyChild, ChainCode &ccChild, unsigned int nChild, const std::vector<unsigned char, secure_allocator<unsigned char>> vout(64); if ((nChild >> 31) == 0) { CPubKey pubkey = GetPubKey(); - assert(pubkey.begin() + 33 == pubkey.end()); + assert(pubkey.size() == CPubKey::COMPRESSED_PUBLIC_KEY_SIZE); BIP32Hash(cc, nChild, *pubkey.begin(), pubkey.begin()+1, vout.data()); } else { - assert(begin() + 32 == end()); + assert(size() == 32); BIP32Hash(cc, nChild, 0, begin(), vout.data()); } memcpy(ccChild.begin(), vout.data()+32, 32); @@ -1,5 +1,6 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers +// Copyright (c) 2017 The Zcash developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -16,24 +17,29 @@ /** - * secp256k1: - * const unsigned int PRIVATE_KEY_SIZE = 279; - * const unsigned int PUBLIC_KEY_SIZE = 65; - * const unsigned int SIGNATURE_SIZE = 72; - * - * see www.keylength.com - * script supports up to 75 for single byte push - */ - -/** * secure_allocator is defined in allocators.h - * CPrivKey is a serialized private key, with all parameters included (279 bytes) + * CPrivKey is a serialized private key, with all parameters included + * (PRIVATE_KEY_SIZE bytes) */ typedef std::vector<unsigned char, secure_allocator<unsigned char> > CPrivKey; /** An encapsulated private key. */ class CKey { +public: + /** + * secp256k1: + */ + static const unsigned int PRIVATE_KEY_SIZE = 279; + static const unsigned int COMPRESSED_PRIVATE_KEY_SIZE = 214; + /** + * see www.keylength.com + * script supports up to 75 for single byte push + */ + static_assert( + PRIVATE_KEY_SIZE >= COMPRESSED_PRIVATE_KEY_SIZE, + "COMPRESSED_PRIVATE_KEY_SIZE is larger than PRIVATE_KEY_SIZE"); + private: //! Whether this private key is valid. We check for correctness when modifying the key //! data, so fValid should always correspond to the actual state. @@ -129,7 +135,7 @@ public: bool VerifyPubKey(const CPubKey& vchPubKey) const; //! Load private key and check that public key matches. - bool Load(CPrivKey& privkey, CPubKey& vchPubKey, bool fSkipCheck); + bool Load(const CPrivKey& privkey, const CPubKey& vchPubKey, bool fSkipCheck); }; struct CExtKey { diff --git a/src/keystore.cpp b/src/keystore.cpp index 5718a14ca2..fab1b81c9a 100644 --- a/src/keystore.cpp +++ b/src/keystore.cpp @@ -1,18 +1,41 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 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 <keystore.h> -#include <key.h> -#include <pubkey.h> #include <util.h> bool CKeyStore::AddKey(const CKey &key) { return AddKeyPubKey(key, key.GetPubKey()); } +void CBasicKeyStore::ImplicitlyLearnRelatedKeyScripts(const CPubKey& pubkey) +{ + AssertLockHeld(cs_KeyStore); + CKeyID key_id = pubkey.GetID(); + // We must actually know about this key already. + assert(HaveKey(key_id) || mapWatchKeys.count(key_id)); + // This adds the redeemscripts necessary to detect P2WPKH and P2SH-P2WPKH + // outputs. Technically P2WPKH outputs don't have a redeemscript to be + // spent. However, our current IsMine logic requires the corresponding + // P2SH-P2WPKH redeemscript to be present in the wallet in order to accept + // payment even to P2WPKH outputs. + // Also note that having superfluous scripts in the keystore never hurts. + // They're only used to guide recursion in signing and IsMine logic - if + // a script is present but we can't do anything with it, it has no effect. + // "Implicitly" refers to fact that scripts are derived automatically from + // existing keys, and are present in memory, even without being explicitly + // loaded (e.g. from a file). + if (pubkey.IsCompressed()) { + CScript script = GetScriptForDestination(WitnessV0KeyHash(key_id)); + // This does not use AddCScript, as it may be overridden. + CScriptID id(script); + mapScripts[id] = std::move(script); + } +} + bool CBasicKeyStore::GetPubKey(const CKeyID &address, CPubKey &vchPubKeyOut) const { CKey key; @@ -33,6 +56,7 @@ bool CBasicKeyStore::AddKeyPubKey(const CKey& key, const CPubKey &pubkey) { LOCK(cs_KeyStore); mapKeys[pubkey.GetID()] = key; + ImplicitlyLearnRelatedKeyScripts(pubkey); return true; } @@ -79,6 +103,16 @@ bool CBasicKeyStore::HaveCScript(const CScriptID& hash) const return mapScripts.count(hash) > 0; } +std::set<CScriptID> CBasicKeyStore::GetCScripts() const +{ + LOCK(cs_KeyStore); + std::set<CScriptID> set_script; + for (const auto& mi : mapScripts) { + set_script.insert(mi.first); + } + return set_script; +} + bool CBasicKeyStore::GetCScript(const CScriptID &hash, CScript& redeemScriptOut) const { LOCK(cs_KeyStore); @@ -112,8 +146,10 @@ bool CBasicKeyStore::AddWatchOnly(const CScript &dest) LOCK(cs_KeyStore); setWatchOnly.insert(dest); CPubKey pubKey; - if (ExtractPubKey(dest, pubKey)) + if (ExtractPubKey(dest, pubKey)) { mapWatchKeys[pubKey.GetID()] = pubKey; + ImplicitlyLearnRelatedKeyScripts(pubKey); + } return true; } @@ -122,8 +158,11 @@ bool CBasicKeyStore::RemoveWatchOnly(const CScript &dest) LOCK(cs_KeyStore); setWatchOnly.erase(dest); CPubKey pubKey; - if (ExtractPubKey(dest, pubKey)) + if (ExtractPubKey(dest, pubKey)) { mapWatchKeys.erase(pubKey.GetID()); + } + // Related CScripts are not removed; having superfluous scripts around is + // harmless (see comment in ImplicitlyLearnRelatedKeyScripts). return true; } @@ -138,3 +177,25 @@ bool CBasicKeyStore::HaveWatchOnly() const LOCK(cs_KeyStore); return (!setWatchOnly.empty()); } + +CKeyID GetKeyForDestination(const CKeyStore& store, const CTxDestination& dest) +{ + // Only supports destinations which map to single public keys, i.e. P2PKH, + // P2WPKH, and P2SH-P2WPKH. + if (auto id = boost::get<CKeyID>(&dest)) { + return *id; + } + if (auto witness_id = boost::get<WitnessV0KeyHash>(&dest)) { + return CKeyID(*witness_id); + } + if (auto script_id = boost::get<CScriptID>(&dest)) { + CScript script; + CTxDestination inner_dest; + if (store.GetCScript(*script_id, script) && ExtractDestination(script, inner_dest)) { + if (auto inner_witness_id = boost::get<WitnessV0KeyHash>(&inner_dest)) { + return CKeyID(*inner_witness_id); + } + } + } + return CKeyID(); +} diff --git a/src/keystore.h b/src/keystore.h index 4e6d8e8a27..ffd3238fd6 100644 --- a/src/keystore.h +++ b/src/keystore.h @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2015 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -36,6 +36,7 @@ public: //! Support for BIP 0013 : see https://github.com/bitcoin/bips/blob/master/bip-0013.mediawiki virtual bool AddCScript(const CScript& redeemScript) =0; virtual bool HaveCScript(const CScriptID &hash) const =0; + virtual std::set<CScriptID> GetCScripts() const =0; virtual bool GetCScript(const CScriptID &hash, CScript& redeemScriptOut) const =0; //! Support for Watch-only addresses @@ -59,6 +60,8 @@ protected: ScriptMap mapScripts; WatchOnlySet setWatchOnly; + void ImplicitlyLearnRelatedKeyScripts(const CPubKey& pubkey); + public: bool AddKeyPubKey(const CKey& key, const CPubKey &pubkey) override; bool GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const override; @@ -67,6 +70,7 @@ public: bool GetKey(const CKeyID &address, CKey &keyOut) const override; bool AddCScript(const CScript& redeemScript) override; bool HaveCScript(const CScriptID &hash) const override; + std::set<CScriptID> GetCScripts() const override; bool GetCScript(const CScriptID &hash, CScript& redeemScriptOut) const override; bool AddWatchOnly(const CScript &dest) override; @@ -78,4 +82,7 @@ public: typedef std::vector<unsigned char, secure_allocator<unsigned char> > CKeyingMaterial; typedef std::map<CKeyID, std::pair<CPubKey, std::vector<unsigned char> > > CryptedKeyMap; +/** Return the CKeyID of the key involved in a script (if there is a unique one). */ +CKeyID GetKeyForDestination(const CKeyStore& store, const CTxDestination& dest); + #endif // BITCOIN_KEYSTORE_H diff --git a/src/limitedmap.h b/src/limitedmap.h index 7afc8b458d..d5f00f1fee 100644 --- a/src/limitedmap.h +++ b/src/limitedmap.h @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2016 The Bitcoin Core developers +// Copyright (c) 2012-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/memusage.h b/src/memusage.h index d931171d35..fea7ecdf9f 100644 --- a/src/memusage.h +++ b/src/memusage.h @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2016 The Bitcoin Core developers +// Copyright (c) 2015-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/merkleblock.cpp b/src/merkleblock.cpp index f4db9dd57e..de3519c1da 100644 --- a/src/merkleblock.cpp +++ b/src/merkleblock.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/merkleblock.h b/src/merkleblock.h index b64c34370e..0976e21c3a 100644 --- a/src/merkleblock.h +++ b/src/merkleblock.h @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/miner.cpp b/src/miner.cpp index 397d99fc9a..dda52790c6 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -22,7 +22,6 @@ #include <primitives/transaction.h> #include <script/standard.h> #include <timedata.h> -#include <txmempool.h> #include <util.h> #include <utilmoneystr.h> #include <validationinterface.h> @@ -353,7 +352,7 @@ void BlockAssembler::addPackageTxs(int &nPackagesSelected, int &nDescendantsUpda // Try to compare the mapTx entry to the mapModifiedTx entry iter = mempool.mapTx.project<0>(mi); if (modit != mapModifiedTx.get<ancestor_score>().end() && - CompareModifiedEntry()(*modit, CTxMemPoolModifiedEntry(iter))) { + CompareTxMemPoolEntryByAncestorFee()(*modit, CTxMemPoolModifiedEntry(iter))) { // The best entry in mapModifiedTx has higher score // than the one from mapTx. // Switch which transaction (package) to consider diff --git a/src/miner.h b/src/miner.h index 36276dc362..9c086332d4 100644 --- a/src/miner.h +++ b/src/miner.h @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -41,6 +41,12 @@ struct CTxMemPoolModifiedEntry { nSigOpCostWithAncestors = entry->GetSigOpCostWithAncestors(); } + int64_t GetModifiedFee() const { return iter->GetModifiedFee(); } + uint64_t GetSizeWithAncestors() const { return nSizeWithAncestors; } + CAmount GetModFeesWithAncestors() const { return nModFeesWithAncestors; } + size_t GetTxSize() const { return iter->GetTxSize(); } + const CTransaction& GetTx() const { return iter->GetTx(); } + CTxMemPool::txiter iter; uint64_t nSizeWithAncestors; CAmount nModFeesWithAncestors; @@ -67,26 +73,11 @@ struct modifiedentry_iter { } }; -// This matches the calculation in CompareTxMemPoolEntryByAncestorFee, -// except operating on CTxMemPoolModifiedEntry. -// TODO: refactor to avoid duplication of this logic. -struct CompareModifiedEntry { - bool operator()(const CTxMemPoolModifiedEntry &a, const CTxMemPoolModifiedEntry &b) - { - double f1 = (double)a.nModFeesWithAncestors * b.nSizeWithAncestors; - double f2 = (double)b.nModFeesWithAncestors * a.nSizeWithAncestors; - if (f1 == f2) { - return CTxMemPool::CompareIteratorByHash()(a.iter, b.iter); - } - return f1 > f2; - } -}; - // A comparator that sorts transactions based on number of ancestors. // This is sufficient to sort an ancestor package in an order that is valid // to appear in a block. struct CompareTxIterByAncestorCount { - bool operator()(const CTxMemPool::txiter &a, const CTxMemPool::txiter &b) + bool operator()(const CTxMemPool::txiter &a, const CTxMemPool::txiter &b) const { if (a->GetCountWithAncestors() != b->GetCountWithAncestors()) return a->GetCountWithAncestors() < b->GetCountWithAncestors(); @@ -106,7 +97,7 @@ typedef boost::multi_index_container< // Reuse same tag from CTxMemPool's similar index boost::multi_index::tag<ancestor_score>, boost::multi_index::identity<CTxMemPoolModifiedEntry>, - CompareModifiedEntry + CompareTxMemPoolEntryByAncestorFee > > > indexed_modified_transaction_set; diff --git a/src/net.cpp b/src/net.cpp index a8e5143d5e..8111390749 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -9,13 +9,11 @@ #include <net.h> -#include <addrman.h> #include <chainparams.h> #include <clientversion.h> #include <consensus/consensus.h> #include <crypto/common.h> #include <crypto/sha256.h> -#include <hash.h> #include <primitives/transaction.h> #include <netbase.h> #include <scheduler.h> @@ -110,13 +108,13 @@ bool GetLocal(CService& addr, const CNetAddr *paddrPeer) int nBestReachability = -1; { LOCK(cs_mapLocalHost); - for (std::map<CNetAddr, LocalServiceInfo>::iterator it = mapLocalHost.begin(); it != mapLocalHost.end(); it++) + for (const auto& entry : mapLocalHost) { - int nScore = (*it).second.nScore; - int nReachability = (*it).first.GetReachabilityFrom(paddrPeer); + int nScore = entry.second.nScore; + int nReachability = entry.first.GetReachabilityFrom(paddrPeer); if (nReachability > nBestReachability || (nReachability == nBestReachability && nScore > nBestScore)) { - addr = CService((*it).first, (*it).second.nPort); + addr = CService(entry.first, entry.second.nPort); nBestReachability = nReachability; nBestScore = nScore; } @@ -138,7 +136,7 @@ static std::vector<CAddress> convertSeed6(const std::vector<SeedSpec6> &vSeedsIn for (const auto& seed_in : vSeedsIn) { struct in6_addr ip; memcpy(&ip, seed_in.addr, sizeof(ip)); - CAddress addr(CService(ip, seed_in.port), NODE_NETWORK); + CAddress addr(CService(ip, seed_in.port), GetDesirableServiceFlags(NODE_NONE)); addr.nTime = GetTime() - GetRand(nOneWeek) - nOneWeek; vSeedsOut.push_back(addr); } @@ -417,39 +415,48 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo if (addrConnect.IsValid()) { bool proxyConnectionFailed = false; - if (GetProxy(addrConnect.GetNetwork(), proxy)) + if (GetProxy(addrConnect.GetNetwork(), proxy)) { + hSocket = CreateSocket(proxy.proxy); + if (hSocket == INVALID_SOCKET) { + return nullptr; + } connected = ConnectThroughProxy(proxy, addrConnect.ToStringIP(), addrConnect.GetPort(), hSocket, nConnectTimeout, &proxyConnectionFailed); - else // no proxy needed (none set for target network) + } else { + // no proxy needed (none set for target network) + hSocket = CreateSocket(addrConnect); + if (hSocket == INVALID_SOCKET) { + return nullptr; + } connected = ConnectSocketDirectly(addrConnect, hSocket, nConnectTimeout); + } if (!proxyConnectionFailed) { // If a connection to the node was attempted, and failure (if any) is not caused by a problem connecting to // the proxy, mark this as an attempt. addrman.Attempt(addrConnect, fCountFailure); } } else if (pszDest && GetNameProxy(proxy)) { + hSocket = CreateSocket(proxy.proxy); + if (hSocket == INVALID_SOCKET) { + return nullptr; + } std::string host; int port = default_port; SplitHostPort(std::string(pszDest), port, host); connected = ConnectThroughProxy(proxy, host, port, hSocket, nConnectTimeout, nullptr); } - if (connected) { - if (!IsSelectableSocket(hSocket)) { - LogPrintf("Cannot create connection: non-selectable socket created (fd >= FD_SETSIZE ?)\n"); - CloseSocket(hSocket); - return nullptr; - } - - // Add node - NodeId id = GetNewNodeId(); - uint64_t nonce = GetDeterministicRandomizer(RANDOMIZER_ID_LOCALHOSTNONCE).Write(id).Finalize(); - CAddress addr_bind = GetBindAddress(hSocket); - CNode* pnode = new CNode(id, nLocalServices, GetBestHeight(), hSocket, addrConnect, CalculateKeyedNetGroup(addrConnect), nonce, addr_bind, pszDest ? pszDest : "", false); - pnode->AddRef(); - - return pnode; + if (!connected) { + CloseSocket(hSocket); + return nullptr; } - return nullptr; + // Add node + NodeId id = GetNewNodeId(); + uint64_t nonce = GetDeterministicRandomizer(RANDOMIZER_ID_LOCALHOSTNONCE).Write(id).Finalize(); + CAddress addr_bind = GetBindAddress(hSocket); + CNode* pnode = new CNode(id, nLocalServices, GetBestHeight(), hSocket, addrConnect, CalculateKeyedNetGroup(addrConnect), nonce, addr_bind, pszDest ? pszDest : "", false); + pnode->AddRef(); + + return pnode; } void CConnman::DumpBanlist() @@ -596,21 +603,28 @@ void CConnman::SetBanned(const banmap_t &banMap) void CConnman::SweepBanned() { int64_t now = GetTime(); - - LOCK(cs_setBanned); - banmap_t::iterator it = setBanned.begin(); - while(it != setBanned.end()) + bool notifyUI = false; { - CSubNet subNet = (*it).first; - CBanEntry banEntry = (*it).second; - if(now > banEntry.nBanUntil) + LOCK(cs_setBanned); + banmap_t::iterator it = setBanned.begin(); + while(it != setBanned.end()) { - setBanned.erase(it++); - setBannedIsDirty = true; - LogPrint(BCLog::NET, "%s: Removed banned node ip/subnet from banlist.dat: %s\n", __func__, subNet.ToString()); + CSubNet subNet = (*it).first; + CBanEntry banEntry = (*it).second; + if(now > banEntry.nBanUntil) + { + setBanned.erase(it++); + setBannedIsDirty = true; + notifyUI = true; + LogPrint(BCLog::NET, "%s: Removed banned node ip/subnet from banlist.dat: %s\n", __func__, subNet.ToString()); + } + else + ++it; } - else - ++it; + } + // update UI + if(notifyUI && clientInterface) { + clientInterface->BannedListChanged(); } } @@ -1102,7 +1116,7 @@ void CConnman::AcceptConnection(const ListenSocket& hListenSocket) { if (IsBanned(addr) && !whitelisted) { - LogPrintf("connection from %s dropped (banned)\n", addr.ToString()); + LogPrint(BCLog::NET, "connection from %s dropped (banned)\n", addr.ToString()); CloseSocket(hSocket); return; } @@ -1563,19 +1577,6 @@ void MapPort(bool) -static std::string GetDNSHost(const CDNSSeedData& data, ServiceFlags* requiredServiceBits) -{ - //use default host for non-filter-capable seeds or if we use the default service bits (NODE_NETWORK) - if (!data.supportsServiceBitsFiltering || *requiredServiceBits == NODE_NETWORK) { - *requiredServiceBits = NODE_NETWORK; - return data.host; - } - - // See chainparams.cpp, most dnsseeds only support one or two possible servicebits hostnames - return strprintf("x%x.%s", *requiredServiceBits, data.host); -} - - void CConnman::ThreadDNSAddressSeed() { // goal: only query DNS seeds if address need is acute @@ -1598,22 +1599,22 @@ void CConnman::ThreadDNSAddressSeed() } } - const std::vector<CDNSSeedData> &vSeeds = Params().DNSSeeds(); + const std::vector<std::string> &vSeeds = Params().DNSSeeds(); int found = 0; LogPrintf("Loading addresses from DNS seeds (could take a while)\n"); - for (const CDNSSeedData &seed : vSeeds) { + for (const std::string &seed : vSeeds) { if (interruptNet) { return; } if (HaveNameProxy()) { - AddOneShot(seed.host); + AddOneShot(seed); } else { std::vector<CNetAddr> vIPs; std::vector<CAddress> vAdd; ServiceFlags requiredServiceBits = GetDesirableServiceFlags(NODE_NONE); - std::string host = GetDNSHost(seed, &requiredServiceBits); + std::string host = strprintf("x%x.%s", requiredServiceBits, seed); CNetAddr resolveSource; if (!resolveSource.SetInternal(host)) { continue; @@ -1629,6 +1630,10 @@ void CConnman::ThreadDNSAddressSeed() found++; } addrman.Add(vAdd, resolveSource); + } else { + // We now avoid directly using results from DNS Seeds which do not support service bit filtering, + // instead using them as a oneshot to get nodes with our desired service bits. + AddOneShot(seed); } } } @@ -2058,44 +2063,21 @@ bool CConnman::BindListenPort(const CService &addrBind, std::string& strError, b return false; } - SOCKET hListenSocket = socket(((struct sockaddr*)&sockaddr)->sa_family, SOCK_STREAM, IPPROTO_TCP); + SOCKET hListenSocket = CreateSocket(addrBind); if (hListenSocket == INVALID_SOCKET) { strError = strprintf("Error: Couldn't open socket for incoming connections (socket returned error %s)", NetworkErrorString(WSAGetLastError())); LogPrintf("%s\n", strError); return false; } - if (!IsSelectableSocket(hListenSocket)) - { - strError = "Error: Couldn't create a listenable socket for incoming connections"; - LogPrintf("%s\n", strError); - return false; - } - - #ifndef WIN32 -#ifdef SO_NOSIGPIPE - // Different way of disabling SIGPIPE on BSD - setsockopt(hListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&nOne, sizeof(int)); -#endif // Allow binding if the port is still in TIME_WAIT state after // the program was closed and restarted. setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (void*)&nOne, sizeof(int)); - // Disable Nagle's algorithm - setsockopt(hListenSocket, IPPROTO_TCP, TCP_NODELAY, (void*)&nOne, sizeof(int)); #else setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (const char*)&nOne, sizeof(int)); - setsockopt(hListenSocket, IPPROTO_TCP, TCP_NODELAY, (const char*)&nOne, sizeof(int)); #endif - // Set to non-blocking, incoming connections will also inherit this - if (!SetSocketNonBlocking(hListenSocket, true)) { - CloseSocket(hListenSocket); - strError = strprintf("BindListenPort: Setting listening socket to non-blocking failed, error %s\n", NetworkErrorString(WSAGetLastError())); - LogPrintf("%s\n", strError); - return false; - } - // some systems don't have IPV6_V6ONLY but are always v6only; others do have the option // and enable it by default or not. Try to enable it, if possible. if (addrBind.IsIPv6()) { @@ -2269,10 +2251,16 @@ bool CConnman::Start(CScheduler& scheduler, const Options& connOptions) { Init(connOptions); - nTotalBytesRecv = 0; - nTotalBytesSent = 0; - nMaxOutboundTotalBytesSentInCycle = 0; - nMaxOutboundCycleStartTime = 0; + { + LOCK(cs_totalBytesRecv); + nTotalBytesRecv = 0; + } + { + LOCK(cs_totalBytesSent); + nTotalBytesSent = 0; + nMaxOutboundTotalBytesSentInCycle = 0; + nMaxOutboundCycleStartTime = 0; + } if (fListen && !InitBinds(connOptions.vBinds, connOptions.vWhiteBinds)) { if (clientInterface) { @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -158,10 +158,16 @@ public: m_msgproc = connOptions.m_msgproc; nSendBufferMaxSize = connOptions.nSendBufferMaxSize; nReceiveFloodSize = connOptions.nReceiveFloodSize; - nMaxOutboundTimeframe = connOptions.nMaxOutboundTimeframe; - nMaxOutboundLimit = connOptions.nMaxOutboundLimit; + { + LOCK(cs_totalBytesSent); + nMaxOutboundTimeframe = connOptions.nMaxOutboundTimeframe; + nMaxOutboundLimit = connOptions.nMaxOutboundLimit; + } vWhitelistedRange = connOptions.vWhitelistedRange; - vAddedNodes = connOptions.m_added_nodes; + { + LOCK(cs_vAddedNodes); + vAddedNodes = connOptions.m_added_nodes; + } } CConnman(uint64_t seed0, uint64_t seed1); @@ -364,14 +370,14 @@ private: // Network usage totals CCriticalSection cs_totalBytesRecv; CCriticalSection cs_totalBytesSent; - uint64_t nTotalBytesRecv; - uint64_t nTotalBytesSent; + uint64_t nTotalBytesRecv GUARDED_BY(cs_totalBytesRecv); + uint64_t nTotalBytesSent GUARDED_BY(cs_totalBytesSent); // outbound limit & stats - uint64_t nMaxOutboundTotalBytesSentInCycle; - uint64_t nMaxOutboundCycleStartTime; - uint64_t nMaxOutboundLimit; - uint64_t nMaxOutboundTimeframe; + uint64_t nMaxOutboundTotalBytesSentInCycle GUARDED_BY(cs_totalBytesSent); + uint64_t nMaxOutboundCycleStartTime GUARDED_BY(cs_totalBytesSent); + uint64_t nMaxOutboundLimit GUARDED_BY(cs_totalBytesSent); + uint64_t nMaxOutboundTimeframe GUARDED_BY(cs_totalBytesSent); // Whitelisted ranges. Any node connecting from these is automatically // whitelisted (as well as those connecting to whitelisted binds). @@ -389,7 +395,7 @@ private: CAddrMan addrman; std::deque<std::string> vOneShots; CCriticalSection cs_vOneShots; - std::vector<std::string> vAddedNodes; + std::vector<std::string> vAddedNodes GUARDED_BY(cs_vAddedNodes); CCriticalSection cs_vAddedNodes; std::vector<CNode*> vNodes; std::list<CNode*> vNodesDisconnected; diff --git a/src/net_processing.cpp b/src/net_processing.cpp index 442cd00c9b..3cf96be61a 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -14,7 +14,6 @@ #include <init.h> #include <validation.h> #include <merkleblock.h> -#include <net.h> #include <netmessagemaker.h> #include <netbase.h> #include <policy/fees.h> @@ -30,7 +29,6 @@ #include <util.h> #include <utilmoneystr.h> #include <utilstrencodings.h> -#include <validationinterface.h> #if defined(NDEBUG) # error "Bitcoin cannot be compiled without assertions." @@ -41,7 +39,7 @@ std::atomic<int64_t> nTimeBestReceived(0); // Used only to inform the wallet of struct IteratorComparator { template<typename I> - bool operator()(const I& a, const I& b) + bool operator()(const I& a, const I& b) const { return &(*a) < &(*b); } @@ -53,12 +51,13 @@ struct COrphanTx { NodeId fromPeer; int64_t nTimeExpire; }; -std::map<uint256, COrphanTx> mapOrphanTransactions GUARDED_BY(cs_main); -std::map<COutPoint, std::set<std::map<uint256, COrphanTx>::iterator, IteratorComparator>> mapOrphanTransactionsByPrev GUARDED_BY(cs_main); -void EraseOrphansFor(NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(cs_main); +static CCriticalSection g_cs_orphans; +std::map<uint256, COrphanTx> mapOrphanTransactions GUARDED_BY(g_cs_orphans); +std::map<COutPoint, std::set<std::map<uint256, COrphanTx>::iterator, IteratorComparator>> mapOrphanTransactionsByPrev GUARDED_BY(g_cs_orphans); +void EraseOrphansFor(NodeId peer); -static size_t vExtraTxnForCompactIt = 0; -static std::vector<std::pair<uint256, CTransactionRef>> vExtraTxnForCompact GUARDED_BY(cs_main); +static size_t vExtraTxnForCompactIt GUARDED_BY(g_cs_orphans) = 0; +static std::vector<std::pair<uint256, CTransactionRef>> vExtraTxnForCompact GUARDED_BY(g_cs_orphans); static const uint64_t RANDOMIZER_ID_ADDRESS_RELAY = 0x3cac0035b5866b90ULL; // SHA256("main address relay")[0:8] @@ -129,7 +128,7 @@ namespace { int g_outbound_peers_with_protect_from_disconnect = 0; /** When our tip was last updated. */ - int64_t g_last_tip_update = 0; + std::atomic<int64_t> g_last_tip_update(0); /** Relay map, protected by cs_main. */ typedef std::map<uint256, CTransactionRef> MapRelay; @@ -633,7 +632,7 @@ bool GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats) { // mapOrphanTransactions // -void AddToCompactExtraTransactions(const CTransactionRef& tx) EXCLUSIVE_LOCKS_REQUIRED(cs_main) +void AddToCompactExtraTransactions(const CTransactionRef& tx) EXCLUSIVE_LOCKS_REQUIRED(g_cs_orphans) { size_t max_extra_txn = gArgs.GetArg("-blockreconstructionextratxn", DEFAULT_BLOCK_RECONSTRUCTION_EXTRA_TXN); if (max_extra_txn <= 0) @@ -644,7 +643,7 @@ void AddToCompactExtraTransactions(const CTransactionRef& tx) EXCLUSIVE_LOCKS_RE vExtraTxnForCompactIt = (vExtraTxnForCompactIt + 1) % max_extra_txn; } -bool AddOrphanTx(const CTransactionRef& tx, NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(cs_main) +bool AddOrphanTx(const CTransactionRef& tx, NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(g_cs_orphans) { const uint256& hash = tx->GetHash(); if (mapOrphanTransactions.count(hash)) @@ -677,7 +676,7 @@ bool AddOrphanTx(const CTransactionRef& tx, NodeId peer) EXCLUSIVE_LOCKS_REQUIRE return true; } -int static EraseOrphanTx(uint256 hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main) +int static EraseOrphanTx(uint256 hash) EXCLUSIVE_LOCKS_REQUIRED(g_cs_orphans) { std::map<uint256, COrphanTx>::iterator it = mapOrphanTransactions.find(hash); if (it == mapOrphanTransactions.end()) @@ -697,6 +696,7 @@ int static EraseOrphanTx(uint256 hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main) void EraseOrphansFor(NodeId peer) { + LOCK(g_cs_orphans); int nErased = 0; std::map<uint256, COrphanTx>::iterator iter = mapOrphanTransactions.begin(); while (iter != mapOrphanTransactions.end()) @@ -711,8 +711,10 @@ void EraseOrphansFor(NodeId peer) } -unsigned int LimitOrphanTxSize(unsigned int nMaxOrphans) EXCLUSIVE_LOCKS_REQUIRED(cs_main) +unsigned int LimitOrphanTxSize(unsigned int nMaxOrphans) { + LOCK(g_cs_orphans); + unsigned int nEvicted = 0; static int64_t nNextSweep; int64_t nNow = GetTime(); @@ -806,7 +808,7 @@ PeerLogicValidation::PeerLogicValidation(CConnman* connmanIn, CScheduler &schedu } void PeerLogicValidation::BlockConnected(const std::shared_ptr<const CBlock>& pblock, const CBlockIndex* pindex, const std::vector<CTransactionRef>& vtxConflicted) { - LOCK(cs_main); + LOCK(g_cs_orphans); std::vector<uint256> vOrphanErase; @@ -973,9 +975,13 @@ bool static AlreadyHave(const CInv& inv) EXCLUSIVE_LOCKS_REQUIRED(cs_main) recentRejects->reset(); } + { + LOCK(g_cs_orphans); + if (mapOrphanTransactions.count(inv.hash)) return true; + } + return recentRejects->contains(inv.hash) || mempool.exists(inv.hash) || - mapOrphanTransactions.count(inv.hash) || pcoinsTip->HaveCoinInCache(COutPoint(inv.hash, 0)) || // Best effort: only try output 0 and 1 pcoinsTip->HaveCoinInCache(COutPoint(inv.hash, 1)); } @@ -1032,170 +1038,198 @@ static void RelayAddress(const CAddress& addr, bool fReachable, CConnman* connma connman->ForEachNodeThen(std::move(sortfunc), std::move(pushfunc)); } +void static ProcessGetBlockData(CNode* pfrom, const Consensus::Params& consensusParams, const CInv& inv, CConnman* connman, const std::atomic<bool>& interruptMsgProc) +{ + bool send = false; + std::shared_ptr<const CBlock> a_recent_block; + std::shared_ptr<const CBlockHeaderAndShortTxIDs> a_recent_compact_block; + bool fWitnessesPresentInARecentCompactBlock; + { + LOCK(cs_most_recent_block); + a_recent_block = most_recent_block; + a_recent_compact_block = most_recent_compact_block; + fWitnessesPresentInARecentCompactBlock = fWitnessesPresentInMostRecentCompactBlock; + } + + bool need_activate_chain = false; + { + LOCK(cs_main); + BlockMap::iterator mi = mapBlockIndex.find(inv.hash); + if (mi != mapBlockIndex.end()) + { + if (mi->second->nChainTx && !mi->second->IsValid(BLOCK_VALID_SCRIPTS) && + mi->second->IsValid(BLOCK_VALID_TREE)) { + // If we have the block and all of its parents, but have not yet validated it, + // we might be in the middle of connecting it (ie in the unlock of cs_main + // before ActivateBestChain but after AcceptBlock). + // In this case, we need to run ActivateBestChain prior to checking the relay + // conditions below. + need_activate_chain = true; + } + } + } // release cs_main before calling ActivateBestChain + if (need_activate_chain) { + CValidationState dummy; + ActivateBestChain(dummy, Params(), a_recent_block); + } + + LOCK(cs_main); + BlockMap::iterator mi = mapBlockIndex.find(inv.hash); + if (mi != mapBlockIndex.end()) { + send = BlockRequestAllowed(mi->second, consensusParams); + if (!send) { + LogPrint(BCLog::NET, "%s: ignoring request from peer=%i for old block that isn't in the main chain\n", __func__, pfrom->GetId()); + } + } + const CNetMsgMaker msgMaker(pfrom->GetSendVersion()); + // disconnect node in case we have reached the outbound limit for serving historical blocks + // never disconnect whitelisted nodes + if (send && connman->OutboundTargetReached(true) && ( ((pindexBestHeader != nullptr) && (pindexBestHeader->GetBlockTime() - mi->second->GetBlockTime() > HISTORICAL_BLOCK_AGE)) || inv.type == MSG_FILTERED_BLOCK) && !pfrom->fWhitelisted) + { + LogPrint(BCLog::NET, "historical block serving limit reached, disconnect peer=%d\n", pfrom->GetId()); + + //disconnect node + pfrom->fDisconnect = true; + send = false; + } + // Avoid leaking prune-height by never sending blocks below the NODE_NETWORK_LIMITED threshold + if (send && !pfrom->fWhitelisted && ( + (((pfrom->GetLocalServices() & NODE_NETWORK_LIMITED) == NODE_NETWORK_LIMITED) && ((pfrom->GetLocalServices() & NODE_NETWORK) != NODE_NETWORK) && (chainActive.Tip()->nHeight - mi->second->nHeight > (int)NODE_NETWORK_LIMITED_MIN_BLOCKS + 2 /* add two blocks buffer extension for possible races */) ) + )) { + LogPrint(BCLog::NET, "Ignore block request below NODE_NETWORK_LIMITED threshold from peer=%d\n", pfrom->GetId()); + + //disconnect node and prevent it from stalling (would otherwise wait for the missing block) + pfrom->fDisconnect = true; + send = false; + } + // Pruned nodes may have deleted the block, so check whether + // it's available before trying to send. + if (send && (mi->second->nStatus & BLOCK_HAVE_DATA)) + { + std::shared_ptr<const CBlock> pblock; + if (a_recent_block && a_recent_block->GetHash() == (*mi).second->GetBlockHash()) { + pblock = a_recent_block; + } else { + // Send block from disk + std::shared_ptr<CBlock> pblockRead = std::make_shared<CBlock>(); + if (!ReadBlockFromDisk(*pblockRead, (*mi).second, consensusParams)) + assert(!"cannot load block from disk"); + pblock = pblockRead; + } + if (inv.type == MSG_BLOCK) + connman->PushMessage(pfrom, msgMaker.Make(SERIALIZE_TRANSACTION_NO_WITNESS, NetMsgType::BLOCK, *pblock)); + else if (inv.type == MSG_WITNESS_BLOCK) + connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::BLOCK, *pblock)); + else if (inv.type == MSG_FILTERED_BLOCK) + { + bool sendMerkleBlock = false; + CMerkleBlock merkleBlock; + { + LOCK(pfrom->cs_filter); + if (pfrom->pfilter) { + sendMerkleBlock = true; + merkleBlock = CMerkleBlock(*pblock, *pfrom->pfilter); + } + } + if (sendMerkleBlock) { + connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::MERKLEBLOCK, merkleBlock)); + // CMerkleBlock just contains hashes, so also push any transactions in the block the client did not see + // This avoids hurting performance by pointlessly requiring a round-trip + // Note that there is currently no way for a node to request any single transactions we didn't send here - + // they must either disconnect and retry or request the full block. + // Thus, the protocol spec specified allows for us to provide duplicate txn here, + // however we MUST always provide at least what the remote peer needs + typedef std::pair<unsigned int, uint256> PairType; + for (PairType& pair : merkleBlock.vMatchedTxn) + connman->PushMessage(pfrom, msgMaker.Make(SERIALIZE_TRANSACTION_NO_WITNESS, NetMsgType::TX, *pblock->vtx[pair.first])); + } + // else + // no response + } + else if (inv.type == MSG_CMPCT_BLOCK) + { + // If a peer is asking for old blocks, we're almost guaranteed + // they won't have a useful mempool to match against a compact block, + // and we don't feel like constructing the object for them, so + // instead we respond with the full, non-compact block. + bool fPeerWantsWitness = State(pfrom->GetId())->fWantsCmpctWitness; + int nSendFlags = fPeerWantsWitness ? 0 : SERIALIZE_TRANSACTION_NO_WITNESS; + if (CanDirectFetch(consensusParams) && mi->second->nHeight >= chainActive.Height() - MAX_CMPCTBLOCK_DEPTH) { + if ((fPeerWantsWitness || !fWitnessesPresentInARecentCompactBlock) && a_recent_compact_block && a_recent_compact_block->header.GetHash() == mi->second->GetBlockHash()) { + connman->PushMessage(pfrom, msgMaker.Make(nSendFlags, NetMsgType::CMPCTBLOCK, *a_recent_compact_block)); + } else { + CBlockHeaderAndShortTxIDs cmpctblock(*pblock, fPeerWantsWitness); + connman->PushMessage(pfrom, msgMaker.Make(nSendFlags, NetMsgType::CMPCTBLOCK, cmpctblock)); + } + } else { + connman->PushMessage(pfrom, msgMaker.Make(nSendFlags, NetMsgType::BLOCK, *pblock)); + } + } + + // Trigger the peer node to send a getblocks request for the next batch of inventory + if (inv.hash == pfrom->hashContinue) + { + // Bypass PushInventory, this must send even if redundant, + // and we want it right after the last block so they don't + // wait for other stuff first. + std::vector<CInv> vInv; + vInv.push_back(CInv(MSG_BLOCK, chainActive.Tip()->GetBlockHash())); + connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::INV, vInv)); + pfrom->hashContinue.SetNull(); + } + } +} + void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParams, CConnman* connman, const std::atomic<bool>& interruptMsgProc) { + AssertLockNotHeld(cs_main); + std::deque<CInv>::iterator it = pfrom->vRecvGetData.begin(); std::vector<CInv> vNotFound; const CNetMsgMaker msgMaker(pfrom->GetSendVersion()); - LOCK(cs_main); - - while (it != pfrom->vRecvGetData.end()) { - // Don't bother if send buffer is too full to respond anyway - if (pfrom->fPauseSend) - break; + { + LOCK(cs_main); - const CInv &inv = *it; - { + while (it != pfrom->vRecvGetData.end() && (it->type == MSG_TX || it->type == MSG_WITNESS_TX)) { if (interruptMsgProc) return; + // Don't bother if send buffer is too full to respond anyway + if (pfrom->fPauseSend) + break; + const CInv &inv = *it; it++; - if (inv.type == MSG_BLOCK || inv.type == MSG_FILTERED_BLOCK || inv.type == MSG_CMPCT_BLOCK || inv.type == MSG_WITNESS_BLOCK) - { - bool send = false; - BlockMap::iterator mi = mapBlockIndex.find(inv.hash); - std::shared_ptr<const CBlock> a_recent_block; - std::shared_ptr<const CBlockHeaderAndShortTxIDs> a_recent_compact_block; - bool fWitnessesPresentInARecentCompactBlock; - { - LOCK(cs_most_recent_block); - a_recent_block = most_recent_block; - a_recent_compact_block = most_recent_compact_block; - fWitnessesPresentInARecentCompactBlock = fWitnessesPresentInMostRecentCompactBlock; - } - if (mi != mapBlockIndex.end()) - { - if (mi->second->nChainTx && !mi->second->IsValid(BLOCK_VALID_SCRIPTS) && - mi->second->IsValid(BLOCK_VALID_TREE)) { - // If we have the block and all of its parents, but have not yet validated it, - // we might be in the middle of connecting it (ie in the unlock of cs_main - // before ActivateBestChain but after AcceptBlock). - // In this case, we need to run ActivateBestChain prior to checking the relay - // conditions below. - CValidationState dummy; - ActivateBestChain(dummy, Params(), a_recent_block); - } - send = BlockRequestAllowed(mi->second, consensusParams); - if (!send) { - LogPrintf("%s: ignoring request from peer=%i for old block that isn't in the main chain\n", __func__, pfrom->GetId()); - } - } - // disconnect node in case we have reached the outbound limit for serving historical blocks - // never disconnect whitelisted nodes - if (send && connman->OutboundTargetReached(true) && ( ((pindexBestHeader != nullptr) && (pindexBestHeader->GetBlockTime() - mi->second->GetBlockTime() > HISTORICAL_BLOCK_AGE)) || inv.type == MSG_FILTERED_BLOCK) && !pfrom->fWhitelisted) - { - LogPrint(BCLog::NET, "historical block serving limit reached, disconnect peer=%d\n", pfrom->GetId()); - - //disconnect node - pfrom->fDisconnect = true; - send = false; - } - // Pruned nodes may have deleted the block, so check whether - // it's available before trying to send. - if (send && (mi->second->nStatus & BLOCK_HAVE_DATA)) - { - std::shared_ptr<const CBlock> pblock; - if (a_recent_block && a_recent_block->GetHash() == (*mi).second->GetBlockHash()) { - pblock = a_recent_block; - } else { - // Send block from disk - std::shared_ptr<CBlock> pblockRead = std::make_shared<CBlock>(); - if (!ReadBlockFromDisk(*pblockRead, (*mi).second, consensusParams)) - assert(!"cannot load block from disk"); - pblock = pblockRead; - } - if (inv.type == MSG_BLOCK) - connman->PushMessage(pfrom, msgMaker.Make(SERIALIZE_TRANSACTION_NO_WITNESS, NetMsgType::BLOCK, *pblock)); - else if (inv.type == MSG_WITNESS_BLOCK) - connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::BLOCK, *pblock)); - else if (inv.type == MSG_FILTERED_BLOCK) - { - bool sendMerkleBlock = false; - CMerkleBlock merkleBlock; - { - LOCK(pfrom->cs_filter); - if (pfrom->pfilter) { - sendMerkleBlock = true; - merkleBlock = CMerkleBlock(*pblock, *pfrom->pfilter); - } - } - if (sendMerkleBlock) { - connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::MERKLEBLOCK, merkleBlock)); - // CMerkleBlock just contains hashes, so also push any transactions in the block the client did not see - // This avoids hurting performance by pointlessly requiring a round-trip - // Note that there is currently no way for a node to request any single transactions we didn't send here - - // they must either disconnect and retry or request the full block. - // Thus, the protocol spec specified allows for us to provide duplicate txn here, - // however we MUST always provide at least what the remote peer needs - typedef std::pair<unsigned int, uint256> PairType; - for (PairType& pair : merkleBlock.vMatchedTxn) - connman->PushMessage(pfrom, msgMaker.Make(SERIALIZE_TRANSACTION_NO_WITNESS, NetMsgType::TX, *pblock->vtx[pair.first])); - } - // else - // no response - } - else if (inv.type == MSG_CMPCT_BLOCK) - { - // If a peer is asking for old blocks, we're almost guaranteed - // they won't have a useful mempool to match against a compact block, - // and we don't feel like constructing the object for them, so - // instead we respond with the full, non-compact block. - bool fPeerWantsWitness = State(pfrom->GetId())->fWantsCmpctWitness; - int nSendFlags = fPeerWantsWitness ? 0 : SERIALIZE_TRANSACTION_NO_WITNESS; - if (CanDirectFetch(consensusParams) && mi->second->nHeight >= chainActive.Height() - MAX_CMPCTBLOCK_DEPTH) { - if ((fPeerWantsWitness || !fWitnessesPresentInARecentCompactBlock) && a_recent_compact_block && a_recent_compact_block->header.GetHash() == mi->second->GetBlockHash()) { - connman->PushMessage(pfrom, msgMaker.Make(nSendFlags, NetMsgType::CMPCTBLOCK, *a_recent_compact_block)); - } else { - CBlockHeaderAndShortTxIDs cmpctblock(*pblock, fPeerWantsWitness); - connman->PushMessage(pfrom, msgMaker.Make(nSendFlags, NetMsgType::CMPCTBLOCK, cmpctblock)); - } - } else { - connman->PushMessage(pfrom, msgMaker.Make(nSendFlags, NetMsgType::BLOCK, *pblock)); - } - } - - // Trigger the peer node to send a getblocks request for the next batch of inventory - if (inv.hash == pfrom->hashContinue) - { - // Bypass PushInventory, this must send even if redundant, - // and we want it right after the last block so they don't - // wait for other stuff first. - std::vector<CInv> vInv; - vInv.push_back(CInv(MSG_BLOCK, chainActive.Tip()->GetBlockHash())); - connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::INV, vInv)); - pfrom->hashContinue.SetNull(); - } - } - } - else if (inv.type == MSG_TX || inv.type == MSG_WITNESS_TX) - { - // Send stream from relay memory - bool push = false; - auto mi = mapRelay.find(inv.hash); - int nSendFlags = (inv.type == MSG_TX ? SERIALIZE_TRANSACTION_NO_WITNESS : 0); - if (mi != mapRelay.end()) { - connman->PushMessage(pfrom, msgMaker.Make(nSendFlags, NetMsgType::TX, *mi->second)); + // Send stream from relay memory + bool push = false; + auto mi = mapRelay.find(inv.hash); + int nSendFlags = (inv.type == MSG_TX ? SERIALIZE_TRANSACTION_NO_WITNESS : 0); + if (mi != mapRelay.end()) { + connman->PushMessage(pfrom, msgMaker.Make(nSendFlags, NetMsgType::TX, *mi->second)); + push = true; + } else if (pfrom->timeLastMempoolReq) { + auto txinfo = mempool.info(inv.hash); + // To protect privacy, do not answer getdata using the mempool when + // that TX couldn't have been INVed in reply to a MEMPOOL request. + if (txinfo.tx && txinfo.nTime <= pfrom->timeLastMempoolReq) { + connman->PushMessage(pfrom, msgMaker.Make(nSendFlags, NetMsgType::TX, *txinfo.tx)); push = true; - } else if (pfrom->timeLastMempoolReq) { - auto txinfo = mempool.info(inv.hash); - // To protect privacy, do not answer getdata using the mempool when - // that TX couldn't have been INVed in reply to a MEMPOOL request. - if (txinfo.tx && txinfo.nTime <= pfrom->timeLastMempoolReq) { - connman->PushMessage(pfrom, msgMaker.Make(nSendFlags, NetMsgType::TX, *txinfo.tx)); - push = true; - } - } - if (!push) { - vNotFound.push_back(inv); } } + if (!push) { + vNotFound.push_back(inv); + } // Track requests for our stuff. GetMainSignals().Inventory(inv.hash); + } + } // release cs_main - if (inv.type == MSG_BLOCK || inv.type == MSG_FILTERED_BLOCK || inv.type == MSG_CMPCT_BLOCK || inv.type == MSG_WITNESS_BLOCK) - break; + if (it != pfrom->vRecvGetData.end()) { + const CInv &inv = *it; + it++; + if (inv.type == MSG_BLOCK || inv.type == MSG_FILTERED_BLOCK || inv.type == MSG_CMPCT_BLOCK || inv.type == MSG_WITNESS_BLOCK) { + ProcessGetBlockData(pfrom, consensusParams, inv, connman, interruptMsgProc); } } @@ -1559,7 +1593,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr if (nVersion < MIN_PEER_PROTO_VERSION) { // disconnect from peers older than this proto version - LogPrintf("peer=%d using obsolete version %i; disconnecting\n", pfrom->GetId(), nVersion); + LogPrint(BCLog::NET, "peer=%d using obsolete version %i; disconnecting\n", pfrom->GetId(), nVersion); connman->PushMessage(pfrom, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::REJECT, strCommand, REJECT_OBSOLETE, strprintf("Version must be %d or greater", MIN_PEER_PROTO_VERSION))); pfrom->fDisconnect = true; @@ -1659,7 +1693,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr if (fLogIPs) remoteAddr = ", peeraddr=" + pfrom->addr.ToString(); - LogPrintf("receive version message: %s: version %d, blocks=%d, us=%s, peer=%d%s\n", + LogPrint(BCLog::NET, "receive version message: %s: version %d, blocks=%d, us=%s, peer=%d%s\n", cleanSubVer, pfrom->nVersion, pfrom->nStartingHeight, addrMe.ToString(), pfrom->GetId(), remoteAddr); @@ -1702,6 +1736,9 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr // Mark this node as currently connected, so we update its timestamp later. LOCK(cs_main); State(pfrom->GetId())->fCurrentlyConnected = true; + LogPrintf("New outbound peer connected: version: %d, blocks=%d, peer=%d%s\n", + pfrom->nVersion.load(), pfrom->nStartingHeight, pfrom->GetId(), + (fLogIPs ? strprintf(", peeraddr=%s", pfrom->addr.ToString()) : "")); } if (pfrom->nVersion >= SENDHEADERS_VERSION) { @@ -1980,7 +2017,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr BlockMap::iterator it = mapBlockIndex.find(req.blockhash); if (it == mapBlockIndex.end() || !(it->second->nStatus & BLOCK_HAVE_DATA)) { - LogPrintf("Peer %d sent us a getblocktxn for a block we don't have", pfrom->GetId()); + LogPrint(BCLog::NET, "Peer %d sent us a getblocktxn for a block we don't have", pfrom->GetId()); return true; } @@ -1997,7 +2034,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr inv.type = State(pfrom->GetId())->fWantsCmpctWitness ? MSG_WITNESS_BLOCK : MSG_BLOCK; inv.hash = req.blockhash; pfrom->vRecvGetData.push_back(inv); - ProcessGetData(pfrom, chainparams.GetConsensus(), connman, interruptMsgProc); + // The message processing loop will go around again (without pausing) and we'll respond then (without cs_main) return true; } @@ -2032,7 +2069,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr pindex = (*mi).second; if (!BlockRequestAllowed(pindex, chainparams.GetConsensus())) { - LogPrintf("%s: ignoring request from peer=%i for old block header that isn't in the main chain\n", __func__, pfrom->GetId()); + LogPrint(BCLog::NET, "%s: ignoring request from peer=%i for old block header that isn't in the main chain\n", __func__, pfrom->GetId()); return true; } } @@ -2090,7 +2127,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr CInv inv(MSG_TX, tx.GetHash()); pfrom->AddInventoryKnown(inv); - LOCK(cs_main); + LOCK2(cs_main, g_cs_orphans); bool fMissingInputs = false; CValidationState state; @@ -2286,10 +2323,12 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr int nDoS; if (state.IsInvalid(nDoS)) { if (nDoS > 0) { + LogPrintf("Peer %d sent us invalid header via cmpctblock\n", pfrom->GetId()); LOCK(cs_main); Misbehaving(pfrom->GetId(), nDoS); + } else { + LogPrint(BCLog::NET, "Peer %d sent us invalid header via cmpctblock\n", pfrom->GetId()); } - LogPrintf("Peer %d sent us invalid header via cmpctblock\n", pfrom->GetId()); return true; } } @@ -2311,7 +2350,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr bool fBlockReconstructed = false; { - LOCK(cs_main); + LOCK2(cs_main, g_cs_orphans); // If AcceptBlockHeader returned true, it set pindex assert(pindex); UpdateBlockAvailability(pfrom->GetId(), pindex->GetBlockHash()); @@ -2891,7 +2930,7 @@ bool PeerLogicValidation::ProcessMessages(CNode* pfrom, std::atomic<bool>& inter msg.SetVersion(pfrom->GetRecvVersion()); // Scan for message start if (memcmp(msg.hdr.pchMessageStart, chainparams.MessageStart(), CMessageHeader::MESSAGE_START_SIZE) != 0) { - LogPrintf("PROCESSMESSAGE: INVALID MESSAGESTART %s peer=%d\n", SanitizeString(msg.hdr.GetCommand()), pfrom->GetId()); + LogPrint(BCLog::NET, "PROCESSMESSAGE: INVALID MESSAGESTART %s peer=%d\n", SanitizeString(msg.hdr.GetCommand()), pfrom->GetId()); pfrom->fDisconnect = true; return false; } @@ -2900,7 +2939,7 @@ bool PeerLogicValidation::ProcessMessages(CNode* pfrom, std::atomic<bool>& inter CMessageHeader& hdr = msg.hdr; if (!hdr.IsValid(chainparams.MessageStart())) { - LogPrintf("PROCESSMESSAGE: ERRORS IN HEADER %s peer=%d\n", SanitizeString(hdr.GetCommand()), pfrom->GetId()); + LogPrint(BCLog::NET, "PROCESSMESSAGE: ERRORS IN HEADER %s peer=%d\n", SanitizeString(hdr.GetCommand()), pfrom->GetId()); return fMoreWork; } std::string strCommand = hdr.GetCommand(); @@ -2913,7 +2952,7 @@ bool PeerLogicValidation::ProcessMessages(CNode* pfrom, std::atomic<bool>& inter const uint256& hash = msg.GetMessageHash(); if (memcmp(hash.begin(), hdr.pchChecksum, CMessageHeader::CHECKSUM_SIZE) != 0) { - LogPrintf("%s(%s, %u bytes): CHECKSUM ERROR expected %s was %s\n", __func__, + LogPrint(BCLog::NET, "%s(%s, %u bytes): CHECKSUM ERROR expected %s was %s\n", __func__, SanitizeString(strCommand), nMessageSize, HexStr(hash.begin(), hash.begin()+CMessageHeader::CHECKSUM_SIZE), HexStr(hdr.pchChecksum, hdr.pchChecksum+CMessageHeader::CHECKSUM_SIZE)); @@ -2936,17 +2975,17 @@ bool PeerLogicValidation::ProcessMessages(CNode* pfrom, std::atomic<bool>& inter if (strstr(e.what(), "end of data")) { // Allow exceptions from under-length message on vRecv - LogPrintf("%s(%s, %u bytes): Exception '%s' caught, normally caused by a message being shorter than its stated length\n", __func__, SanitizeString(strCommand), nMessageSize, e.what()); + LogPrint(BCLog::NET, "%s(%s, %u bytes): Exception '%s' caught, normally caused by a message being shorter than its stated length\n", __func__, SanitizeString(strCommand), nMessageSize, e.what()); } else if (strstr(e.what(), "size too large")) { // Allow exceptions from over-long size - LogPrintf("%s(%s, %u bytes): Exception '%s' caught\n", __func__, SanitizeString(strCommand), nMessageSize, e.what()); + LogPrint(BCLog::NET, "%s(%s, %u bytes): Exception '%s' caught\n", __func__, SanitizeString(strCommand), nMessageSize, e.what()); } else if (strstr(e.what(), "non-canonical ReadCompactSize()")) { // Allow exceptions from non-canonical encoding - LogPrintf("%s(%s, %u bytes): Exception '%s' caught\n", __func__, SanitizeString(strCommand), nMessageSize, e.what()); + LogPrint(BCLog::NET, "%s(%s, %u bytes): Exception '%s' caught\n", __func__, SanitizeString(strCommand), nMessageSize, e.what()); } else { @@ -2960,7 +2999,7 @@ bool PeerLogicValidation::ProcessMessages(CNode* pfrom, std::atomic<bool>& inter } if (!fRet) { - LogPrintf("%s(%s, %u bytes) FAILED peer=%d\n", __func__, SanitizeString(strCommand), nMessageSize, pfrom->GetId()); + LogPrint(BCLog::NET, "%s(%s, %u bytes) FAILED peer=%d\n", __func__, SanitizeString(strCommand), nMessageSize, pfrom->GetId()); } LOCK(cs_main); diff --git a/src/net_processing.h b/src/net_processing.h index 3fc1e05835..4f2b8935f4 100644 --- a/src/net_processing.h +++ b/src/net_processing.h @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/netaddress.cpp b/src/netaddress.cpp index 3ef3c67ae4..81f72879f4 100644 --- a/src/netaddress.cpp +++ b/src/netaddress.cpp @@ -1,12 +1,8 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#ifdef HAVE_CONFIG_H -#include <config/bitcoin-config.h> -#endif - #include <netaddress.h> #include <hash.h> #include <utilstrencodings.h> diff --git a/src/netaddress.h b/src/netaddress.h index 3b542b4748..93bbb66491 100644 --- a/src/netaddress.h +++ b/src/netaddress.h @@ -1,4 +1,4 @@ -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/netbase.cpp b/src/netbase.cpp index bd1eaf062f..276b2f4dc2 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -1,12 +1,8 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#ifdef HAVE_CONFIG_H -#include <config/bitcoin-config.h> -#endif - #include <netbase.h> #include <hash.h> @@ -317,12 +313,11 @@ std::string Socks5ErrorString(uint8_t err) } /** Connect using SOCKS5 (as described in RFC1928) */ -static bool Socks5(const std::string& strDest, int port, const ProxyCredentials *auth, SOCKET& hSocket) +static bool Socks5(const std::string& strDest, int port, const ProxyCredentials *auth, const SOCKET& hSocket) { IntrRecvError recvr; LogPrint(BCLog::NET, "SOCKS5 connecting %s\n", strDest); if (strDest.size() > 255) { - CloseSocket(hSocket); return error("Hostname too long"); } // Accepted authentication methods @@ -338,17 +333,14 @@ static bool Socks5(const std::string& strDest, int port, const ProxyCredentials } ssize_t ret = send(hSocket, (const char*)vSocks5Init.data(), vSocks5Init.size(), MSG_NOSIGNAL); if (ret != (ssize_t)vSocks5Init.size()) { - CloseSocket(hSocket); return error("Error sending to proxy"); } uint8_t pchRet1[2]; if ((recvr = InterruptibleRecv(pchRet1, 2, SOCKS5_RECV_TIMEOUT, hSocket)) != IntrRecvError::OK) { - CloseSocket(hSocket); LogPrintf("Socks5() connect to %s:%d failed: InterruptibleRecv() timeout or other failure\n", strDest, port); return false; } if (pchRet1[0] != SOCKSVersion::SOCKS5) { - CloseSocket(hSocket); return error("Proxy failed to initialize"); } if (pchRet1[1] == SOCKS5Method::USER_PASS && auth) { @@ -363,23 +355,19 @@ static bool Socks5(const std::string& strDest, int port, const ProxyCredentials vAuth.insert(vAuth.end(), auth->password.begin(), auth->password.end()); ret = send(hSocket, (const char*)vAuth.data(), vAuth.size(), MSG_NOSIGNAL); if (ret != (ssize_t)vAuth.size()) { - CloseSocket(hSocket); return error("Error sending authentication to proxy"); } LogPrint(BCLog::PROXY, "SOCKS5 sending proxy authentication %s:%s\n", auth->username, auth->password); uint8_t pchRetA[2]; if ((recvr = InterruptibleRecv(pchRetA, 2, SOCKS5_RECV_TIMEOUT, hSocket)) != IntrRecvError::OK) { - CloseSocket(hSocket); return error("Error reading proxy authentication response"); } if (pchRetA[0] != 0x01 || pchRetA[1] != 0x00) { - CloseSocket(hSocket); return error("Proxy authentication unsuccessful"); } } else if (pchRet1[1] == SOCKS5Method::NOAUTH) { // Perform no authentication } else { - CloseSocket(hSocket); return error("Proxy requested wrong authentication method %02x", pchRet1[1]); } std::vector<uint8_t> vSocks5; @@ -393,12 +381,10 @@ static bool Socks5(const std::string& strDest, int port, const ProxyCredentials vSocks5.push_back((port >> 0) & 0xFF); ret = send(hSocket, (const char*)vSocks5.data(), vSocks5.size(), MSG_NOSIGNAL); if (ret != (ssize_t)vSocks5.size()) { - CloseSocket(hSocket); return error("Error sending to proxy"); } uint8_t pchRet2[4]; if ((recvr = InterruptibleRecv(pchRet2, 4, SOCKS5_RECV_TIMEOUT, hSocket)) != IntrRecvError::OK) { - CloseSocket(hSocket); if (recvr == IntrRecvError::Timeout) { /* If a timeout happens here, this effectively means we timed out while connecting * to the remote node. This is very common for Tor, so do not print an @@ -409,17 +395,14 @@ static bool Socks5(const std::string& strDest, int port, const ProxyCredentials } } if (pchRet2[0] != SOCKSVersion::SOCKS5) { - CloseSocket(hSocket); return error("Proxy failed to accept request"); } if (pchRet2[1] != SOCKS5Reply::SUCCEEDED) { // Failures to connect to a peer that are not proxy errors - CloseSocket(hSocket); LogPrintf("Socks5() connect to %s:%d failed: %s\n", strDest, port, Socks5ErrorString(pchRet2[1])); return false; } if (pchRet2[2] != 0x00) { // Reserved field must be 0 - CloseSocket(hSocket); return error("Error: malformed proxy response"); } uint8_t pchRet3[256]; @@ -431,41 +414,42 @@ static bool Socks5(const std::string& strDest, int port, const ProxyCredentials { recvr = InterruptibleRecv(pchRet3, 1, SOCKS5_RECV_TIMEOUT, hSocket); if (recvr != IntrRecvError::OK) { - CloseSocket(hSocket); return error("Error reading from proxy"); } int nRecv = pchRet3[0]; recvr = InterruptibleRecv(pchRet3, nRecv, SOCKS5_RECV_TIMEOUT, hSocket); break; } - default: CloseSocket(hSocket); return error("Error: malformed proxy response"); + default: return error("Error: malformed proxy response"); } if (recvr != IntrRecvError::OK) { - CloseSocket(hSocket); return error("Error reading from proxy"); } if ((recvr = InterruptibleRecv(pchRet3, 2, SOCKS5_RECV_TIMEOUT, hSocket)) != IntrRecvError::OK) { - CloseSocket(hSocket); return error("Error reading from proxy"); } LogPrint(BCLog::NET, "SOCKS5 connected %s\n", strDest); return true; } -bool ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRet, int nTimeout) +SOCKET CreateSocket(const CService &addrConnect) { - hSocketRet = INVALID_SOCKET; - struct sockaddr_storage sockaddr; socklen_t len = sizeof(sockaddr); if (!addrConnect.GetSockAddr((struct sockaddr*)&sockaddr, &len)) { - LogPrintf("Cannot connect to %s: unsupported network\n", addrConnect.ToString()); - return false; + LogPrintf("Cannot create socket for %s: unsupported network\n", addrConnect.ToString()); + return INVALID_SOCKET; } SOCKET hSocket = socket(((struct sockaddr*)&sockaddr)->sa_family, SOCK_STREAM, IPPROTO_TCP); if (hSocket == INVALID_SOCKET) - return false; + return INVALID_SOCKET; + + if (!IsSelectableSocket(hSocket)) { + CloseSocket(hSocket); + LogPrintf("Cannot create connection: non-selectable socket created (fd >= FD_SETSIZE ?)\n"); + return INVALID_SOCKET; + } #ifdef SO_NOSIGPIPE int set = 1; @@ -479,9 +463,23 @@ bool ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRet, int // Set to non-blocking if (!SetSocketNonBlocking(hSocket, true)) { CloseSocket(hSocket); - return error("ConnectSocketDirectly: Setting socket to non-blocking failed, error %s\n", NetworkErrorString(WSAGetLastError())); + LogPrintf("ConnectSocketDirectly: Setting socket to non-blocking failed, error %s\n", NetworkErrorString(WSAGetLastError())); } + return hSocket; +} +bool ConnectSocketDirectly(const CService &addrConnect, const SOCKET& hSocket, int nTimeout) +{ + struct sockaddr_storage sockaddr; + socklen_t len = sizeof(sockaddr); + if (hSocket == INVALID_SOCKET) { + LogPrintf("Cannot connect to %s: invalid socket\n", addrConnect.ToString()); + return false; + } + if (!addrConnect.GetSockAddr((struct sockaddr*)&sockaddr, &len)) { + LogPrintf("Cannot connect to %s: unsupported network\n", addrConnect.ToString()); + return false; + } if (connect(hSocket, (struct sockaddr*)&sockaddr, len) == SOCKET_ERROR) { int nErr = WSAGetLastError(); @@ -496,13 +494,11 @@ bool ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRet, int if (nRet == 0) { LogPrint(BCLog::NET, "connection to %s timeout\n", addrConnect.ToString()); - CloseSocket(hSocket); return false; } if (nRet == SOCKET_ERROR) { LogPrintf("select() for %s failed: %s\n", addrConnect.ToString(), NetworkErrorString(WSAGetLastError())); - CloseSocket(hSocket); return false; } socklen_t nRetSize = sizeof(nRet); @@ -513,13 +509,11 @@ bool ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRet, int #endif { LogPrintf("getsockopt() for %s failed: %s\n", addrConnect.ToString(), NetworkErrorString(WSAGetLastError())); - CloseSocket(hSocket); return false; } if (nRet != 0) { LogPrintf("connect() to %s failed after select(): %s\n", addrConnect.ToString(), NetworkErrorString(nRet)); - CloseSocket(hSocket); return false; } } @@ -530,12 +524,9 @@ bool ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRet, int #endif { LogPrintf("connect() to %s failed: %s\n", addrConnect.ToString(), NetworkErrorString(WSAGetLastError())); - CloseSocket(hSocket); return false; } } - - hSocketRet = hSocket; return true; } @@ -587,9 +578,8 @@ bool IsProxy(const CNetAddr &addr) { return false; } -bool ConnectThroughProxy(const proxyType &proxy, const std::string& strDest, int port, SOCKET& hSocketRet, int nTimeout, bool *outProxyConnectionFailed) +bool ConnectThroughProxy(const proxyType &proxy, const std::string& strDest, int port, const SOCKET& hSocket, int nTimeout, bool *outProxyConnectionFailed) { - SOCKET hSocket = INVALID_SOCKET; // first connect to proxy server if (!ConnectSocketDirectly(proxy.proxy, hSocket, nTimeout)) { if (outProxyConnectionFailed) @@ -601,14 +591,14 @@ bool ConnectThroughProxy(const proxyType &proxy, const std::string& strDest, int ProxyCredentials random_auth; static std::atomic_int counter(0); random_auth.username = random_auth.password = strprintf("%i", counter++); - if (!Socks5(strDest, (unsigned short)port, &random_auth, hSocket)) + if (!Socks5(strDest, (unsigned short)port, &random_auth, hSocket)) { return false; + } } else { - if (!Socks5(strDest, (unsigned short)port, 0, hSocket)) + if (!Socks5(strDest, (unsigned short)port, 0, hSocket)) { return false; + } } - - hSocketRet = hSocket; return true; } bool LookupSubNet(const char* pszName, CSubNet& ret) diff --git a/src/netbase.h b/src/netbase.h index 0a07be87b7..c0921b6441 100644 --- a/src/netbase.h +++ b/src/netbase.h @@ -1,4 +1,4 @@ -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -51,8 +51,9 @@ bool Lookup(const char *pszName, CService& addr, int portDefault, bool fAllowLoo bool Lookup(const char *pszName, std::vector<CService>& vAddr, int portDefault, bool fAllowLookup, unsigned int nMaxSolutions); CService LookupNumeric(const char *pszName, int portDefault = 0); bool LookupSubNet(const char *pszName, CSubNet& subnet); -bool ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRet, int nTimeout); -bool ConnectThroughProxy(const proxyType &proxy, const std::string& strDest, int port, SOCKET& hSocketRet, int nTimeout, bool *outProxyConnectionFailed); +SOCKET CreateSocket(const CService &addrConnect); +bool ConnectSocketDirectly(const CService &addrConnect, const SOCKET& hSocketRet, int nTimeout); +bool ConnectThroughProxy(const proxyType &proxy, const std::string& strDest, int port, const SOCKET& hSocketRet, int nTimeout, bool *outProxyConnectionFailed); /** Return readable error string for a network error code */ std::string NetworkErrorString(int err); /** Close socket and set hSocket to INVALID_SOCKET */ diff --git a/src/netmessagemaker.h b/src/netmessagemaker.h index ea7fccacb2..975be460b3 100644 --- a/src/netmessagemaker.h +++ b/src/netmessagemaker.h @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/noui.cpp b/src/noui.cpp index feb3464a56..efe6f28246 100644 --- a/src/noui.cpp +++ b/src/noui.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/policy/feerate.cpp b/src/policy/feerate.cpp index 26c44ee0cf..a560815491 100644 --- a/src/policy/feerate.cpp +++ b/src/policy/feerate.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/policy/feerate.h b/src/policy/feerate.h index 35b1b23786..eed77d5030 100644 --- a/src/policy/feerate.h +++ b/src/policy/feerate.h @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2015 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/policy/fees.cpp b/src/policy/fees.cpp index 013116318b..9142f3706d 100644 --- a/src/policy/fees.cpp +++ b/src/policy/fees.cpp @@ -1,15 +1,13 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 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 <policy/fees.h> #include <policy/policy.h> -#include <amount.h> #include <clientversion.h> #include <primitives/transaction.h> -#include <random.h> #include <streams.h> #include <txmempool.h> #include <util.h> @@ -413,15 +411,13 @@ void TxConfirmStats::Read(CAutoFile& filein, int nFileVersion, size_t numBuckets size_t maxConfirms, maxPeriods; // The current version will store the decay with each individual TxConfirmStats and also keep a scale factor - if (nFileVersion >= 149900) { - filein >> decay; - if (decay <= 0 || decay >= 1) { - throw std::runtime_error("Corrupt estimates file. Decay must be between 0 and 1 (non-inclusive)"); - } - filein >> scale; - if (scale == 0) { - throw std::runtime_error("Corrupt estimates file. Scale must be non-zero"); - } + filein >> decay; + if (decay <= 0 || decay >= 1) { + throw std::runtime_error("Corrupt estimates file. Decay must be between 0 and 1 (non-inclusive)"); + } + filein >> scale; + if (scale == 0) { + throw std::runtime_error("Corrupt estimates file. Scale must be non-zero"); } filein >> avg; @@ -445,20 +441,13 @@ void TxConfirmStats::Read(CAutoFile& filein, int nFileVersion, size_t numBuckets } } - if (nFileVersion >= 149900) { - filein >> failAvg; - if (maxPeriods != failAvg.size()) { - throw std::runtime_error("Corrupt estimates file. Mismatch in confirms tracked for failures"); - } - for (unsigned int i = 0; i < maxPeriods; i++) { - if (failAvg[i].size() != numBuckets) { - throw std::runtime_error("Corrupt estimates file. Mismatch in one of failure average bucket counts"); - } - } - } else { - failAvg.resize(confAvg.size()); - for (unsigned int i = 0; i < failAvg.size(); i++) { - failAvg[i].resize(numBuckets); + filein >> failAvg; + if (maxPeriods != failAvg.size()) { + throw std::runtime_error("Corrupt estimates file. Mismatch in confirms tracked for failures"); + } + for (unsigned int i = 0; i < maxPeriods; i++) { + if (failAvg[i].size() != numBuckets) { + throw std::runtime_error("Corrupt estimates file. Mismatch in one of failure average bucket counts"); } } @@ -565,7 +554,7 @@ void CBlockPolicyEstimator::processTransaction(const CTxMemPoolEntry& entry, boo if (mapMemPoolTxs.count(hash)) { LogPrint(BCLog::ESTIMATEFEE, "Blockpolicy error mempool tx %s already being tracked\n", hash.ToString().c_str()); - return; + return; } if (txHeight != nBestSeenHeight) { @@ -946,32 +935,9 @@ bool CBlockPolicyEstimator::Read(CAutoFile& filein) unsigned int nFileBestSeenHeight; filein >> nFileBestSeenHeight; - if (nVersionThatWrote < 149900) { - // Read the old fee estimates file for temporary use, but then discard. Will start collecting data from scratch. - // decay is stored before buckets in old versions, so pre-read decay and pass into TxConfirmStats constructor - double tempDecay; - filein >> tempDecay; - if (tempDecay <= 0 || tempDecay >= 1) - throw std::runtime_error("Corrupt estimates file. Decay must be between 0 and 1 (non-inclusive)"); - - std::vector<double> tempBuckets; - filein >> tempBuckets; - size_t tempNum = tempBuckets.size(); - if (tempNum <= 1 || tempNum > 1000) - throw std::runtime_error("Corrupt estimates file. Must have between 2 and 1000 feerate buckets"); - - std::map<double, unsigned int> tempMap; - - std::unique_ptr<TxConfirmStats> tempFeeStats(new TxConfirmStats(tempBuckets, tempMap, MED_BLOCK_PERIODS, tempDecay, 1)); - tempFeeStats->Read(filein, nVersionThatWrote, tempNum); - // if nVersionThatWrote < 139900 then another TxConfirmStats (for priority) follows but can be ignored. - - tempMap.clear(); - for (unsigned int i = 0; i < tempBuckets.size(); i++) { - tempMap[tempBuckets[i]] = i; - } - } - else { // nVersionThatWrote >= 149900 + if (nVersionRequired < 149900) { + LogPrintf("%s: incompatible old fee estimation data (non-fatal). Version: %d\n", __func__, nVersionRequired); + } else { // New format introduced in 149900 unsigned int nFileHistoricalFirst, nFileHistoricalBest; filein >> nFileHistoricalFirst >> nFileHistoricalBest; if (nFileHistoricalFirst > nFileHistoricalBest || nFileHistoricalBest > nFileBestSeenHeight) { diff --git a/src/policy/fees.h b/src/policy/fees.h index 6528560f52..96a842b7a1 100644 --- a/src/policy/fees.h +++ b/src/policy/fees.h @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 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_POLICYESTIMATOR_H diff --git a/src/policy/policy.cpp b/src/policy/policy.cpp index b69bed5d6f..bff58932b4 100644 --- a/src/policy/policy.cpp +++ b/src/policy/policy.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/policy/policy.h b/src/policy/policy.h index f3f8ebbbb4..3d96406bbc 100644 --- a/src/policy/policy.h +++ b/src/policy/policy.h @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -49,28 +49,28 @@ static const unsigned int DUST_RELAY_TX_FEE = 3000; * with. However scripts violating these flags may still be present in valid * blocks and we must accept those blocks. */ -static const unsigned int STANDARD_SCRIPT_VERIFY_FLAGS = MANDATORY_SCRIPT_VERIFY_FLAGS | - SCRIPT_VERIFY_DERSIG | - SCRIPT_VERIFY_STRICTENC | - SCRIPT_VERIFY_MINIMALDATA | - SCRIPT_VERIFY_NULLDUMMY | - SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS | - SCRIPT_VERIFY_CLEANSTACK | - SCRIPT_VERIFY_MINIMALIF | - SCRIPT_VERIFY_NULLFAIL | - SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY | - SCRIPT_VERIFY_CHECKSEQUENCEVERIFY | - SCRIPT_VERIFY_LOW_S | - SCRIPT_VERIFY_WITNESS | - SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM | - SCRIPT_VERIFY_WITNESS_PUBKEYTYPE; +static constexpr unsigned int STANDARD_SCRIPT_VERIFY_FLAGS = MANDATORY_SCRIPT_VERIFY_FLAGS | + SCRIPT_VERIFY_DERSIG | + SCRIPT_VERIFY_STRICTENC | + SCRIPT_VERIFY_MINIMALDATA | + 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 | + SCRIPT_VERIFY_WITNESS | + SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM | + SCRIPT_VERIFY_WITNESS_PUBKEYTYPE; /** For convenience, standard but not mandatory verify flags. */ -static const unsigned int STANDARD_NOT_MANDATORY_VERIFY_FLAGS = STANDARD_SCRIPT_VERIFY_FLAGS & ~MANDATORY_SCRIPT_VERIFY_FLAGS; +static constexpr unsigned int STANDARD_NOT_MANDATORY_VERIFY_FLAGS = STANDARD_SCRIPT_VERIFY_FLAGS & ~MANDATORY_SCRIPT_VERIFY_FLAGS; /** Used as the flags parameter to sequence and nLocktime checks in non-consensus code. */ -static const unsigned int STANDARD_LOCKTIME_VERIFY_FLAGS = LOCKTIME_VERIFY_SEQUENCE | - LOCKTIME_MEDIAN_TIME_PAST; +static constexpr unsigned int STANDARD_LOCKTIME_VERIFY_FLAGS = LOCKTIME_VERIFY_SEQUENCE | + LOCKTIME_MEDIAN_TIME_PAST; CAmount GetDustThreshold(const CTxOut& txout, const CFeeRate& dustRelayFee); diff --git a/src/policy/rbf.cpp b/src/policy/rbf.cpp index e9692d4b48..c5a1741608 100644 --- a/src/policy/rbf.cpp +++ b/src/policy/rbf.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2016 The Bitcoin Core developers +// Copyright (c) 2016-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/policy/rbf.h b/src/policy/rbf.h index 1a5218e120..72f51b0f03 100644 --- a/src/policy/rbf.h +++ b/src/policy/rbf.h @@ -1,4 +1,4 @@ -// Copyright (c) 2016 The Bitcoin Core developers +// Copyright (c) 2016-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/pow.cpp b/src/pow.cpp index cecb54ca7b..929ea26a02 100644 --- a/src/pow.cpp +++ b/src/pow.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/prevector.h b/src/prevector.h index eb29b3ae7e..f8d6a09145 100644 --- a/src/prevector.h +++ b/src/prevector.h @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2016 The Bitcoin Core developers +// Copyright (c) 2015-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/primitives/block.cpp b/src/primitives/block.cpp index 9e20565511..21f880bccb 100644 --- a/src/primitives/block.cpp +++ b/src/primitives/block.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/primitives/block.h b/src/primitives/block.h index 4957958c6a..612a9fa203 100644 --- a/src/primitives/block.h +++ b/src/primitives/block.h @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/primitives/transaction.cpp b/src/primitives/transaction.cpp index d8230d1423..6f463cabf5 100644 --- a/src/primitives/transaction.cpp +++ b/src/primitives/transaction.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/primitives/transaction.h b/src/primitives/transaction.h index 32f45e5748..cd348fdbe4 100644 --- a/src/primitives/transaction.h +++ b/src/primitives/transaction.h @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/protocol.cpp b/src/protocol.cpp index 8c34c4196e..c412ad9ffe 100644 --- a/src/protocol.cpp +++ b/src/protocol.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/protocol.h b/src/protocol.h index bc31434515..43d8ac067a 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -246,9 +246,8 @@ const std::vector<std::string> &getAllNetMessageTypes(); enum ServiceFlags : uint64_t { // Nothing NODE_NONE = 0, - // NODE_NETWORK means that the node is capable of serving the block chain. It is currently - // set by all Bitcoin Core nodes, and is unset by SPV clients or other peers that just want - // network services but don't provide them. + // NODE_NETWORK means that the node is capable of serving the complete block chain. It is currently + // set by all Bitcoin Core non pruned nodes, and is unset by SPV clients or other light clients. NODE_NETWORK = (1 << 0), // NODE_GETUTXO means the node is capable of responding to the getutxo protocol request. // Bitcoin Core does not support this but a patch set called Bitcoin XT does. @@ -264,6 +263,10 @@ enum ServiceFlags : uint64_t { // NODE_XTHIN means the node supports Xtreme Thinblocks // If this is turned off then the node will not service nor make xthin requests NODE_XTHIN = (1 << 4), + // NODE_NETWORK_LIMITED means the same as NODE_NETWORK with the limitation of only + // serving the last 288 (2 day) blocks + // See BIP159 for details on how this is implemented. + NODE_NETWORK_LIMITED = (1 << 10), // Bits 24-31 are reserved for temporary experiments. Just pick a bit that // isn't getting used, or one not being used much, and notify the @@ -288,7 +291,15 @@ enum ServiceFlags : uint64_t { * unless they set NODE_NETWORK_LIMITED and we are out of IBD, in which * case NODE_NETWORK_LIMITED suffices). * - * Thus, generally, avoid calling with peerServices == NODE_NONE. + * Thus, generally, avoid calling with peerServices == NODE_NONE, unless + * state-specific flags must absolutely be avoided. When called with + * peerServices == NODE_NONE, the returned desirable service flags are + * guaranteed to not change dependant on state - ie they are suitable for + * use when describing peers which we know to be desirable, but for which + * we do not have a confirmed set of service flags. + * + * If the NODE_NONE return value is changed, contrib/seeds/makeseeds.py + * should be updated appropriately to filter for the same nodes. */ static ServiceFlags GetDesirableServiceFlags(ServiceFlags services) { return ServiceFlags(NODE_NETWORK | NODE_WITNESS); diff --git a/src/pubkey.cpp b/src/pubkey.cpp index 7f5ec1e8de..6e601a6f13 100644 --- a/src/pubkey.cpp +++ b/src/pubkey.cpp @@ -1,4 +1,5 @@ -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers +// Copyright (c) 2017 The Zcash developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -46,7 +47,7 @@ static int ecdsa_signature_parse_der_lax(const secp256k1_context* ctx, secp256k1 lenbyte = input[pos++]; if (lenbyte & 0x80) { lenbyte -= 0x80; - if (pos + lenbyte > inputlen) { + if (lenbyte > inputlen - pos) { return 0; } pos += lenbyte; @@ -65,14 +66,15 @@ static int ecdsa_signature_parse_der_lax(const secp256k1_context* ctx, secp256k1 lenbyte = input[pos++]; if (lenbyte & 0x80) { lenbyte -= 0x80; - if (pos + lenbyte > inputlen) { + if (lenbyte > inputlen - pos) { return 0; } while (lenbyte > 0 && input[pos] == 0) { pos++; lenbyte--; } - if (lenbyte >= sizeof(size_t)) { + static_assert(sizeof(size_t) >= 4, "size_t too small"); + if (lenbyte >= 4) { return 0; } rlen = 0; @@ -103,14 +105,15 @@ static int ecdsa_signature_parse_der_lax(const secp256k1_context* ctx, secp256k1 lenbyte = input[pos++]; if (lenbyte & 0x80) { lenbyte -= 0x80; - if (pos + lenbyte > inputlen) { + if (lenbyte > inputlen - pos) { return 0; } while (lenbyte > 0 && input[pos] == 0) { pos++; lenbyte--; } - if (lenbyte >= sizeof(size_t)) { + static_assert(sizeof(size_t) >= 4, "size_t too small"); + if (lenbyte >= 4) { return 0; } slen = 0; @@ -181,7 +184,7 @@ bool CPubKey::Verify(const uint256 &hash, const std::vector<unsigned char>& vchS } bool CPubKey::RecoverCompact(const uint256 &hash, const std::vector<unsigned char>& vchSig) { - if (vchSig.size() != 65) + if (vchSig.size() != COMPACT_SIGNATURE_SIZE) return false; int recid = (vchSig[0] - 27) & 3; bool fComp = ((vchSig[0] - 27) & 4) != 0; @@ -193,8 +196,8 @@ bool CPubKey::RecoverCompact(const uint256 &hash, const std::vector<unsigned cha if (!secp256k1_ecdsa_recover(secp256k1_context_verify, &pubkey, &sig, hash.begin())) { return false; } - unsigned char pub[65]; - size_t publen = 65; + unsigned char pub[PUBLIC_KEY_SIZE]; + size_t publen = PUBLIC_KEY_SIZE; secp256k1_ec_pubkey_serialize(secp256k1_context_verify, pub, &publen, &pubkey, fComp ? SECP256K1_EC_COMPRESSED : SECP256K1_EC_UNCOMPRESSED); Set(pub, pub + publen); return true; @@ -214,8 +217,8 @@ bool CPubKey::Decompress() { if (!secp256k1_ec_pubkey_parse(secp256k1_context_verify, &pubkey, &(*this)[0], size())) { return false; } - unsigned char pub[65]; - size_t publen = 65; + unsigned char pub[PUBLIC_KEY_SIZE]; + size_t publen = PUBLIC_KEY_SIZE; secp256k1_ec_pubkey_serialize(secp256k1_context_verify, pub, &publen, &pubkey, SECP256K1_EC_UNCOMPRESSED); Set(pub, pub + publen); return true; @@ -224,7 +227,7 @@ bool CPubKey::Decompress() { bool CPubKey::Derive(CPubKey& pubkeyChild, ChainCode &ccChild, unsigned int nChild, const ChainCode& cc) const { assert(IsValid()); assert((nChild >> 31) == 0); - assert(begin() + 33 == end()); + assert(size() == COMPRESSED_PUBLIC_KEY_SIZE); unsigned char out[64]; BIP32Hash(cc, nChild, *begin(), begin()+1, out); memcpy(ccChild.begin(), out+32, 32); @@ -235,8 +238,8 @@ bool CPubKey::Derive(CPubKey& pubkeyChild, ChainCode &ccChild, unsigned int nChi if (!secp256k1_ec_pubkey_tweak_add(secp256k1_context_verify, &pubkey, out)) { return false; } - unsigned char pub[33]; - size_t publen = 33; + unsigned char pub[COMPRESSED_PUBLIC_KEY_SIZE]; + size_t publen = COMPRESSED_PUBLIC_KEY_SIZE; secp256k1_ec_pubkey_serialize(secp256k1_context_verify, pub, &publen, &pubkey, SECP256K1_EC_COMPRESSED); pubkeyChild.Set(pub, pub + publen); return true; @@ -248,8 +251,8 @@ void CExtPubKey::Encode(unsigned char code[BIP32_EXTKEY_SIZE]) const { code[5] = (nChild >> 24) & 0xFF; code[6] = (nChild >> 16) & 0xFF; code[7] = (nChild >> 8) & 0xFF; code[8] = (nChild >> 0) & 0xFF; memcpy(code+9, chaincode.begin(), 32); - assert(pubkey.size() == 33); - memcpy(code+41, pubkey.begin(), 33); + assert(pubkey.size() == CPubKey::COMPRESSED_PUBLIC_KEY_SIZE); + memcpy(code+41, pubkey.begin(), CPubKey::COMPRESSED_PUBLIC_KEY_SIZE); } void CExtPubKey::Decode(const unsigned char code[BIP32_EXTKEY_SIZE]) { diff --git a/src/pubkey.h b/src/pubkey.h index c9f3c18eb3..59bf56395c 100644 --- a/src/pubkey.h +++ b/src/pubkey.h @@ -1,5 +1,6 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers +// Copyright (c) 2017 The Zcash developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -13,16 +14,6 @@ #include <stdexcept> #include <vector> -/** - * secp256k1: - * const unsigned int PRIVATE_KEY_SIZE = 279; - * const unsigned int PUBLIC_KEY_SIZE = 65; - * const unsigned int SIGNATURE_SIZE = 72; - * - * see www.keylength.com - * script supports up to 75 for single byte push - */ - const unsigned int BIP32_EXTKEY_SIZE = 74; /** A reference to a CKey: the Hash160 of its serialized public key */ @@ -38,21 +29,37 @@ typedef uint256 ChainCode; /** An encapsulated public key. */ class CPubKey { +public: + /** + * secp256k1: + */ + static const unsigned int PUBLIC_KEY_SIZE = 65; + static const unsigned int COMPRESSED_PUBLIC_KEY_SIZE = 33; + static const unsigned int SIGNATURE_SIZE = 72; + static const unsigned int COMPACT_SIGNATURE_SIZE = 65; + /** + * see www.keylength.com + * script supports up to 75 for single byte push + */ + static_assert( + PUBLIC_KEY_SIZE >= COMPRESSED_PUBLIC_KEY_SIZE, + "COMPRESSED_PUBLIC_KEY_SIZE is larger than PUBLIC_KEY_SIZE"); + private: /** * Just store the serialized data. * Its length can very cheaply be computed from the first byte. */ - unsigned char vch[65]; + unsigned char vch[PUBLIC_KEY_SIZE]; //! Compute the length of a pubkey with a given first byte. unsigned int static GetLen(unsigned char chHeader) { if (chHeader == 2 || chHeader == 3) - return 33; + return COMPRESSED_PUBLIC_KEY_SIZE; if (chHeader == 4 || chHeader == 6 || chHeader == 7) - return 65; + return PUBLIC_KEY_SIZE; return 0; } @@ -127,7 +134,7 @@ public: void Unserialize(Stream& s) { unsigned int len = ::ReadCompactSize(s); - if (len <= 65) { + if (len <= PUBLIC_KEY_SIZE) { s.read((char*)vch, len); } else { // invalid pubkey, skip available data @@ -166,7 +173,7 @@ public: //! Check whether this is a compressed public key. bool IsCompressed() const { - return size() == 33; + return size() == COMPRESSED_PUBLIC_KEY_SIZE; } /** diff --git a/src/qt/addressbookpage.cpp b/src/qt/addressbookpage.cpp index dda8dce391..517aa49e2b 100644 --- a/src/qt/addressbookpage.cpp +++ b/src/qt/addressbookpage.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/addressbookpage.h b/src/qt/addressbookpage.h index 3c00fd0809..54a43478d1 100644 --- a/src/qt/addressbookpage.h +++ b/src/qt/addressbookpage.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/addresstablemodel.cpp b/src/qt/addresstablemodel.cpp index 1d16940acb..74f0db3520 100644 --- a/src/qt/addresstablemodel.cpp +++ b/src/qt/addresstablemodel.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -341,7 +341,7 @@ void AddressTableModel::updateEntry(const QString &address, priv->updateEntry(address, label, isMine, purpose, status); } -QString AddressTableModel::addRow(const QString &type, const QString &label, const QString &address) +QString AddressTableModel::addRow(const QString &type, const QString &label, const QString &address, const OutputType address_type) { std::string strLabel = label.toStdString(); std::string strAddress = address.toStdString(); @@ -384,7 +384,8 @@ QString AddressTableModel::addRow(const QString &type, const QString &label, con return QString(); } } - strAddress = EncodeDestination(newKey.GetID()); + wallet->LearnRelatedScripts(newKey, address_type); + strAddress = EncodeDestination(GetDestinationForKey(newKey, address_type)); } else { diff --git a/src/qt/addresstablemodel.h b/src/qt/addresstablemodel.h index d04b95ebae..11439e25d5 100644 --- a/src/qt/addresstablemodel.h +++ b/src/qt/addresstablemodel.h @@ -8,6 +8,8 @@ #include <QAbstractTableModel> #include <QStringList> +enum OutputType : int; + class AddressTablePriv; class WalletModel; @@ -61,7 +63,7 @@ public: /* Add an address to the model. Returns the added address on success, and an empty string otherwise. */ - QString addRow(const QString &type, const QString &label, const QString &address); + QString addRow(const QString &type, const QString &label, const QString &address, const OutputType address_type); /* Look up label for address in address book, if not found return empty string. */ diff --git a/src/qt/askpassphrasedialog.cpp b/src/qt/askpassphrasedialog.cpp index a720ac956b..0270af98b7 100644 --- a/src/qt/askpassphrasedialog.cpp +++ b/src/qt/askpassphrasedialog.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/askpassphrasedialog.h b/src/qt/askpassphrasedialog.h index 7c6acc4650..7ec8bf0a15 100644 --- a/src/qt/askpassphrasedialog.h +++ b/src/qt/askpassphrasedialog.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/bantablemodel.cpp b/src/qt/bantablemodel.cpp index 84807da65d..c89c90e118 100644 --- a/src/qt/bantablemodel.cpp +++ b/src/qt/bantablemodel.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -55,11 +55,11 @@ public: #if QT_VERSION >= 0x040700 cachedBanlist.reserve(banMap.size()); #endif - for (banmap_t::iterator it = banMap.begin(); it != banMap.end(); it++) + for (const auto& entry : banMap) { CCombinedBan banEntry; - banEntry.subnet = (*it).first; - banEntry.banEntry = (*it).second; + banEntry.subnet = entry.first; + banEntry.banEntry = entry.second; cachedBanlist.append(banEntry); } diff --git a/src/qt/bantablemodel.h b/src/qt/bantablemodel.h index dc69dee20a..a54f8793d0 100644 --- a/src/qt/bantablemodel.h +++ b/src/qt/bantablemodel.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp index 557d7efcec..0666dcb9a3 100644 --- a/src/qt/bitcoin.cpp +++ b/src/qt/bitcoin.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/bitcoinaddressvalidator.cpp b/src/qt/bitcoinaddressvalidator.cpp index e8d174bf29..395ab447d2 100644 --- a/src/qt/bitcoinaddressvalidator.cpp +++ b/src/qt/bitcoinaddressvalidator.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2014 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/bitcoinamountfield.cpp b/src/qt/bitcoinamountfield.cpp index 0b21349c54..e8307ff125 100644 --- a/src/qt/bitcoinamountfield.cpp +++ b/src/qt/bitcoinamountfield.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/bitcoinamountfield.h b/src/qt/bitcoinamountfield.h index 659ecb416b..8e2cceeb5e 100644 --- a/src/qt/bitcoinamountfield.h +++ b/src/qt/bitcoinamountfield.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index cd3234c564..afd90a3bc6 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -1,11 +1,7 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 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 defined(HAVE_CONFIG_H) -#include <config/bitcoin-config.h> -#endif - #include <qt/bitcoingui.h> #include <qt/bitcoinunits.h> @@ -1210,7 +1206,7 @@ UnitDisplayStatusBarControl::UnitDisplayStatusBarControl(const PlatformStyle *pl const QFontMetrics fm(font()); for (const BitcoinUnits::Unit unit : units) { - max_width = qMax(max_width, fm.width(BitcoinUnits::name(unit))); + max_width = qMax(max_width, fm.width(BitcoinUnits::longName(unit))); } setMinimumSize(max_width, 0); setAlignment(Qt::AlignRight | Qt::AlignVCenter); @@ -1229,7 +1225,7 @@ void UnitDisplayStatusBarControl::createContextMenu() menu = new QMenu(this); for (BitcoinUnits::Unit u : BitcoinUnits::availableUnits()) { - QAction *menuAction = new QAction(QString(BitcoinUnits::name(u)), this); + QAction *menuAction = new QAction(QString(BitcoinUnits::longName(u)), this); menuAction->setData(QVariant(u)); menu->addAction(menuAction); } @@ -1254,7 +1250,7 @@ void UnitDisplayStatusBarControl::setOptionsModel(OptionsModel *_optionsModel) /** When Display Units are changed on OptionsModel it will refresh the display text of the control on the status bar */ void UnitDisplayStatusBarControl::updateDisplayUnit(int newUnits) { - setText(BitcoinUnits::name(newUnits)); + setText(BitcoinUnits::longName(newUnits)); } /** Shows context menu with Display Unit options by the mouse coordinates */ diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h index 1647975fec..ddb7ecb76a 100644 --- a/src/qt/bitcoingui.h +++ b/src/qt/bitcoingui.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/bitcoinstrings.cpp b/src/qt/bitcoinstrings.cpp index 9f798ccf62..adf001c968 100644 --- a/src/qt/bitcoinstrings.cpp +++ b/src/qt/bitcoinstrings.cpp @@ -24,6 +24,9 @@ QT_TRANSLATE_NOOP("bitcoin-core", "" "Accept relayed transactions received from whitelisted peers even when not " "relaying transactions (default: %d)"), QT_TRANSLATE_NOOP("bitcoin-core", "" +"Add a node to connect to and attempt to keep the connection open (see the " +"`addnode` RPC command help for more info)"), +QT_TRANSLATE_NOOP("bitcoin-core", "" "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"), @@ -42,8 +45,11 @@ QT_TRANSLATE_NOOP("bitcoin-core", "" QT_TRANSLATE_NOOP("bitcoin-core", "" "Cannot obtain a lock on data directory %s. %s is probably already running."), QT_TRANSLATE_NOOP("bitcoin-core", "" +"Cannot provide specific connections and have addrman find outgoing " +"connections at the same."), +QT_TRANSLATE_NOOP("bitcoin-core", "" "Connect only to the specified node(s); -connect=0 disables automatic " -"connections"), +"connections (the rules for this peer are the same as for -addnode)"), QT_TRANSLATE_NOOP("bitcoin-core", "" "Create new files with system default permissions, instead of umask 077 (only " "effective with disabled wallet functionality)"), @@ -160,12 +166,20 @@ QT_TRANSLATE_NOOP("bitcoin-core", "" "Set lowest fee rate (in %s/kB) for transactions to be included in block " "creation. (default: %s)"), QT_TRANSLATE_NOOP("bitcoin-core", "" +"Set maximum BIP141 block weight to this * 4. Deprecated, use blockmaxweight"), +QT_TRANSLATE_NOOP("bitcoin-core", "" "Set the number of script verification threads (%u to %d, 0 = auto, <0 = " "leave that many cores free, default: %d)"), QT_TRANSLATE_NOOP("bitcoin-core", "" "Sets the serialization of raw transaction or block hex returned in non-" "verbose mode, non-segwit(0) or segwit(1) (default: %d)"), QT_TRANSLATE_NOOP("bitcoin-core", "" +"Specify directory to hold wallets (default: <datadir>/wallets if it exists, " +"otherwise <datadir>)"), +QT_TRANSLATE_NOOP("bitcoin-core", "" +"Specify location of debug log file: this can be an absolute path or a path " +"relative to the data directory (default: %s)"), +QT_TRANSLATE_NOOP("bitcoin-core", "" "Support filtering of blocks and transaction with bloom filters (default: %u)"), QT_TRANSLATE_NOOP("bitcoin-core", "" "The block database contains a block which appears to be from the future. " @@ -212,9 +226,6 @@ QT_TRANSLATE_NOOP("bitcoin-core", "" QT_TRANSLATE_NOOP("bitcoin-core", "" "Use UPnP to map the listening port (default: 1 when listening and no -proxy)"), QT_TRANSLATE_NOOP("bitcoin-core", "" -"Use hierarchical deterministic key generation (HD) after BIP32. Only has " -"effect during wallet creation/first start"), -QT_TRANSLATE_NOOP("bitcoin-core", "" "Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: " "%s)"), QT_TRANSLATE_NOOP("bitcoin-core", "" @@ -250,20 +261,16 @@ QT_TRANSLATE_NOOP("bitcoin-core", "" QT_TRANSLATE_NOOP("bitcoin-core", "" "You need to rebuild the database using -reindex to go back to unpruned " "mode. This will redownload the entire blockchain"), -QT_TRANSLATE_NOOP("bitcoin-core", "" -"You need to rebuild the database using -reindex-chainstate to change -txindex"), QT_TRANSLATE_NOOP("bitcoin-core", "%d of last 100 blocks have unexpected version"), QT_TRANSLATE_NOOP("bitcoin-core", "%s corrupt, salvage failed"), QT_TRANSLATE_NOOP("bitcoin-core", "%s is set very high!"), QT_TRANSLATE_NOOP("bitcoin-core", "(default: %s)"), QT_TRANSLATE_NOOP("bitcoin-core", "(default: %u)"), -QT_TRANSLATE_NOOP("bitcoin-core", "(press q to shutdown and continue later)"), QT_TRANSLATE_NOOP("bitcoin-core", "-maxmempool must be at least %d MB"), QT_TRANSLATE_NOOP("bitcoin-core", "<category> can be:"), QT_TRANSLATE_NOOP("bitcoin-core", "Accept command line and JSON-RPC commands"), QT_TRANSLATE_NOOP("bitcoin-core", "Accept connections from outside (default: 1 if no -proxy or -connect)"), QT_TRANSLATE_NOOP("bitcoin-core", "Accept public REST requests (default: %u)"), -QT_TRANSLATE_NOOP("bitcoin-core", "Add a node to connect to and attempt to keep the connection open"), QT_TRANSLATE_NOOP("bitcoin-core", "Allow DNS lookups for -addnode, -seednode and -connect"), QT_TRANSLATE_NOOP("bitcoin-core", "Always query for peer addresses via DNS lookup (default: %u)"), QT_TRANSLATE_NOOP("bitcoin-core", "Append comment to the user agent string"), @@ -272,7 +279,6 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Automatically create Tor hidden service (defa QT_TRANSLATE_NOOP("bitcoin-core", "Block creation options:"), QT_TRANSLATE_NOOP("bitcoin-core", "Cannot downgrade wallet"), QT_TRANSLATE_NOOP("bitcoin-core", "Cannot resolve -%s address: '%s'"), -QT_TRANSLATE_NOOP("bitcoin-core", "Cannot write default address"), QT_TRANSLATE_NOOP("bitcoin-core", "Chain selection options:"), QT_TRANSLATE_NOOP("bitcoin-core", "Change index out of range"), QT_TRANSLATE_NOOP("bitcoin-core", "Connect through SOCKS5 proxy"), @@ -289,6 +295,7 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Enable publish hash transaction in <address>" QT_TRANSLATE_NOOP("bitcoin-core", "Enable publish raw block in <address>"), QT_TRANSLATE_NOOP("bitcoin-core", "Enable publish raw transaction in <address>"), QT_TRANSLATE_NOOP("bitcoin-core", "Enable transaction replacement in the memory pool (default: %u)"), +QT_TRANSLATE_NOOP("bitcoin-core", "Error creating %s: You can't create non-HD wallets with this version."), QT_TRANSLATE_NOOP("bitcoin-core", "Error initializing block database"), QT_TRANSLATE_NOOP("bitcoin-core", "Error initializing wallet database environment %s!"), QT_TRANSLATE_NOOP("bitcoin-core", "Error loading %s"), @@ -306,6 +313,7 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Error"), QT_TRANSLATE_NOOP("bitcoin-core", "Error: A fatal internal error occurred, see debug.log for details"), QT_TRANSLATE_NOOP("bitcoin-core", "Error: Disk space is low!"), QT_TRANSLATE_NOOP("bitcoin-core", "Failed to listen on any port. Use -listen=0 if you want this."), +QT_TRANSLATE_NOOP("bitcoin-core", "Failed to rescan the wallet during initialization"), QT_TRANSLATE_NOOP("bitcoin-core", "Fee (in %s/kB) to add to transactions you send (default: %s)"), QT_TRANSLATE_NOOP("bitcoin-core", "How many blocks to check at startup (default: %u, 0 = all)"), QT_TRANSLATE_NOOP("bitcoin-core", "Importing..."), @@ -360,15 +368,17 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Rescanning..."), QT_TRANSLATE_NOOP("bitcoin-core", "Rewinding blocks..."), QT_TRANSLATE_NOOP("bitcoin-core", "Run in the background as a daemon and accept commands"), QT_TRANSLATE_NOOP("bitcoin-core", "Send trace/debug info to console instead of debug.log file"), -QT_TRANSLATE_NOOP("bitcoin-core", "Send transactions with full-RBF opt-in enabled (default: %u)"), +QT_TRANSLATE_NOOP("bitcoin-core", "Send transactions with full-RBF opt-in enabled (RPC only, default: %u)"), QT_TRANSLATE_NOOP("bitcoin-core", "Set database cache size in megabytes (%d to %d, default: %d)"), QT_TRANSLATE_NOOP("bitcoin-core", "Set key pool size to <n> (default: %u)"), QT_TRANSLATE_NOOP("bitcoin-core", "Set maximum BIP141 block weight (default: %d)"), -QT_TRANSLATE_NOOP("bitcoin-core", "Set maximum block size in bytes (default: %d)"), QT_TRANSLATE_NOOP("bitcoin-core", "Set the number of threads to service RPC calls (default: %d)"), QT_TRANSLATE_NOOP("bitcoin-core", "Show all debugging options (usage: --help -help-debug)"), QT_TRANSLATE_NOOP("bitcoin-core", "Shrink debug.log file on client startup (default: 1 when no -debug)"), QT_TRANSLATE_NOOP("bitcoin-core", "Signing transaction failed"), +QT_TRANSLATE_NOOP("bitcoin-core", "Specified -walletdir \"%s\" does not exist"), +QT_TRANSLATE_NOOP("bitcoin-core", "Specified -walletdir \"%s\" is a relative path"), +QT_TRANSLATE_NOOP("bitcoin-core", "Specified -walletdir \"%s\" is not a directory"), QT_TRANSLATE_NOOP("bitcoin-core", "Specify configuration file (default: %s)"), QT_TRANSLATE_NOOP("bitcoin-core", "Specify connection timeout in milliseconds (minimum: 1, default: %d)"), QT_TRANSLATE_NOOP("bitcoin-core", "Specify data directory"), @@ -395,6 +405,7 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Transaction too large for fee policy"), QT_TRANSLATE_NOOP("bitcoin-core", "Transaction too large"), QT_TRANSLATE_NOOP("bitcoin-core", "Unable to bind to %s on this computer (bind returned error %s)"), QT_TRANSLATE_NOOP("bitcoin-core", "Unable to bind to %s on this computer. %s is probably already running."), +QT_TRANSLATE_NOOP("bitcoin-core", "Unable to generate initial keys"), QT_TRANSLATE_NOOP("bitcoin-core", "Unable to start HTTP server. See debug log for details."), QT_TRANSLATE_NOOP("bitcoin-core", "Unknown network specified in -onlynet: '%s'"), QT_TRANSLATE_NOOP("bitcoin-core", "Unsupported argument -benchmark ignored, use -debug=bench."), @@ -409,13 +420,14 @@ QT_TRANSLATE_NOOP("bitcoin-core", "User Agent comment (%s) contains unsafe chara QT_TRANSLATE_NOOP("bitcoin-core", "Username for JSON-RPC connections"), QT_TRANSLATE_NOOP("bitcoin-core", "Verifying blocks..."), QT_TRANSLATE_NOOP("bitcoin-core", "Verifying wallet(s)..."), -QT_TRANSLATE_NOOP("bitcoin-core", "Wallet %s resides outside data directory %s"), +QT_TRANSLATE_NOOP("bitcoin-core", "Wallet %s resides outside wallet directory %s"), QT_TRANSLATE_NOOP("bitcoin-core", "Wallet debugging/testing options:"), QT_TRANSLATE_NOOP("bitcoin-core", "Wallet needed to be rewritten: restart %s to complete"), QT_TRANSLATE_NOOP("bitcoin-core", "Wallet options:"), QT_TRANSLATE_NOOP("bitcoin-core", "Warning"), QT_TRANSLATE_NOOP("bitcoin-core", "Warning: unknown new rules activated (versionbit %i)"), QT_TRANSLATE_NOOP("bitcoin-core", "Whether to operate in a blocks only mode (default: %u)"), +QT_TRANSLATE_NOOP("bitcoin-core", "You need to rebuild the database using -reindex to change -txindex"), QT_TRANSLATE_NOOP("bitcoin-core", "Zapping all transactions from wallet..."), QT_TRANSLATE_NOOP("bitcoin-core", "ZeroMQ notification options:"), }; diff --git a/src/qt/bitcoinunits.cpp b/src/qt/bitcoinunits.cpp index c8614fdfe0..9df05d2a13 100644 --- a/src/qt/bitcoinunits.cpp +++ b/src/qt/bitcoinunits.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -36,24 +36,33 @@ bool BitcoinUnits::valid(int unit) } } -QString BitcoinUnits::name(int unit) +QString BitcoinUnits::longName(int unit) { switch(unit) { case BTC: return QString("BTC"); case mBTC: return QString("mBTC"); - case uBTC: return QString::fromUtf8("μBTC"); + case uBTC: return QString::fromUtf8("µBTC (bits)"); default: return QString("???"); } } +QString BitcoinUnits::shortName(int unit) +{ + switch(unit) + { + case uBTC: return QString::fromUtf8("bits"); + default: return longName(unit); + } +} + QString BitcoinUnits::description(int unit) { switch(unit) { case BTC: return QString("Bitcoins"); case mBTC: return QString("Milli-Bitcoins (1 / 1" THIN_SP_UTF8 "000)"); - case uBTC: return QString("Micro-Bitcoins (1 / 1" THIN_SP_UTF8 "000" THIN_SP_UTF8 "000)"); + case uBTC: return QString("Micro-Bitcoins (bits) (1 / 1" THIN_SP_UTF8 "000" THIN_SP_UTF8 "000)"); default: return QString("???"); } } @@ -121,7 +130,7 @@ QString BitcoinUnits::format(int unit, const CAmount& nIn, bool fPlus, Separator QString BitcoinUnits::formatWithUnit(int unit, const CAmount& amount, bool plussign, SeparatorStyle separators) { - return format(unit, amount, plussign, separators) + QString(" ") + name(unit); + return format(unit, amount, plussign, separators) + QString(" ") + shortName(unit); } QString BitcoinUnits::formatHtmlWithUnit(int unit, const CAmount& amount, bool plussign, SeparatorStyle separators) @@ -176,7 +185,7 @@ QString BitcoinUnits::getAmountColumnTitle(int unit) QString amountTitle = QObject::tr("Amount"); if (BitcoinUnits::valid(unit)) { - amountTitle += " ("+BitcoinUnits::name(unit) + ")"; + amountTitle += " ("+BitcoinUnits::shortName(unit) + ")"; } return amountTitle; } @@ -197,7 +206,7 @@ QVariant BitcoinUnits::data(const QModelIndex &index, int role) const { case Qt::EditRole: case Qt::DisplayRole: - return QVariant(name(unit)); + return QVariant(longName(unit)); case Qt::ToolTipRole: return QVariant(description(unit)); case UnitRole: diff --git a/src/qt/bitcoinunits.h b/src/qt/bitcoinunits.h index 3f5a7fd32d..310f651815 100644 --- a/src/qt/bitcoinunits.h +++ b/src/qt/bitcoinunits.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -76,8 +76,10 @@ public: static QList<Unit> availableUnits(); //! Is unit ID valid? static bool valid(int unit); + //! Long name + static QString longName(int unit); //! Short name - static QString name(int unit); + static QString shortName(int unit); //! Longer description static QString description(int unit); //! Number of Satoshis (1e-8) per unit diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index 78174b90a1..3642e5d4d4 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/clientmodel.h b/src/qt/clientmodel.h index 6447cae1bb..99ec2365a9 100644 --- a/src/qt/clientmodel.h +++ b/src/qt/clientmodel.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp index 03e633e375..ea4d6a4816 100644 --- a/src/qt/coincontroldialog.cpp +++ b/src/qt/coincontroldialog.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -28,9 +28,7 @@ #include <QFlags> #include <QIcon> #include <QSettings> -#include <QString> #include <QTreeWidget> -#include <QTreeWidgetItem> QList<CAmount> CoinControlDialog::payAmounts; CCoinControl* CoinControlDialog::coinControl = new CCoinControl(); diff --git a/src/qt/coincontroldialog.h b/src/qt/coincontroldialog.h index 51b0a42907..355ed5f553 100644 --- a/src/qt/coincontroldialog.h +++ b/src/qt/coincontroldialog.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/coincontroltreewidget.cpp b/src/qt/coincontroltreewidget.cpp index b628824793..82db28d586 100644 --- a/src/qt/coincontroltreewidget.cpp +++ b/src/qt/coincontroltreewidget.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/csvmodelwriter.cpp b/src/qt/csvmodelwriter.cpp index 702757147b..672226ca11 100644 --- a/src/qt/csvmodelwriter.cpp +++ b/src/qt/csvmodelwriter.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/editaddressdialog.cpp b/src/qt/editaddressdialog.cpp index 0437f81a7e..a945fc6aa0 100644 --- a/src/qt/editaddressdialog.cpp +++ b/src/qt/editaddressdialog.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -11,6 +11,8 @@ #include <QDataWidgetMapper> #include <QMessageBox> +extern OutputType g_address_type; + EditAddressDialog::EditAddressDialog(Mode _mode, QWidget *parent) : QDialog(parent), ui(new Ui::EditAddressDialog), @@ -77,7 +79,8 @@ bool EditAddressDialog::saveCurrentRow() address = model->addRow( mode == NewSendingAddress ? AddressTableModel::Send : AddressTableModel::Receive, ui->labelEdit->text(), - ui->addressEdit->text()); + ui->addressEdit->text(), + g_address_type); break; case EditReceivingAddress: case EditSendingAddress: diff --git a/src/qt/forms/receivecoinsdialog.ui b/src/qt/forms/receivecoinsdialog.ui index 58f030ebf0..09fb435a58 100644 --- a/src/qt/forms/receivecoinsdialog.ui +++ b/src/qt/forms/receivecoinsdialog.ui @@ -7,7 +7,7 @@ <x>0</x> <y>0</y> <width>776</width> - <height>364</height> + <height>396</height> </rect> </property> <layout class="QVBoxLayout" name="verticalLayout" stretch="0,0,1"> @@ -28,6 +28,22 @@ <layout class="QVBoxLayout" name="verticalLayout_3"> <item> <layout class="QGridLayout" name="gridLayout"> + <item row="5" column="0"> + <widget class="QLabel" name="label"> + <property name="toolTip"> + <string>An optional amount to request. Leave this empty or zero to not request a specific amount.</string> + </property> + <property name="text"> + <string>&Amount:</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + <property name="buddy"> + <cstring>reqAmount</cstring> + </property> + </widget> + </item> <item row="6" column="0"> <widget class="QLabel" name="label_3"> <property name="toolTip"> @@ -51,13 +67,6 @@ </property> </widget> </item> - <item row="6" column="2"> - <widget class="QLineEdit" name="reqMessage"> - <property name="toolTip"> - <string>An optional message to attach to the payment request, which will be displayed when the request is opened. Note: The message will not be sent with the payment over the Bitcoin network.</string> - </property> - </widget> - </item> <item row="2" column="2"> <widget class="QLabel" name="label_5"> <property name="text"> @@ -81,32 +90,10 @@ </property> </widget> </item> - <item row="5" column="0"> - <widget class="QLabel" name="label"> - <property name="toolTip"> - <string>An optional amount to request. Leave this empty or zero to not request a specific amount.</string> - </property> - <property name="text"> - <string>&Amount:</string> - </property> - <property name="alignment"> - <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> - </property> - <property name="buddy"> - <cstring>reqAmount</cstring> - </property> - </widget> - </item> - <item row="5" column="2"> - <widget class="BitcoinAmountField" name="reqAmount"> - <property name="minimumSize"> - <size> - <width>80</width> - <height>0</height> - </size> - </property> + <item row="6" column="2"> + <widget class="QLineEdit" name="reqMessage"> <property name="toolTip"> - <string>An optional amount to request. Leave this empty or zero to not request a specific amount.</string> + <string>An optional message to attach to the payment request, which will be displayed when the request is opened. Note: The message will not be sent with the payment over the Bitcoin network.</string> </property> </widget> </item> @@ -174,6 +161,73 @@ </property> </widget> </item> + <item row="5" column="2"> + <layout class="QHBoxLayout" name="horizontalLayout_6"> + <item> + <widget class="BitcoinAmountField" name="reqAmount"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>80</width> + <height>0</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>1000</width> + <height>100</height> + </size> + </property> + <property name="toolTip"> + <string>An optional amount to request. Leave this empty or zero to not request a specific amount.</string> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="useBech32"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maximumSize"> + <size> + <width>1000</width> + <height>16777215</height> + </size> + </property> + <property name="focusPolicy"> + <enum>Qt::StrongFocus</enum> + </property> + <property name="toolTip"> + <string>Bech32 addresses (BIP-173) are cheaper to spend from and offer better protection against typos. When unchecked a P2SH wrapped SegWit address will be created, compatible with older wallets.</string> + </property> + <property name="text"> + <string>Generate Bech32 address</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_3"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>0</width> + <height>0</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> </layout> </item> </layout> @@ -306,6 +360,7 @@ <tabstops> <tabstop>reqLabel</tabstop> <tabstop>reqAmount</tabstop> + <tabstop>useBech32</tabstop> <tabstop>reqMessage</tabstop> <tabstop>receiveButton</tabstop> <tabstop>clearButton</tabstop> diff --git a/src/qt/forms/sendcoinsdialog.ui b/src/qt/forms/sendcoinsdialog.ui index 9c89741afe..195a5560f7 100644 --- a/src/qt/forms/sendcoinsdialog.ui +++ b/src/qt/forms/sendcoinsdialog.ui @@ -1108,10 +1108,10 @@ <item> <widget class="QCheckBox" name="optInRBF"> <property name="text"> - <string>Request Replace-By-Fee</string> + <string>Enable Replace-By-Fee</string> </property> <property name="toolTip"> - <string>Indicates that the sender may wish to replace this transaction with a new one paying higher fees (prior to being confirmed).</string> + <string>With Replace-By-Fee (BIP-125) you can increase a transaction's fee after it is sent. Without this, a higher fee may be recommended to compensate for increased transaction delay risk.</string> </property> </widget> </item> diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp index 80ee35a341..558d4f108c 100644 --- a/src/qt/guiutil.cpp +++ b/src/qt/guiutil.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -9,7 +9,6 @@ #include <qt/qvalidatedlineedit.h> #include <qt/walletmodel.h> -#include <fs.h> #include <primitives/transaction.h> #include <init.h> #include <policy/policy.h> @@ -996,6 +995,18 @@ QString formatBytes(uint64_t bytes) return QString(QObject::tr("%1 GB")).arg(bytes / 1024 / 1024 / 1024); } +qreal calculateIdealFontSize(int width, const QString& text, QFont font, qreal minPointSize, qreal font_size) { + while(font_size >= minPointSize) { + font.setPointSizeF(font_size); + QFontMetrics fm(font); + if (fm.width(text) < width) { + break; + } + font_size -= 0.5; + } + return font_size; +} + void ClickableLabel::mouseReleaseEvent(QMouseEvent *event) { Q_EMIT clicked(event->pos()); diff --git a/src/qt/guiutil.h b/src/qt/guiutil.h index d0ab491952..71a69483f5 100644 --- a/src/qt/guiutil.h +++ b/src/qt/guiutil.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -201,6 +201,8 @@ namespace GUIUtil QString formatBytes(uint64_t bytes); + qreal calculateIdealFontSize(int width, const QString& text, QFont font, qreal minPointSize = 4, qreal startPointSize = 14); + class ClickableLabel : public QLabel { Q_OBJECT diff --git a/src/qt/intro.cpp b/src/qt/intro.cpp index 9e4c765101..e69f196238 100644 --- a/src/qt/intro.cpp +++ b/src/qt/intro.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -22,7 +22,7 @@ static const uint64_t GB_BYTES = 1000000000LL; /* Minimum free space (in GB) needed for data directory */ -static const uint64_t BLOCK_CHAIN_SIZE = 150; +static const uint64_t BLOCK_CHAIN_SIZE = 200; /* Minimum free space (in GB) needed for data directory when pruned; Does not include prune target */ static const uint64_t CHAIN_STATE_SIZE = 3; /* Total required space (in GB) depending on user choice (prune, not prune) */ @@ -214,7 +214,10 @@ bool Intro::pickDataDirectory() } dataDir = intro.getDataDirectory(); try { - TryCreateDirectories(GUIUtil::qstringToBoostPath(dataDir)); + if (TryCreateDirectories(GUIUtil::qstringToBoostPath(dataDir))) { + // If a new data directory has been created, make wallets subdirectory too + TryCreateDirectories(GUIUtil::qstringToBoostPath(dataDir) / "wallets"); + } break; } catch (const fs::filesystem_error&) { QMessageBox::critical(0, tr(PACKAGE_NAME), diff --git a/src/qt/locale/bitcoin_en.ts b/src/qt/locale/bitcoin_en.ts index 821be8987e..2b712b4317 100644 --- a/src/qt/locale/bitcoin_en.ts +++ b/src/qt/locale/bitcoin_en.ts @@ -165,6 +165,11 @@ <translation>Repeat new passphrase</translation> </message> <message> + <location line="+14"/> + <source>Show password</source> + <translation type="unfinished"></translation> + </message> + <message> <location filename="../askpassphrasedialog.cpp" line="+46"/> <source>Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>ten or more random characters</b>, or <b>eight or more words</b>.</source> <translation type="unfinished"></translation> @@ -205,7 +210,7 @@ <translation type="unfinished"></translation> </message> <message> - <location line="+44"/> + <location line="+45"/> <source>Confirm wallet encryption</source> <translation type="unfinished"></translation> </message> @@ -278,7 +283,7 @@ </message> <message> <location line="+47"/> - <location line="+24"/> + <location line="+33"/> <source>Warning: The Caps Lock key is on!</source> <translation type="unfinished"></translation> </message> @@ -299,27 +304,27 @@ <context> <name>BitcoinGUI</name> <message> - <location filename="../bitcoingui.cpp" line="+357"/> + <location filename="../bitcoingui.cpp" line="+358"/> <source>Sign &message...</source> <translation>Sign &message...</translation> </message> <message> - <location line="+429"/> + <location line="+430"/> <source>Synchronizing with network...</source> <translation>Synchronizing with network...</translation> </message> <message> - <location line="-507"/> + <location line="-508"/> <source>&Overview</source> <translation>&Overview</translation> </message> <message> - <location line="-143"/> + <location line="-144"/> <source>Node</source> <translation type="unfinished"></translation> </message> <message> - <location line="+144"/> + <location line="+145"/> <source>Show general overview of wallet</source> <translation>Show general overview of wallet</translation> </message> @@ -404,7 +409,7 @@ <translation type="unfinished"></translation> </message> <message> - <location line="+359"/> + <location line="+360"/> <source>Click to disable network activity.</source> <translation type="unfinished"></translation> </message> @@ -429,7 +434,7 @@ <translation>Reindexing blocks on disk...</translation> </message> <message> - <location line="-510"/> + <location line="-511"/> <source>Send coins to a Bitcoin address</source> <translation>Send coins to a Bitcoin address</translation> </message> @@ -459,17 +464,17 @@ <translation>&Verify message...</translation> </message> <message> - <location line="+516"/> + <location line="+517"/> <source>Bitcoin</source> <translation>Bitcoin</translation> </message> <message> - <location line="-741"/> + <location line="-743"/> <source>Wallet</source> <translation>Wallet</translation> </message> <message> - <location line="+152"/> + <location line="+153"/> <source>&Send</source> <translation>&Send</translation> </message> @@ -549,7 +554,7 @@ <translation type="unfinished"></translation> </message> <message numerus="yes"> - <location line="+356"/> + <location line="+357"/> <source>%n active connection(s) to Bitcoin network</source> <translation> <numerusform>%n active connection to Bitcoin network</numerusform> @@ -610,12 +615,12 @@ <translation>Up to date</translation> </message> <message> - <location line="-440"/> + <location line="-441"/> <source>Show the %1 help message to get a list with possible Bitcoin command-line options</source> <translation type="unfinished"></translation> </message> <message> - <location line="+199"/> + <location line="+200"/> <source>%1 client</source> <translation type="unfinished"></translation> </message> @@ -783,7 +788,7 @@ <translation type="unfinished">Confirmed</translation> </message> <message> - <location filename="../coincontroldialog.cpp" line="+54"/> + <location filename="../coincontroldialog.cpp" line="+53"/> <source>Copy address</source> <translation type="unfinished"></translation> </message> @@ -913,7 +918,7 @@ <translation>&Address</translation> </message> <message> - <location filename="../editaddressdialog.cpp" line="+28"/> + <location filename="../editaddressdialog.cpp" line="+30"/> <source>New receiving address</source> <translation type="unfinished"></translation> </message> @@ -933,7 +938,7 @@ <translation type="unfinished"></translation> </message> <message> - <location line="+71"/> + <location line="+72"/> <source>The entered address "%1" is not a valid Bitcoin address.</source> <translation type="unfinished"></translation> </message> @@ -1118,7 +1123,7 @@ <translation type="unfinished"></translation> </message> <message> - <location line="+70"/> + <location line="+73"/> <source>Error: Specified data directory "%1" cannot be created.</source> <translation type="unfinished"></translation> </message> @@ -1169,7 +1174,7 @@ <message> <location line="+7"/> <location line="+26"/> - <location filename="../modaloverlay.cpp" line="+138"/> + <location filename="../modaloverlay.cpp" line="+140"/> <source>Unknown...</source> <translation type="unfinished"></translation> </message> @@ -1276,17 +1281,7 @@ <translation type="unfinished"></translation> </message> <message> - <location line="+114"/> - <source>Accept connections from outside</source> - <translation type="unfinished"></translation> - </message> - <message> - <location line="+3"/> - <source>Allow incoming connections</source> - <translation type="unfinished"></translation> - </message> - <message> - <location line="+44"/> + <location line="+161"/> <location line="+187"/> <source>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source> <translation type="unfinished"></translation> @@ -1299,7 +1294,22 @@ <translation type="unfinished"></translation> </message> <message> - <location line="+166"/> + <location line="+38"/> + <source>Use separate SOCKS&5 proxy to reach peers via Tor hidden services:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+108"/> + <source>Hide the icon from the system tray.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+3"/> + <source>&Hide tray icon</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+17"/> <source>Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Exit in the menu.</source> <translation type="unfinished"></translation> </message> @@ -1310,12 +1320,7 @@ <translation type="unfinished"></translation> </message> <message> - <location line="-10"/> - <source>Third party transaction URLs</source> - <translation type="unfinished"></translation> - </message> - <message> - <location line="+41"/> + <location line="+31"/> <source>Active command-line options that override above options:</source> <translation type="unfinished"></translation> </message> @@ -1385,7 +1390,17 @@ <translation>Map port using &UPnP</translation> </message> <message> - <location line="+17"/> + <location line="+7"/> + <source>Accept connections from outside.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+3"/> + <source>Allow incomin&g connections</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+7"/> <source>Connect to the Bitcoin network through a SOCKS5 proxy.</source> <translation type="unfinished"></translation> </message> @@ -1438,27 +1453,12 @@ <translation type="unfinished"></translation> </message> <message> - <location line="+3"/> - <source>Use separate SOCKS5 proxy to reach peers via Tor hidden services:</source> - <translation type="unfinished"></translation> - </message> - <message> - <location line="+102"/> + <location line="+105"/> <source>&Window</source> <translation>&Window</translation> </message> <message> - <location line="+6"/> - <source>&Hide the icon from the system tray.</source> - <translation type="unfinished"></translation> - </message> - <message> - <location line="+3"/> - <source>Hide tray icon</source> - <translation type="unfinished"></translation> - </message> - <message> - <location line="+7"/> + <location line="+16"/> <source>Show only a tray icon after minimizing the window.</source> <translation>Show only a tray icon after minimizing the window.</translation> </message> @@ -1503,7 +1503,12 @@ <translation type="unfinished"></translation> </message> <message> - <location line="+646"/> + <location line="+464"/> + <source>&Third party transaction URLs</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+182"/> <source>&OK</source> <translation>&OK</translation> </message> @@ -1513,7 +1518,7 @@ <translation>&Cancel</translation> </message> <message> - <location filename="../optionsdialog.cpp" line="+84"/> + <location filename="../optionsdialog.cpp" line="+82"/> <source>default</source> <translation>default</translation> </message> @@ -1666,34 +1671,34 @@ <context> <name>PaymentServer</name> <message> - <location filename="../paymentserver.cpp" line="+328"/> - <location line="+216"/> + <location filename="../paymentserver.cpp" line="+326"/> + <location line="+214"/> <location line="+42"/> - <location line="+113"/> + <location line="+111"/> <location line="+14"/> <location line="+18"/> <source>Payment request error</source> <translation type="unfinished"></translation> </message> <message> - <location line="-402"/> + <location line="-398"/> <source>Cannot start bitcoin: click-to-pay handler</source> <translation type="unfinished"></translation> </message> <message> - <location line="+103"/> - <location line="+14"/> + <location line="+102"/> + <location line="+13"/> <location line="+7"/> <source>URI handling</source> <translation type="unfinished"></translation> </message> <message> - <location line="-20"/> + <location line="-19"/> <source>Payment request fetch URL is invalid: %1</source> <translation type="unfinished"></translation> </message> <message> - <location line="+13"/> + <location line="+12"/> <source>Invalid payment address %1</source> <translation type="unfinished"></translation> </message> @@ -1718,12 +1723,12 @@ <location line="+31"/> <location line="+10"/> <location line="+17"/> - <location line="+88"/> + <location line="+86"/> <source>Payment request rejected</source> <translation type="unfinished"></translation> </message> <message> - <location line="-155"/> + <location line="-153"/> <source>Payment request network doesn't match client network.</source> <translation type="unfinished"></translation> </message> @@ -1759,7 +1764,7 @@ <translation type="unfinished"></translation> </message> <message> - <location line="+44"/> + <location line="+42"/> <source>Payment request %1 is too large (%2 bytes, allowed %3 bytes).</source> <translation type="unfinished"></translation> </message> @@ -1792,7 +1797,7 @@ <context> <name>PeerTableModel</name> <message> - <location filename="../peertablemodel.cpp" line="+117"/> + <location filename="../peertablemodel.cpp" line="+121"/> <source>User Agent</source> <translation type="unfinished"></translation> </message> @@ -1811,11 +1816,21 @@ <source>Ping</source> <translation type="unfinished"></translation> </message> + <message> + <location line="+0"/> + <source>Sent</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+0"/> + <source>Received</source> + <translation type="unfinished"></translation> + </message> </context> <context> <name>QObject</name> <message> - <location filename="../bitcoinunits.cpp" line="+176"/> + <location filename="../bitcoinunits.cpp" line="+185"/> <source>Amount</source> <translation type="unfinished">Amount</translation> </message> @@ -1825,7 +1840,7 @@ <translation type="unfinished"></translation> </message> <message> - <location line="+766"/> + <location line="+760"/> <source>%1 d</source> <translation type="unfinished"></translation> </message> @@ -1915,15 +1930,40 @@ </translation> </message> <message> + <location line="+8"/> + <source>%1 B</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+2"/> + <source>%1 KB</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+2"/> + <source>%1 MB</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+2"/> + <source>%1 GB</source> + <translation type="unfinished"></translation> + </message> + <message> <location filename="../bitcoin.cpp" line="+178"/> <source>%1 didn't yet exit safely...</source> <translation type="unfinished"></translation> </message> + <message> + <location filename="../modaloverlay.cpp" line="-29"/> + <source>unknown</source> + <translation type="unfinished"></translation> + </message> </context> <context> <name>QObject::QObject</name> <message> - <location line="-86"/> + <location filename="../bitcoin.cpp" line="-86"/> <source>Error: Specified data directory "%1" does not exist.</source> <translation type="unfinished"></translation> </message> @@ -1941,7 +1981,7 @@ <context> <name>QRImageWidget</name> <message> - <location filename="../receiverequestdialog.cpp" line="+36"/> + <location filename="../receiverequestdialog.cpp" line="+35"/> <source>&Save Image...</source> <translation type="unfinished"></translation> </message> @@ -2100,8 +2140,8 @@ </message> <message> <location line="+60"/> - <location filename="../rpcconsole.cpp" line="+467"/> - <location line="+728"/> + <location filename="../rpcconsole.cpp" line="+496"/> + <location line="+718"/> <source>Select a peer to view detailed information.</source> <translation type="unfinished"></translation> </message> @@ -2232,7 +2272,7 @@ <translation type="unfinished"></translation> </message> <message> - <location filename="../rpcconsole.cpp" line="-413"/> + <location filename="../rpcconsole.cpp" line="-401"/> <source>In:</source> <translation type="unfinished"></translation> </message> @@ -2252,7 +2292,7 @@ <translation>Clear console</translation> </message> <message> - <location filename="../rpcconsole.cpp" line="-223"/> + <location filename="../rpcconsole.cpp" line="-225"/> <source>1 &hour</source> <translation type="unfinished"></translation> </message> @@ -2290,52 +2330,37 @@ <translation type="unfinished"></translation> </message> <message> - <location line="+135"/> + <location line="+136"/> <source>Welcome to the %1 RPC console.</source> <translation type="unfinished"></translation> </message> <message> - <location line="+2"/> - <source>Type <b>help</b> for an overview of available commands.</source> - <translation>Type <b>help</b> for an overview of available commands.</translation> - </message> - <message> - <location line="-1"/> + <location line="+1"/> <source>Use up and down arrows to navigate history, and %1 to clear screen.</source> <translation type="unfinished"></translation> </message> <message> - <location line="+3"/> - <source>WARNING: Scammers have been active, telling users to type commands here, stealing their wallet contents. Do not use this console without fully understanding the ramifications of a command.</source> - <translation type="unfinished"></translation> - </message> - <message> - <location line="+36"/> - <source>Network activity disabled</source> - <translation type="unfinished"></translation> - </message> - <message> - <location line="+150"/> - <source>%1 B</source> + <location line="+1"/> + <source>Type %1 for an overview of available commands.</source> <translation type="unfinished"></translation> </message> <message> - <location line="+2"/> - <source>%1 KB</source> + <location line="+1"/> + <source>For more information on using this console type %1.</source> <translation type="unfinished"></translation> </message> <message> <location line="+2"/> - <source>%1 MB</source> + <source>WARNING: Scammers have been active, telling users to type commands here, stealing their wallet contents. Do not use this console without fully understanding the ramifications of a command.</source> <translation type="unfinished"></translation> </message> <message> - <location line="+2"/> - <source>%1 GB</source> + <location line="+36"/> + <source>Network activity disabled</source> <translation type="unfinished"></translation> </message> <message> - <location line="+99"/> + <location line="+243"/> <source>(node id: %1)</source> <translation type="unfinished"></translation> </message> @@ -2380,39 +2405,29 @@ <context> <name>ReceiveCoinsDialog</name> <message> - <location filename="../forms/receivecoinsdialog.ui" line="+107"/> + <location filename="../forms/receivecoinsdialog.ui" line="+37"/> <source>&Amount:</source> <translation type="unfinished"></translation> </message> <message> - <location line="-16"/> + <location line="+46"/> <source>&Label:</source> <translation type="unfinished">&Label:</translation> </message> <message> - <location line="-37"/> + <location line="-30"/> <source>&Message:</source> <translation type="unfinished"></translation> </message> <message> - <location line="-20"/> - <source>Reuse one of the previously used receiving addresses. Reusing addresses has security and privacy issues. Do not use this unless re-generating a payment request made before.</source> - <translation type="unfinished"></translation> - </message> - <message> - <location line="+3"/> - <source>R&euse an existing receiving address (not recommended)</source> - <translation type="unfinished"></translation> - </message> - <message> - <location line="+14"/> - <location line="+23"/> + <location line="-3"/> + <location line="+46"/> <source>An optional message to attach to the payment request, which will be displayed when the request is opened. Note: The message will not be sent with the payment over the Bitcoin network.</source> <translation type="unfinished"></translation> </message> <message> - <location line="-7"/> - <location line="+21"/> + <location line="-30"/> + <location line="+14"/> <source>An optional label to associate with the new receiving address.</source> <translation type="unfinished"></translation> </message> @@ -2422,13 +2437,13 @@ <translation type="unfinished"></translation> </message> <message> - <location line="+23"/> - <location line="+22"/> + <location line="-39"/> + <location line="+153"/> <source>An optional amount to request. Leave this empty or zero to not request a specific amount.</source> <translation type="unfinished"></translation> </message> <message> - <location line="+32"/> + <location line="-59"/> <source>Clear all fields of the form.</source> <translation type="unfinished"></translation> </message> @@ -2438,17 +2453,27 @@ <translation type="unfinished"></translation> </message> <message> - <location line="+75"/> + <location line="+142"/> <source>Requested payments history</source> <translation type="unfinished"></translation> </message> <message> - <location line="-95"/> + <location line="-162"/> <source>&Request payment</source> <translation type="unfinished"></translation> </message> <message> - <location line="+120"/> + <location line="+98"/> + <source>Bech32 addresses (BIP-173) are cheaper to spend from and offer better protection against typos. When unchecked a P2SH wrapped SegWit address will be created, compatible with older wallets.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+3"/> + <source>Generate Bech32 address</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+86"/> <source>Show the selected request (does the same as double clicking an entry)</source> <translation type="unfinished"></translation> </message> @@ -2598,7 +2623,7 @@ <name>SendCoinsDialog</name> <message> <location filename="../forms/sendcoinsdialog.ui" line="+14"/> - <location filename="../sendcoinsdialog.cpp" line="+586"/> + <location filename="../sendcoinsdialog.cpp" line="+578"/> <source>Send Coins</source> <translation>Send Coins</translation> </message> @@ -2703,7 +2728,7 @@ <translation type="unfinished"></translation> </message> <message> - <location line="+84"/> + <location line="+78"/> <location line="+13"/> <source>Paying only the minimum fee is just fine as long as there is less transaction volume than space in the blocks. But be aware that this can end up in a never confirming transaction once there is more demand for bitcoin transactions than the network can process.</source> <translation type="unfinished"></translation> @@ -2729,17 +2754,7 @@ <translation type="unfinished"></translation> </message> <message> - <location line="+103"/> - <source>Request Replace-By-Fee</source> - <translation type="unfinished"></translation> - </message> - <message> - <location line="+3"/> - <source>Indicates that the sender may wish to replace this transaction with a new one paying higher fees (prior to being confirmed).</source> - <translation type="unfinished"></translation> - </message> - <message> - <location line="+79"/> + <location line="+185"/> <source>Send to multiple recipients at once</source> <translation>Send to multiple recipients at once</translation> </message> @@ -2754,17 +2769,27 @@ <translation type="unfinished"></translation> </message> <message> - <location line="-839"/> + <location line="-833"/> <source>Dust:</source> <translation type="unfinished"></translation> </message> <message> - <location line="+700"/> + <location line="+694"/> <source>Confirmation time target:</source> <translation type="unfinished"></translation> </message> <message> - <location line="+142"/> + <location line="+74"/> + <source>Enable Replace-By-Fee</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+3"/> + <source>With Replace-By-Fee (BIP-125) you can increase a transaction's fee after it is sent. Without this, a higher fee may be recommended to compensate for increased transaction delay risk.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+65"/> <source>Clear &All</source> <translation>Clear &All</translation> </message> @@ -2784,7 +2809,7 @@ <translation>S&end</translation> </message> <message> - <location filename="../sendcoinsdialog.cpp" line="-499"/> + <location filename="../sendcoinsdialog.cpp" line="-494"/> <source>Copy quantity</source> <translation type="unfinished"></translation> </message> @@ -2819,12 +2844,12 @@ <translation type="unfinished"></translation> </message> <message> - <location line="+82"/> + <location line="+76"/> <source>%1 (%2 blocks)</source> <translation type="unfinished"></translation> </message> <message> - <location line="+129"/> + <location line="+127"/> <location line="+5"/> <location line="+5"/> <location line="+4"/> @@ -2852,17 +2877,22 @@ <translation type="unfinished"></translation> </message> <message> - <location line="+5"/> - <source>This transaction signals replaceability (optin-RBF).</source> + <location line="+4"/> + <source>You can increase the fee later (signals Replace-By-Fee, BIP-125).</source> <translation type="unfinished"></translation> </message> <message> - <location line="+4"/> + <location line="+2"/> + <source>Not signalling Replace-By-Fee, BIP-125.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+5"/> <source>Confirm send coins</source> <translation type="unfinished"></translation> </message> <message> - <location line="+191"/> + <location line="+192"/> <source>The recipient address is not valid. Please recheck.</source> <translation type="unfinished"></translation> </message> @@ -2907,7 +2937,7 @@ <translation type="unfinished"></translation> </message> <message> - <location line="+68"/> + <location line="+91"/> <source>Pay only the required fee of %1</source> <translation type="unfinished"></translation> </message> @@ -2925,7 +2955,7 @@ <translation type="unfinished"></translation> </message> <message> - <location line="+8"/> + <location line="+5"/> <source>Warning: Unknown change address</source> <translation type="unfinished"></translation> </message> @@ -2949,13 +2979,13 @@ <name>SendCoinsEntry</name> <message> <location filename="../forms/sendcoinsentry.ui" line="+155"/> - <location line="+539"/> + <location line="+546"/> <location line="+533"/> <source>A&mount:</source> <translation>A&mount:</translation> </message> <message> - <location line="-1185"/> + <location line="-1192"/> <source>Pay &To:</source> <translation>Pay &To:</translation> </message> @@ -2996,13 +3026,13 @@ </message> <message> <location line="+7"/> - <location line="+548"/> + <location line="+555"/> <location line="+533"/> <source>Remove this entry</source> <translation type="unfinished"></translation> </message> <message> - <location line="-1021"/> + <location line="-1028"/> <source>The fee will be deducted from the amount being sent. The recipient will receive less bitcoins than you enter in the amount field. If multiple recipients are selected, the fee is split equally.</source> <translation type="unfinished"></translation> </message> @@ -3012,6 +3042,11 @@ <translation type="unfinished"></translation> </message> <message> + <location line="+7"/> + <source>Use available balance</source> + <translation type="unfinished"></translation> + </message> + <message> <location line="+9"/> <source>Message:</source> <translation type="unfinished"></translation> @@ -3027,12 +3062,12 @@ <translation type="unfinished"></translation> </message> <message> - <location line="-1009"/> + <location line="-1016"/> <source>Enter a label for this address to add it to the list of used addresses</source> <translation type="unfinished"></translation> </message> <message> - <location line="+47"/> + <location line="+54"/> <source>A message that was attached to the bitcoin: URI which will be stored with the transaction for your reference. Note: This message will not be sent over the Bitcoin network.</source> <translation type="unfinished"></translation> </message> @@ -3049,7 +3084,7 @@ <translation type="unfinished"></translation> </message> <message> - <location filename="../sendcoinsentry.cpp" line="+37"/> + <location filename="../sendcoinsentry.cpp" line="+36"/> <source>Enter a label for this address to add it to your address book</source> <translation type="unfinished"></translation> </message> @@ -3192,27 +3227,27 @@ <translation type="unfinished"></translation> </message> <message> - <location line="+83"/> - <location line="+80"/> + <location line="+82"/> + <location line="+78"/> <source>The entered address is invalid.</source> <translation type="unfinished"></translation> </message> <message> - <location line="-80"/> - <location line="+8"/> - <location line="+72"/> - <location line="+8"/> + <location line="-78"/> + <location line="+7"/> + <location line="+71"/> + <location line="+6"/> <source>Please check the address and try again.</source> <translation type="unfinished"></translation> </message> <message> - <location line="-80"/> - <location line="+80"/> + <location line="-77"/> + <location line="+77"/> <source>The entered address does not refer to a key.</source> <translation type="unfinished"></translation> </message> <message> - <location line="-72"/> + <location line="-69"/> <source>Wallet unlock was cancelled.</source> <translation type="unfinished"></translation> </message> @@ -3232,7 +3267,7 @@ <translation type="unfinished"></translation> </message> <message> - <location line="+58"/> + <location line="+55"/> <source>The signature could not be decoded.</source> <translation type="unfinished"></translation> </message> @@ -3248,7 +3283,7 @@ <translation type="unfinished"></translation> </message> <message> - <location line="+7"/> + <location line="+6"/> <source>Message verification failed.</source> <translation type="unfinished"></translation> </message> @@ -3364,7 +3399,7 @@ </message> <message> <location line="+5"/> - <location line="+13"/> + <location line="+12"/> <location line="+72"/> <source>From</source> <translation type="unfinished"></translation> @@ -3739,7 +3774,7 @@ </message> <message> <location line="+6"/> - <source>Enter address or label to search</source> + <source>Enter address, transaction id, or label to search</source> <translation type="unfinished"></translation> </message> <message> @@ -3748,7 +3783,7 @@ <translation type="unfinished"></translation> </message> <message> - <location line="+37"/> + <location line="+48"/> <source>Abandon transaction</source> <translation type="unfinished"></translation> </message> @@ -3798,7 +3833,7 @@ <translation type="unfinished"></translation> </message> <message> - <location line="+193"/> + <location line="+194"/> <source>Export Transaction History</source> <translation type="unfinished"></translation> </message> @@ -3884,7 +3919,7 @@ <context> <name>WalletFrame</name> <message> - <location filename="../walletframe.cpp" line="+27"/> + <location filename="../walletframe.cpp" line="+28"/> <source>No wallet has been loaded.</source> <translation type="unfinished"></translation> </message> @@ -3892,19 +3927,19 @@ <context> <name>WalletModel</name> <message> - <location filename="../walletmodel.cpp" line="+291"/> + <location filename="../walletmodel.cpp" line="+290"/> <source>Send Coins</source> <translation type="unfinished">Send Coins</translation> </message> <message> - <location line="+387"/> - <location line="+46"/> - <location line="+9"/> + <location line="+384"/> + <location line="+39"/> + <location line="+6"/> <source>Fee bump error</source> <translation type="unfinished"></translation> </message> <message> - <location line="-55"/> + <location line="-45"/> <source>Increasing transaction fee failed</source> <translation type="unfinished"></translation> </message> @@ -3914,7 +3949,7 @@ <translation type="unfinished"></translation> </message> <message> - <location line="+6"/> + <location line="+4"/> <source>Current fee:</source> <translation type="unfinished"></translation> </message> @@ -3934,12 +3969,12 @@ <translation type="unfinished"></translation> </message> <message> - <location line="+22"/> + <location line="+17"/> <source>Can't sign transaction.</source> <translation type="unfinished"></translation> </message> <message> - <location line="+9"/> + <location line="+6"/> <source>Could not commit transaction</source> <translation type="unfinished"></translation> </message> @@ -3990,32 +4025,32 @@ <context> <name>bitcoin-core</name> <message> - <location filename="../bitcoinstrings.cpp" line="+343"/> + <location filename="../bitcoinstrings.cpp" line="+351"/> <source>Options:</source> <translation>Options:</translation> </message> <message> - <location line="+31"/> + <location line="+33"/> <source>Specify data directory</source> <translation>Specify data directory</translation> </message> <message> - <location line="-95"/> + <location line="-99"/> <source>Connect to a node to retrieve peer addresses, and disconnect</source> <translation>Connect to a node to retrieve peer addresses, and disconnect</translation> </message> <message> - <location line="+98"/> + <location line="+102"/> <source>Specify your own public address</source> <translation>Specify your own public address</translation> </message> <message> - <location line="-114"/> + <location line="-116"/> <source>Accept command line and JSON-RPC commands</source> <translation>Accept command line and JSON-RPC commands</translation> </message> <message> - <location line="-207"/> + <location line="-209"/> <source>Distributed under the MIT software license, see the accompanying file %s or %s</source> <translation type="unfinished"></translation> </message> @@ -4040,12 +4075,12 @@ <translation type="unfinished"></translation> </message> <message> - <location line="+150"/> + <location line="+151"/> <source>Error: A fatal internal error occurred, see debug.log for details</source> <translation type="unfinished"></translation> </message> <message> - <location line="+3"/> + <location line="+4"/> <source>Fee (in %s/kB) to add to transactions you send (default: %s)</source> <translation type="unfinished"></translation> </message> @@ -4060,12 +4095,12 @@ <translation>Run in the background as a daemon and accept commands</translation> </message> <message> - <location line="+37"/> + <location line="+40"/> <source>Unable to start HTTP server. See debug log for details.</source> <translation type="unfinished"></translation> </message> <message> - <location line="-386"/> + <location line="-397"/> <source>Bitcoin Core</source> <translation type="unfinished">Bitcoin Core</translation> </message> @@ -4085,6 +4120,11 @@ <translation type="unfinished"></translation> </message> <message> + <location line="+3"/> + <source>Add a node to connect to and attempt to keep the connection open (see the `addnode` RPC command help for more info)</source> + <translation type="unfinished"></translation> + </message> + <message> <location line="+7"/> <source>Bind to given address and always listen on it. Use [host]:port notation for IPv6</source> <translation>Bind to given address and always listen on it. Use [host]:port notation for IPv6</translation> @@ -4095,7 +4135,17 @@ <translation type="unfinished"></translation> </message> <message> - <location line="+8"/> + <location line="+2"/> + <source>Cannot provide specific connections and have addrman find outgoing connections at the same.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+3"/> + <source>Connect only to the specified node(s); -connect=0 disables automatic connections (the rules for this peer are the same as for -addnode)</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+6"/> <source>Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup</source> <translation type="unfinished"></translation> </message> @@ -4160,12 +4210,12 @@ <translation type="unfinished"></translation> </message> <message> - <location line="+3"/> + <location line="+5"/> <source>Set the number of script verification threads (%u to %d, 0 = auto, <0 = leave that many cores free, default: %d)</source> <translation type="unfinished"></translation> </message> <message> - <location line="+8"/> + <location line="+14"/> <source>The block database contains a block which appears to be from the future. This may be due to your computer's date and time being set incorrectly. Only rebuild the block database if you are sure that your computer's date and time are correct</source> <translation type="unfinished"></translation> </message> @@ -4195,7 +4245,7 @@ <translation type="unfinished"></translation> </message> <message> - <location line="+8"/> + <location line="+5"/> <source>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. The client then connects normally using the rpcuser=<USERNAME>/rpcpassword=<PASSWORD> pair of arguments. This option can be specified multiple times</source> <translation type="unfinished"></translation> </message> @@ -4221,11 +4271,6 @@ </message> <message> <location line="+11"/> - <source>You need to rebuild the database using -reindex-chainstate to change -txindex</source> - <translation type="unfinished"></translation> - </message> - <message> - <location line="+2"/> <source>%d of last 100 blocks have unexpected version</source> <translation type="unfinished"></translation> </message> @@ -4236,11 +4281,6 @@ </message> <message> <location line="+4"/> - <source>(press q to shutdown and continue later)</source> - <translation type="unfinished"></translation> - </message> - <message> - <location line="+1"/> <source>-maxmempool must be at least %d MB</source> <translation type="unfinished"></translation> </message> @@ -4255,7 +4295,7 @@ <translation type="unfinished"></translation> </message> <message> - <location line="+5"/> + <location line="+4"/> <source>Append comment to the user agent string</source> <translation type="unfinished"></translation> </message> @@ -4275,7 +4315,7 @@ <translation type="unfinished"></translation> </message> <message> - <location line="+2"/> + <location line="+1"/> <source>Chain selection options:</source> <translation type="unfinished"></translation> </message> @@ -4341,6 +4381,11 @@ </message> <message> <location line="+1"/> + <source>Error creating %s: You can't create non-HD wallets with this version.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+1"/> <source>Error initializing block database</source> <translation>Error initializing block database</translation> </message> @@ -4385,6 +4430,11 @@ <translation>Failed to listen on any port. Use -listen=0 if you want this.</translation> </message> <message> + <location line="+1"/> + <source>Failed to rescan the wallet during initialization</source> + <translation type="unfinished"></translation> + </message> + <message> <location line="+3"/> <source>Importing...</source> <translation type="unfinished"></translation> @@ -4485,17 +4535,17 @@ <translation type="unfinished"></translation> </message> <message> - <location line="+4"/> - <source>Set database cache size in megabytes (%d to %d, default: %d)</source> + <location line="+3"/> + <source>Send transactions with full-RBF opt-in enabled (RPC only, default: %u)</source> <translation type="unfinished"></translation> </message> <message> - <location line="+3"/> - <source>Set maximum block size in bytes (default: %d)</source> + <location line="+1"/> + <source>Set database cache size in megabytes (%d to %d, default: %d)</source> <translation type="unfinished"></translation> </message> <message> - <location line="+9"/> + <location line="+14"/> <source>Specify wallet file (within data directory)</source> <translation>Specify wallet file (within data directory)</translation> </message> @@ -4515,7 +4565,7 @@ <translation type="unfinished"></translation> </message> <message> - <location line="+3"/> + <location line="+4"/> <source>Unsupported argument -benchmark ignored, use -debug=bench.</source> <translation type="unfinished"></translation> </message> @@ -4560,12 +4610,7 @@ <translation>Verifying blocks...</translation> </message> <message> - <location line="+2"/> - <source>Wallet %s resides outside data directory %s</source> - <translation>Wallet %s resides outside data directory %s</translation> - </message> - <message> - <location line="+1"/> + <location line="+3"/> <source>Wallet debugging/testing options:</source> <translation type="unfinished"></translation> </message> @@ -4580,7 +4625,7 @@ <translation type="unfinished"></translation> </message> <message> - <location line="-389"/> + <location line="-397"/> <source>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</source> <translation type="unfinished"></translation> </message> @@ -4590,7 +4635,7 @@ <translation type="unfinished"></translation> </message> <message> - <location line="+14"/> + <location line="+17"/> <source>Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality)</source> <translation type="unfinished"></translation> </message> @@ -4635,17 +4680,12 @@ <translation type="unfinished"></translation> </message> <message> - <location line="+36"/> + <location line="+44"/> <source>The transaction amount is too small to send after the fee has been deducted</source> <translation type="unfinished"></translation> </message> <message> - <location line="+34"/> - <source>Use hierarchical deterministic key generation (HD) after BIP32. Only has effect during wallet creation/first start</source> - <translation type="unfinished"></translation> - </message> - <message> - <location line="+33"/> + <location line="+64"/> <source>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</source> <translation type="unfinished"></translation> </message> @@ -4655,27 +4695,27 @@ <translation type="unfinished"></translation> </message> <message> - <location line="+9"/> + <location line="+7"/> <source>(default: %u)</source> <translation type="unfinished"></translation> </message> <message> - <location line="+6"/> + <location line="+5"/> <source>Accept public REST requests (default: %u)</source> <translation type="unfinished"></translation> </message> <message> - <location line="+6"/> + <location line="+5"/> <source>Automatically create Tor hidden service (default: %d)</source> <translation type="unfinished"></translation> </message> <message> - <location line="+7"/> + <location line="+6"/> <source>Connect through SOCKS5 proxy</source> <translation type="unfinished"></translation> </message> <message> - <location line="+19"/> + <location line="+20"/> <source>Error loading %s: You can't disable HD on an already existing HD wallet</source> <translation type="unfinished"></translation> </message> @@ -4690,7 +4730,7 @@ <translation type="unfinished"></translation> </message> <message> - <location line="+8"/> + <location line="+9"/> <source>Imports blocks from external blk000??.dat file on startup</source> <translation type="unfinished"></translation> </message> @@ -4755,7 +4795,7 @@ <translation>Send trace/debug info to console instead of debug.log file</translation> </message> <message> - <location line="+7"/> + <location line="+6"/> <source>Show all debugging options (usage: --help -help-debug)</source> <translation type="unfinished"></translation> </message> @@ -4770,6 +4810,21 @@ <translation>Signing transaction failed</translation> </message> <message> + <location line="+1"/> + <source>Specified -walletdir "%s" does not exist</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+1"/> + <source>Specified -walletdir "%s" is a relative path</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+1"/> + <source>Specified -walletdir "%s" is not a directory</source> + <translation type="unfinished"></translation> + </message> + <message> <location line="+10"/> <source>The transaction amount is too small to pay the fee</source> <translation type="unfinished"></translation> @@ -4810,7 +4865,12 @@ <translation type="unfinished"></translation> </message> <message> - <location line="+8"/> + <location line="+2"/> + <source>Unable to generate initial keys</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+7"/> <source>Upgrade wallet to latest format on startup</source> <translation type="unfinished"></translation> </message> @@ -4825,7 +4885,12 @@ <translation type="unfinished"></translation> </message> <message> - <location line="+5"/> + <location line="+1"/> + <source>Wallet %s resides outside wallet directory %s</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+4"/> <source>Warning</source> <translation>Warning</translation> </message> @@ -4841,6 +4906,11 @@ </message> <message> <location line="+1"/> + <source>You need to rebuild the database using -reindex to change -txindex</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+1"/> <source>Zapping all transactions from wallet...</source> <translation type="unfinished"></translation> </message> @@ -4850,22 +4920,22 @@ <translation type="unfinished"></translation> </message> <message> - <location line="-76"/> + <location line="-80"/> <source>Password for JSON-RPC connections</source> <translation>Password for JSON-RPC connections</translation> </message> <message> - <location line="-261"/> + <location line="-263"/> <source>Execute command when the best block changes (%s in cmd is replaced by block hash)</source> <translation>Execute command when the best block changes (%s in cmd is replaced by block hash)</translation> </message> <message> - <location line="+184"/> + <location line="+185"/> <source>Allow DNS lookups for -addnode, -seednode and -connect</source> <translation>Allow DNS lookups for -addnode, -seednode and -connect</translation> </message> <message> - <location line="-253"/> + <location line="-260"/> <source>(1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data)</source> <translation type="unfinished"></translation> </message> @@ -4875,17 +4945,12 @@ <translation type="unfinished"></translation> </message> <message> - <location line="+19"/> + <location line="+22"/> <source>Bind to given address to listen for JSON-RPC connections. This option is ignored unless -rpcallowip is also passed. Port is optional and overrides -rpcport. Use [host]:port notation for IPv6. This option can be specified multiple times (default: 127.0.0.1 and ::1 i.e., localhost, or if -rpcallowip has been specified, 0.0.0.0 and :: i.e., all addresses)</source> <translation type="unfinished"></translation> </message> <message> - <location line="+8"/> - <source>Connect only to the specified node(s); -connect=0 disables automatic connections</source> - <translation type="unfinished"></translation> - </message> - <message> - <location line="+15"/> + <location line="+26"/> <source>Do not keep transactions in the mempool longer than <n> hours (default: %u)</source> <translation type="unfinished"></translation> </message> @@ -4935,12 +5000,27 @@ <translation type="unfinished"></translation> </message> <message> - <location line="+37"/> + <location line="+34"/> + <source>Set maximum BIP141 block weight to this * 4. Deprecated, use blockmaxweight</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+5"/> <source>Sets the serialization of raw transaction or block hex returned in non-verbose mode, non-segwit(0) or segwit(1) (default: %d)</source> <translation type="unfinished"></translation> </message> <message> <location line="+3"/> + <source>Specify directory to hold wallets (default: <datadir>/wallets if it exists, otherwise <datadir>)</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+3"/> + <source>Specify location of debug log file: this can be an absolute path or a path relative to the data directory (default: %s)</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+3"/> <source>Support filtering of blocks and transaction with bloom filters (default: %u)</source> <translation type="unfinished"></translation> </message> @@ -4980,7 +5060,7 @@ <translation type="unfinished"></translation> </message> <message> - <location line="+8"/> + <location line="+5"/> <source>Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s)</source> <translation type="unfinished"></translation> </message> @@ -5000,7 +5080,7 @@ <translation type="unfinished"></translation> </message> <message> - <location line="+13"/> + <location line="+11"/> <source>%s is set very high!</source> <translation type="unfinished"></translation> </message> @@ -5010,7 +5090,7 @@ <translation type="unfinished"></translation> </message> <message> - <location line="+10"/> + <location line="+8"/> <source>Always query for peer addresses via DNS lookup (default: %u)</source> <translation type="unfinished"></translation> </message> @@ -5030,7 +5110,7 @@ <translation type="unfinished"></translation> </message> <message> - <location line="+9"/> + <location line="+10"/> <source>How many blocks to check at startup (default: %u, 0 = all)</source> <translation type="unfinished"></translation> </message> @@ -5090,12 +5170,7 @@ <translation type="unfinished"></translation> </message> <message> - <location line="+7"/> - <source>Send transactions with full-RBF opt-in enabled (default: %u)</source> - <translation type="unfinished"></translation> - </message> - <message> - <location line="+2"/> + <location line="+9"/> <source>Set key pool size to <n> (default: %u)</source> <translation type="unfinished"></translation> </message> @@ -5105,12 +5180,12 @@ <translation type="unfinished"></translation> </message> <message> - <location line="+2"/> + <location line="+1"/> <source>Set the number of threads to service RPC calls (default: %d)</source> <translation type="unfinished"></translation> </message> <message> - <location line="+4"/> + <location line="+7"/> <source>Specify configuration file (default: %s)</source> <translation type="unfinished"></translation> </message> @@ -5170,12 +5245,12 @@ <translation type="unfinished"></translation> </message> <message> - <location line="+6"/> + <location line="+7"/> <source>Unknown network specified in -onlynet: '%s'</source> <translation>Unknown network specified in -onlynet: '%s'</translation> </message> <message> - <location line="-82"/> + <location line="-85"/> <source>Insufficient funds</source> <translation>Insufficient funds</translation> </message> @@ -5185,37 +5260,27 @@ <translation>Loading block index...</translation> </message> <message> - <location line="-66"/> - <source>Add a node to connect to and attempt to keep the connection open</source> - <translation>Add a node to connect to and attempt to keep the connection open</translation> - </message> - <message> - <location line="+67"/> + <location line="+1"/> <source>Loading wallet...</source> <translation>Loading wallet...</translation> </message> <message> - <location line="-60"/> + <location line="-61"/> <source>Cannot downgrade wallet</source> <translation>Cannot downgrade wallet</translation> </message> <message> - <location line="+2"/> - <source>Cannot write default address</source> - <translation>Cannot write default address</translation> - </message> - <message> - <location line="+84"/> + <location line="+87"/> <source>Rescanning...</source> <translation>Rescanning...</translation> </message> <message> - <location line="-73"/> + <location line="-75"/> <source>Done loading</source> <translation>Done loading</translation> </message> <message> - <location line="+19"/> + <location line="+20"/> <source>Error</source> <translation>Error</translation> </message> diff --git a/src/qt/macnotificationhandler.h b/src/qt/macnotificationhandler.h index 3a005c3c46..1e25d3e7a4 100644 --- a/src/qt/macnotificationhandler.h +++ b/src/qt/macnotificationhandler.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2014 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/modaloverlay.cpp b/src/qt/modaloverlay.cpp index b707b0dda9..b573dbe226 100644 --- a/src/qt/modaloverlay.cpp +++ b/src/qt/modaloverlay.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2016 The Bitcoin Core developers +// Copyright (c) 2016-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/modaloverlay.h b/src/qt/modaloverlay.h index cda23f9540..63465ab66e 100644 --- a/src/qt/modaloverlay.h +++ b/src/qt/modaloverlay.h @@ -1,4 +1,4 @@ -// Copyright (c) 2016 The Bitcoin Core developers +// Copyright (c) 2016-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/networkstyle.cpp b/src/qt/networkstyle.cpp index 42ae3ae566..2816633b0f 100644 --- a/src/qt/networkstyle.cpp +++ b/src/qt/networkstyle.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2016 The Bitcoin Core developers +// Copyright (c) 2014-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/notificator.cpp b/src/qt/notificator.cpp index 4f8732a9ce..64a8e5d989 100644 --- a/src/qt/notificator.cpp +++ b/src/qt/notificator.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 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,7 +6,6 @@ #include <QApplication> #include <QByteArray> -#include <QIcon> #include <QImageWriter> #include <QMessageBox> #include <QMetaType> diff --git a/src/qt/notificator.h b/src/qt/notificator.h index ef6f5c7ec5..3da24cd1a1 100644 --- a/src/qt/notificator.h +++ b/src/qt/notificator.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/openuridialog.cpp b/src/qt/openuridialog.cpp index 40671922f4..751cfa8b43 100644 --- a/src/qt/openuridialog.cpp +++ b/src/qt/openuridialog.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2014 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp index d7aa8bc38b..5bef473c63 100644 --- a/src/qt/optionsdialog.cpp +++ b/src/qt/optionsdialog.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -338,7 +338,7 @@ QValidator::State ProxyAddressValidator::validate(QString &input, int &pos) cons { Q_UNUSED(pos); // Validate the proxy - CService serv(LookupNumeric(input.toStdString().c_str(), 9050)); + CService serv(LookupNumeric(input.toStdString().c_str(), DEFAULT_GUI_PROXY_PORT)); proxyType addrProxy = proxyType(serv, true); if (addrProxy.IsValid()) return QValidator::Acceptable; diff --git a/src/qt/optionsdialog.h b/src/qt/optionsdialog.h index f9f5823c05..faf9ff8959 100644 --- a/src/qt/optionsdialog.h +++ b/src/qt/optionsdialog.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp index a0645d9a74..4ade88d843 100644 --- a/src/qt/optionsmodel.cpp +++ b/src/qt/optionsmodel.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -11,7 +11,6 @@ #include <qt/bitcoinunits.h> #include <qt/guiutil.h> -#include <amount.h> #include <init.h> #include <validation.h> // For DEFAULT_SCRIPTCHECK_THREADS #include <net.h> @@ -28,6 +27,8 @@ #include <QSettings> #include <QStringList> +const char *DEFAULT_GUI_PROXY_HOST = "127.0.0.1"; + OptionsModel::OptionsModel(QObject *parent, bool resetSettings) : QAbstractListModel(parent) { @@ -124,8 +125,8 @@ void OptionsModel::Init(bool resetSettings) if (!settings.contains("fUseProxy")) settings.setValue("fUseProxy", false); - if (!settings.contains("addrProxy") || !settings.value("addrProxy").toString().contains(':')) - settings.setValue("addrProxy", "127.0.0.1:9050"); + if (!settings.contains("addrProxy")) + settings.setValue("addrProxy", QString("%1:%2").arg(DEFAULT_GUI_PROXY_HOST, DEFAULT_GUI_PROXY_PORT)); // Only try to set -proxy, if user has enabled fUseProxy if (settings.value("fUseProxy").toBool() && !gArgs.SoftSetArg("-proxy", settings.value("addrProxy").toString().toStdString())) addOverriddenOption("-proxy"); @@ -134,8 +135,8 @@ void OptionsModel::Init(bool resetSettings) if (!settings.contains("fUseSeparateProxyTor")) settings.setValue("fUseSeparateProxyTor", false); - if (!settings.contains("addrSeparateProxyTor") || !settings.value("addrSeparateProxyTor").toString().contains(':')) - settings.setValue("addrSeparateProxyTor", "127.0.0.1:9050"); + if (!settings.contains("addrSeparateProxyTor")) + settings.setValue("addrSeparateProxyTor", QString("%1:%2").arg(DEFAULT_GUI_PROXY_HOST, DEFAULT_GUI_PROXY_PORT)); // Only try to set -onion, if user has enabled fUseSeparateProxyTor if (settings.value("fUseSeparateProxyTor").toBool() && !gArgs.SoftSetArg("-onion", settings.value("addrSeparateProxyTor").toString().toStdString())) addOverriddenOption("-onion"); @@ -200,6 +201,33 @@ int OptionsModel::rowCount(const QModelIndex & parent) const return OptionIDRowCount; } +struct ProxySetting { + bool is_set; + QString ip; + QString port; +}; + +static ProxySetting GetProxySetting(QSettings &settings, const QString &name) +{ + static const ProxySetting default_val = {false, DEFAULT_GUI_PROXY_HOST, QString("%1").arg(DEFAULT_GUI_PROXY_PORT)}; + // Handle the case that the setting is not set at all + if (!settings.contains(name)) { + return default_val; + } + // contains IP at index 0 and port at index 1 + QStringList ip_port = settings.value(name).toString().split(":", QString::SkipEmptyParts); + if (ip_port.size() == 2) { + return {true, ip_port.at(0), ip_port.at(1)}; + } else { // Invalid: return default + return default_val; + } +} + +static void SetProxySetting(QSettings &settings, const QString &name, const ProxySetting &ip_port) +{ + settings.setValue(name, ip_port.ip + ":" + ip_port.port); +} + // read QSettings values and return them QVariant OptionsModel::data(const QModelIndex & index, int role) const { @@ -226,30 +254,18 @@ QVariant OptionsModel::data(const QModelIndex & index, int role) const // default proxy case ProxyUse: return settings.value("fUseProxy", false); - case ProxyIP: { - // contains IP at index 0 and port at index 1 - QStringList strlIpPort = settings.value("addrProxy").toString().split(":", QString::SkipEmptyParts); - return strlIpPort.at(0); - } - case ProxyPort: { - // contains IP at index 0 and port at index 1 - QStringList strlIpPort = settings.value("addrProxy").toString().split(":", QString::SkipEmptyParts); - return strlIpPort.at(1); - } + case ProxyIP: + return GetProxySetting(settings, "addrProxy").ip; + case ProxyPort: + return GetProxySetting(settings, "addrProxy").port; // separate Tor proxy case ProxyUseTor: return settings.value("fUseSeparateProxyTor", false); - case ProxyIPTor: { - // contains IP at index 0 and port at index 1 - QStringList strlIpPort = settings.value("addrSeparateProxyTor").toString().split(":", QString::SkipEmptyParts); - return strlIpPort.at(0); - } - case ProxyPortTor: { - // contains IP at index 0 and port at index 1 - QStringList strlIpPort = settings.value("addrSeparateProxyTor").toString().split(":", QString::SkipEmptyParts); - return strlIpPort.at(1); - } + case ProxyIPTor: + return GetProxySetting(settings, "addrSeparateProxyTor").ip; + case ProxyPortTor: + return GetProxySetting(settings, "addrSeparateProxyTor").port; #ifdef ENABLE_WALLET case SpendZeroConfChange: @@ -314,25 +330,19 @@ bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, in } break; case ProxyIP: { - // contains current IP at index 0 and current port at index 1 - QStringList strlIpPort = settings.value("addrProxy").toString().split(":", QString::SkipEmptyParts); - // if that key doesn't exist or has a changed IP - if (!settings.contains("addrProxy") || strlIpPort.at(0) != value.toString()) { - // construct new value from new IP and current port - QString strNewValue = value.toString() + ":" + strlIpPort.at(1); - settings.setValue("addrProxy", strNewValue); + auto ip_port = GetProxySetting(settings, "addrProxy"); + if (!ip_port.is_set || ip_port.ip != value.toString()) { + ip_port.ip = value.toString(); + SetProxySetting(settings, "addrProxy", ip_port); setRestartRequired(true); } } break; case ProxyPort: { - // contains current IP at index 0 and current port at index 1 - QStringList strlIpPort = settings.value("addrProxy").toString().split(":", QString::SkipEmptyParts); - // if that key doesn't exist or has a changed port - if (!settings.contains("addrProxy") || strlIpPort.at(1) != value.toString()) { - // construct new value from current IP and new port - QString strNewValue = strlIpPort.at(0) + ":" + value.toString(); - settings.setValue("addrProxy", strNewValue); + auto ip_port = GetProxySetting(settings, "addrProxy"); + if (!ip_port.is_set || ip_port.port != value.toString()) { + ip_port.port = value.toString(); + SetProxySetting(settings, "addrProxy", ip_port); setRestartRequired(true); } } @@ -346,25 +356,19 @@ bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, in } break; case ProxyIPTor: { - // contains current IP at index 0 and current port at index 1 - QStringList strlIpPort = settings.value("addrSeparateProxyTor").toString().split(":", QString::SkipEmptyParts); - // if that key doesn't exist or has a changed IP - if (!settings.contains("addrSeparateProxyTor") || strlIpPort.at(0) != value.toString()) { - // construct new value from new IP and current port - QString strNewValue = value.toString() + ":" + strlIpPort.at(1); - settings.setValue("addrSeparateProxyTor", strNewValue); + auto ip_port = GetProxySetting(settings, "addrSeparateProxyTor"); + if (!ip_port.is_set || ip_port.ip != value.toString()) { + ip_port.ip = value.toString(); + SetProxySetting(settings, "addrSeparateProxyTor", ip_port); setRestartRequired(true); } } break; case ProxyPortTor: { - // contains current IP at index 0 and current port at index 1 - QStringList strlIpPort = settings.value("addrSeparateProxyTor").toString().split(":", QString::SkipEmptyParts); - // if that key doesn't exist or has a changed port - if (!settings.contains("addrSeparateProxyTor") || strlIpPort.at(1) != value.toString()) { - // construct new value from current IP and new port - QString strNewValue = strlIpPort.at(0) + ":" + value.toString(); - settings.setValue("addrSeparateProxyTor", strNewValue); + auto ip_port = GetProxySetting(settings, "addrSeparateProxyTor"); + if (!ip_port.is_set || ip_port.port != value.toString()) { + ip_port.port = value.toString(); + SetProxySetting(settings, "addrSeparateProxyTor", ip_port); setRestartRequired(true); } } diff --git a/src/qt/optionsmodel.h b/src/qt/optionsmodel.h index b6e8fdef68..3f50541eb4 100644 --- a/src/qt/optionsmodel.h +++ b/src/qt/optionsmodel.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -13,6 +13,9 @@ QT_BEGIN_NAMESPACE class QNetworkProxy; QT_END_NAMESPACE +extern const char *DEFAULT_GUI_PROXY_HOST; +static constexpr unsigned short DEFAULT_GUI_PROXY_PORT = 9050; + /** Interface from Qt to configuration data structure for Bitcoin client. To Qt, the options are presented as a list with the different options laid out vertically. diff --git a/src/qt/overviewpage.cpp b/src/qt/overviewpage.cpp index 7818607d30..d1c9f17961 100644 --- a/src/qt/overviewpage.cpp +++ b/src/qt/overviewpage.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/overviewpage.h b/src/qt/overviewpage.h index 1e09d907b0..0ce9f98c8c 100644 --- a/src/qt/overviewpage.h +++ b/src/qt/overviewpage.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/paymentrequestplus.cpp b/src/qt/paymentrequestplus.cpp index 4503728882..b0ef475b35 100644 --- a/src/qt/paymentrequestplus.cpp +++ b/src/qt/paymentrequestplus.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/paymentrequestplus.h b/src/qt/paymentrequestplus.h index e1388f2b5d..be3923304f 100644 --- a/src/qt/paymentrequestplus.h +++ b/src/qt/paymentrequestplus.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/paymentserver.cpp b/src/qt/paymentserver.cpp index 510a3783ae..bc69d4f945 100644 --- a/src/qt/paymentserver.cpp +++ b/src/qt/paymentserver.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -636,27 +636,25 @@ void PaymentServer::fetchPaymentACK(CWallet* wallet, const SendCoinsRecipient& r // Create a new refund address, or re-use: QString account = tr("Refund from %1").arg(recipient.authenticatedMerchant); std::string strAccount = account.toStdString(); - std::set<CTxDestination> refundAddresses = wallet->GetAccountAddresses(strAccount); - if (!refundAddresses.empty()) { - CScript s = GetScriptForDestination(*refundAddresses.begin()); + CPubKey newKey; + if (wallet->GetKeyFromPool(newKey)) { + // BIP70 requests encode the scriptPubKey directly, so we are not restricted to address + // types supported by the receiver. As a result, we choose the address format we also + // use for change. Despite an actual payment and not change, this is a close match: + // it's the output type we use subject to privacy issues, but not restricted by what + // other software supports. + const OutputType change_type = g_change_type != OUTPUT_TYPE_NONE ? g_change_type : g_address_type; + wallet->LearnRelatedScripts(newKey, change_type); + CTxDestination dest = GetDestinationForKey(newKey, change_type); + wallet->SetAddressBook(dest, strAccount, "refund"); + + CScript s = GetScriptForDestination(dest); payments::Output* refund_to = payment.add_refund_to(); refund_to->set_script(&s[0], s.size()); - } - else { - CPubKey newKey; - if (wallet->GetKeyFromPool(newKey)) { - CKeyID keyID = newKey.GetID(); - wallet->SetAddressBook(keyID, strAccount, "refund"); - - CScript s = GetScriptForDestination(keyID); - payments::Output* refund_to = payment.add_refund_to(); - refund_to->set_script(&s[0], s.size()); - } - else { - // This should never happen, because sending coins should have - // just unlocked the wallet and refilled the keypool. - qWarning() << "PaymentServer::fetchPaymentACK: Error getting refund key, refund_to not set"; - } + } else { + // This should never happen, because sending coins should have + // just unlocked the wallet and refilled the keypool. + qWarning() << "PaymentServer::fetchPaymentACK: Error getting refund key, refund_to not set"; } int length = payment.ByteSize(); diff --git a/src/qt/paymentserver.h b/src/qt/paymentserver.h index 9adef9743d..e262fc6bf7 100644 --- a/src/qt/paymentserver.h +++ b/src/qt/paymentserver.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/peertablemodel.cpp b/src/qt/peertablemodel.cpp index cfafab2c8a..0a57dcfca3 100644 --- a/src/qt/peertablemodel.cpp +++ b/src/qt/peertablemodel.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/peertablemodel.h b/src/qt/peertablemodel.h index e41fe4bb03..e3c9c6e5a3 100644 --- a/src/qt/peertablemodel.h +++ b/src/qt/peertablemodel.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/platformstyle.cpp b/src/qt/platformstyle.cpp index cc8ea3622b..fce71f661a 100644 --- a/src/qt/platformstyle.cpp +++ b/src/qt/platformstyle.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2016 The Bitcoin Core developers +// Copyright (c) 2015-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -8,10 +8,8 @@ #include <QApplication> #include <QColor> -#include <QIcon> #include <QImage> #include <QPalette> -#include <QPixmap> static const struct { const char *platformId; diff --git a/src/qt/qvalidatedlineedit.cpp b/src/qt/qvalidatedlineedit.cpp index 4d6d5891c9..8a13cd340f 100644 --- a/src/qt/qvalidatedlineedit.cpp +++ b/src/qt/qvalidatedlineedit.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/qvaluecombobox.cpp b/src/qt/qvaluecombobox.cpp index af5f6f8fd0..72c3a9d835 100644 --- a/src/qt/qvaluecombobox.cpp +++ b/src/qt/qvaluecombobox.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/receivecoinsdialog.cpp b/src/qt/receivecoinsdialog.cpp index d6e2beb312..7fd5285467 100644 --- a/src/qt/receivecoinsdialog.cpp +++ b/src/qt/receivecoinsdialog.cpp @@ -1,14 +1,15 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 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 <wallet/wallet.h> + #include <qt/receivecoinsdialog.h> #include <qt/forms/ui_receivecoinsdialog.h> #include <qt/addressbookpage.h> #include <qt/addresstablemodel.h> #include <qt/bitcoinunits.h> -#include <qt/guiutil.h> #include <qt/optionsmodel.h> #include <qt/platformstyle.h> #include <qt/receiverequestdialog.h> @@ -17,7 +18,6 @@ #include <QAction> #include <QCursor> -#include <QItemSelection> #include <QMessageBox> #include <QScrollBar> #include <QTextDocument> @@ -93,6 +93,15 @@ void ReceiveCoinsDialog::setModel(WalletModel *_model) SLOT(recentRequestsView_selectionChanged(QItemSelection, QItemSelection))); // Last 2 columns are set by the columnResizingFixer, when the table geometry is ready. columnResizingFixer = new GUIUtil::TableViewLastColumnResizingFixer(tableView, AMOUNT_MINIMUM_COLUMN_WIDTH, DATE_COLUMN_WIDTH, this); + + // configure bech32 checkbox, disable if launched with legacy as default: + if (model->getDefaultAddressType() == OUTPUT_TYPE_BECH32) { + ui->useBech32->setCheckState(Qt::Checked); + } else { + ui->useBech32->setCheckState(Qt::Unchecked); + } + + ui->useBech32->setVisible(model->getDefaultAddressType() != OUTPUT_TYPE_LEGACY); } } @@ -135,7 +144,11 @@ void ReceiveCoinsDialog::on_receiveButton_clicked() QString address; QString label = ui->reqLabel->text(); /* Generate new receiving address */ - address = model->getAddressTableModel()->addRow(AddressTableModel::Receive, label, ""); + OutputType address_type = model->getDefaultAddressType(); + if (address_type != OUTPUT_TYPE_LEGACY) { + address_type = ui->useBech32->isChecked() ? OUTPUT_TYPE_BECH32 : OUTPUT_TYPE_P2SH_SEGWIT; + } + address = model->getAddressTableModel()->addRow(AddressTableModel::Receive, label, "", address_type); SendCoinsRecipient info(address, label, ui->reqAmount->value(), ui->reqMessage->text()); ReceiveRequestDialog *dialog = new ReceiveRequestDialog(this); diff --git a/src/qt/receivecoinsdialog.h b/src/qt/receivecoinsdialog.h index 3687cca87b..931f5aa101 100644 --- a/src/qt/receivecoinsdialog.h +++ b/src/qt/receivecoinsdialog.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/receiverequestdialog.cpp b/src/qt/receiverequestdialog.cpp index c69fea1c93..d4cb0e5ba2 100644 --- a/src/qt/receiverequestdialog.cpp +++ b/src/qt/receiverequestdialog.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -9,7 +9,6 @@ #include <qt/guiconstants.h> #include <qt/guiutil.h> #include <qt/optionsmodel.h> -#include <qt/walletmodel.h> #include <QClipboard> #include <QDrag> @@ -184,9 +183,13 @@ void ReceiveRequestDialog::update() QPainter painter(&qrAddrImage); painter.drawImage(0, 0, qrImage.scaled(QR_IMAGE_SIZE, QR_IMAGE_SIZE)); QFont font = GUIUtil::fixedPitchFont(); - font.setPixelSize(12); - painter.setFont(font); QRect paddedRect = qrAddrImage.rect(); + + // calculate ideal font size + qreal font_size = GUIUtil::calculateIdealFontSize(paddedRect.width() - 20, info.address, font); + font.setPointSizeF(font_size); + + painter.setFont(font); paddedRect.setHeight(QR_IMAGE_SIZE+12); painter.drawText(paddedRect, Qt::AlignBottom|Qt::AlignCenter, info.address); painter.end(); diff --git a/src/qt/receiverequestdialog.h b/src/qt/receiverequestdialog.h index 23b81135e2..21bbf1edb7 100644 --- a/src/qt/receiverequestdialog.h +++ b/src/qt/receiverequestdialog.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/recentrequeststablemodel.cpp b/src/qt/recentrequeststablemodel.cpp index 4d6e401d0d..0dd7d46960 100644 --- a/src/qt/recentrequeststablemodel.cpp +++ b/src/qt/recentrequeststablemodel.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -123,7 +123,7 @@ void RecentRequestsTableModel::updateAmountColumnTitle() /** Gets title for amount column including current display unit if optionsModel reference available. */ QString RecentRequestsTableModel::getAmountTitle() { - return (this->walletModel->getOptionsModel() != nullptr) ? tr("Requested") + " ("+BitcoinUnits::name(this->walletModel->getOptionsModel()->getDisplayUnit()) + ")" : ""; + return (this->walletModel->getOptionsModel() != nullptr) ? tr("Requested") + " ("+BitcoinUnits::shortName(this->walletModel->getOptionsModel()->getDisplayUnit()) + ")" : ""; } QModelIndex RecentRequestsTableModel::index(int row, int column, const QModelIndex &parent) const diff --git a/src/qt/recentrequeststablemodel.h b/src/qt/recentrequeststablemodel.h index c88b8c4426..ebad98cee8 100644 --- a/src/qt/recentrequeststablemodel.h +++ b/src/qt/recentrequeststablemodel.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index 6687d62baa..c4b209a880 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -11,7 +11,6 @@ #include <qt/bantablemodel.h> #include <qt/clientmodel.h> -#include <qt/guiutil.h> #include <qt/platformstyle.h> #include <chainparams.h> #include <netbase.h> @@ -35,7 +34,6 @@ #include <QScrollBar> #include <QSettings> #include <QSignalMapper> -#include <QThread> #include <QTime> #include <QTimer> #include <QStringList> @@ -392,11 +390,37 @@ void RPCExecutor::request(const QString &command) { std::string result; std::string executableCommand = command.toStdString() + "\n"; + + // Catch the console-only-help command before RPC call is executed and reply with help text as-if a RPC reply. + if(executableCommand == "help-console\n") + { + Q_EMIT reply(RPCConsole::CMD_REPLY, QString(("\n" + "This console accepts RPC commands using the standard syntax.\n" + " example: getblockhash 0\n\n" + + "This console can also accept RPC commands using parenthesized syntax.\n" + " example: getblockhash(0)\n\n" + + "Commands may be nested when specified with the parenthesized syntax.\n" + " example: getblock(getblockhash(0) 1)\n\n" + + "A space or a comma can be used to delimit arguments for either syntax.\n" + " example: getblockhash 0\n" + " getblockhash,0\n\n" + + "Named results can be queried with a non-quoted key string in brackets.\n" + " example: getblock(getblockhash(0) true)[tx]\n\n" + + "Results without keys can be queried using an integer in brackets.\n" + " example: getblock(getblockhash(0),true)[tx][0]\n\n"))); + return; + } 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) @@ -645,6 +669,7 @@ void RPCConsole::setClientModel(ClientModel *model) wordList << ("help " + commandList[i]).c_str(); } + wordList << "help-console"; wordList.sort(); autoCompleter = new QCompleter(wordList, this); autoCompleter->setModelSorting(QCompleter::CaseSensitivelySortedModel); @@ -750,10 +775,11 @@ void RPCConsole::clear(bool clearHistory) message(CMD_REPLY, (tr("Welcome to the %1 RPC console.").arg(tr(PACKAGE_NAME)) + "<br>" + tr("Use up and down arrows to navigate history, and %1 to clear screen.").arg("<b>"+clsKey+"</b>") + "<br>" + - tr("Type <b>help</b> for an overview of available commands.")) + - "<br><span class=\"secwarning\">" + + tr("Type %1 for an overview of available commands.").arg("<b>help</b>") + "<br>" + + tr("For more information on using this console type %1.").arg("<b>help-console</b>") + + "<br><span class=\"secwarning\"><br>" + tr("WARNING: Scammers have been active, telling users to type commands here, stealing their wallet contents. Do not use this console without fully understanding the ramifications of a command.") + - "</span>", + "</span>"), true); } diff --git a/src/qt/rpcconsole.h b/src/qt/rpcconsole.h index 5960410cdd..c41cbb0933 100644 --- a/src/qt/rpcconsole.h +++ b/src/qt/rpcconsole.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp index 036b6ebcc0..9fd61db70e 100644 --- a/src/qt/sendcoinsdialog.cpp +++ b/src/qt/sendcoinsdialog.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -13,7 +13,6 @@ #include <qt/optionsmodel.h> #include <qt/platformstyle.h> #include <qt/sendcoinsentry.h> -#include <qt/walletmodel.h> #include <base58.h> #include <chainparams.h> @@ -25,11 +24,9 @@ #include <wallet/fees.h> #include <QFontMetrics> -#include <QMessageBox> #include <QScrollBar> #include <QSettings> #include <QTextDocument> -#include <QTimer> static const std::array<int, 9> confTargets = { {2, 4, 6, 12, 24, 48, 144, 504, 1008} }; int getConfTargetForIndex(int index) { @@ -165,7 +162,7 @@ void SendCoinsDialog::setModel(WalletModel *_model) coinControlUpdateLabels(); // fee section - for (const int &n : confTargets) { + for (const int n : confTargets) { ui->confTargetSelector->addItem(tr("%1 (%2 blocks)").arg(GUIUtil::formatNiceTimeOffset(n*Params().GetConsensus().nPowTargetSpacing)).arg(n)); } connect(ui->confTargetSelector, SIGNAL(currentIndexChanged(int)), this, SLOT(updateSmartFeeLabel())); @@ -184,7 +181,7 @@ void SendCoinsDialog::setModel(WalletModel *_model) updateSmartFeeLabel(); // set default rbf checkbox state - ui->optInRBF->setCheckState(model->getDefaultWalletRbf() ? Qt::Checked : Qt::Unchecked); + ui->optInRBF->setCheckState(Qt::Checked); // set the smartfee-sliders default value (wallets default conf.target or last stored value) QSettings settings; @@ -339,15 +336,17 @@ void SendCoinsDialog::on_sendButton_clicked() } questionString.append(tr("Total Amount %1") .arg(BitcoinUnits::formatHtmlWithUnit(model->getOptionsModel()->getDisplayUnit(), totalAmount))); - questionString.append(QString("<span style='font-size:10pt;font-weight:normal;'><br />(=%2)</span>") + questionString.append(QString("<span style='font-size:10pt;font-weight:normal;'><br />(=%1)</span>") .arg(alternativeUnits.join(" " + tr("or") + "<br />"))); - if (ui->optInRBF->isChecked()) - { - questionString.append("<hr /><span>"); - questionString.append(tr("This transaction signals replaceability (optin-RBF).")); - questionString.append("</span>"); + questionString.append("<hr /><span>"); + if (ui->optInRBF->isChecked()) { + questionString.append(tr("You can increase the fee later (signals Replace-By-Fee, BIP-125).")); + } else { + questionString.append(tr("Not signalling Replace-By-Fee, BIP-125.")); } + questionString.append("</span>"); + SendConfirmationDialog confirmationDialog(tr("Confirm send coins"), questionString.arg(formatted.join("<br />")), SEND_CONFIRM_DELAY, this); diff --git a/src/qt/sendcoinsdialog.h b/src/qt/sendcoinsdialog.h index 300116fd9f..7c27785d12 100644 --- a/src/qt/sendcoinsdialog.h +++ b/src/qt/sendcoinsdialog.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/sendcoinsentry.cpp b/src/qt/sendcoinsentry.cpp index 20e39bdeba..b7decbb69b 100644 --- a/src/qt/sendcoinsentry.cpp +++ b/src/qt/sendcoinsentry.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -10,7 +10,6 @@ #include <qt/guiutil.h> #include <qt/optionsmodel.h> #include <qt/platformstyle.h> -#include <qt/walletmodel.h> #include <QApplication> #include <QClipboard> diff --git a/src/qt/sendcoinsentry.h b/src/qt/sendcoinsentry.h index b470a0d72e..a9fdd5938c 100644 --- a/src/qt/sendcoinsentry.h +++ b/src/qt/sendcoinsentry.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/signverifymessagedialog.cpp b/src/qt/signverifymessagedialog.cpp index 4cd0c76b16..364dcd6f45 100644 --- a/src/qt/signverifymessagedialog.cpp +++ b/src/qt/signverifymessagedialog.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/splashscreen.cpp b/src/qt/splashscreen.cpp index 5aa1de5553..fa3bd18d5a 100644 --- a/src/qt/splashscreen.cpp +++ b/src/qt/splashscreen.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/splashscreen.h b/src/qt/splashscreen.h index c6cfd503f7..e1568e406b 100644 --- a/src/qt/splashscreen.h +++ b/src/qt/splashscreen.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/test/compattests.cpp b/src/qt/test/compattests.cpp index 7a4388e940..3e601583c3 100644 --- a/src/qt/test/compattests.cpp +++ b/src/qt/test/compattests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2016 The Bitcoin Core developers +// Copyright (c) 2016-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/test/paymentservertests.cpp b/src/qt/test/paymentservertests.cpp index 1864604372..6e80625123 100644 --- a/src/qt/test/paymentservertests.cpp +++ b/src/qt/test/paymentservertests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2009-2015 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/test/paymentservertests.h b/src/qt/test/paymentservertests.h index 6d84c38287..f022d2687b 100644 --- a/src/qt/test/paymentservertests.h +++ b/src/qt/test/paymentservertests.h @@ -1,4 +1,4 @@ -// Copyright (c) 2009-2015 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/test/rpcnestedtests.cpp b/src/qt/test/rpcnestedtests.cpp index 0596ccf90e..aaec15cc13 100644 --- a/src/qt/test/rpcnestedtests.cpp +++ b/src/qt/test/rpcnestedtests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2016 The Bitcoin Core developers +// Copyright (c) 2016-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/test/rpcnestedtests.h b/src/qt/test/rpcnestedtests.h index 04a9d124aa..0ce1c66f44 100644 --- a/src/qt/test/rpcnestedtests.h +++ b/src/qt/test/rpcnestedtests.h @@ -1,4 +1,4 @@ -// Copyright (c) 2016 The Bitcoin Core developers +// Copyright (c) 2016-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/test/test_main.cpp b/src/qt/test/test_main.cpp index 2e11b4f4d6..25ee66dc6b 100644 --- a/src/qt/test/test_main.cpp +++ b/src/qt/test/test_main.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/test/uritests.cpp b/src/qt/test/uritests.cpp index e47aa8b546..8415250630 100644 --- a/src/qt/test/uritests.cpp +++ b/src/qt/test/uritests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2009-2014 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/test/wallettests.cpp b/src/qt/test/wallettests.cpp index 4b7c3bd726..cd49292138 100644 --- a/src/qt/test/wallettests.cpp +++ b/src/qt/test/wallettests.cpp @@ -149,6 +149,9 @@ void BumpFee(TransactionView& view, const uint256& txid, bool expectDisabled, st // src/qt/test/test_bitcoin-qt -platform cocoa # macOS void TestGUI() { + g_address_type = OUTPUT_TYPE_P2SH_SEGWIT; + g_change_type = OUTPUT_TYPE_P2SH_SEGWIT; + // Set up wallet and chain with 105 blocks (5 mature blocks for spending). TestChain100Setup test; for (int i = 0; i < 5; ++i) { @@ -161,12 +164,14 @@ void TestGUI() wallet.LoadWallet(firstRun); { LOCK(wallet.cs_wallet); - wallet.SetAddressBook(test.coinbaseKey.GetPubKey().GetID(), "", "receive"); + wallet.SetAddressBook(GetDestinationForKey(test.coinbaseKey.GetPubKey(), g_address_type), "", "receive"); wallet.AddKeyPubKey(test.coinbaseKey, test.coinbaseKey.GetPubKey()); } { LOCK(cs_main); - wallet.ScanForWalletTransactions(chainActive.Genesis(), nullptr, true); + WalletRescanReserver reserver(&wallet); + reserver.reserve(); + wallet.ScanForWalletTransactions(chainActive.Genesis(), nullptr, reserver, true); } wallet.SetBroadcastTransactions(true); diff --git a/src/qt/trafficgraphwidget.cpp b/src/qt/trafficgraphwidget.cpp index b5e4ccb406..f869799462 100644 --- a/src/qt/trafficgraphwidget.cpp +++ b/src/qt/trafficgraphwidget.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp index 3f245e6c33..c1d28be0ab 100644 --- a/src/qt/transactiondesc.cpp +++ b/src/qt/transactiondesc.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/transactiondescdialog.cpp b/src/qt/transactiondescdialog.cpp index 74d7a8f525..161fccd462 100644 --- a/src/qt/transactiondescdialog.cpp +++ b/src/qt/transactiondescdialog.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/transactionfilterproxy.cpp b/src/qt/transactionfilterproxy.cpp index 15859bf36d..39d03fa547 100644 --- a/src/qt/transactionfilterproxy.cpp +++ b/src/qt/transactionfilterproxy.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -9,8 +9,6 @@ #include <cstdlib> -#include <QDateTime> - // Earliest date that can be represented (far in the past) const QDateTime TransactionFilterProxy::MIN_DATE = QDateTime::fromTime_t(0); // Last date that can be represented (far in the future) @@ -20,7 +18,7 @@ TransactionFilterProxy::TransactionFilterProxy(QObject *parent) : QSortFilterProxyModel(parent), dateFrom(MIN_DATE), dateTo(MAX_DATE), - addrPrefix(), + m_search_string(), typeFilter(ALL_TYPES), watchOnlyFilter(WatchOnlyFilter_All), minAmount(0), @@ -38,6 +36,7 @@ bool TransactionFilterProxy::filterAcceptsRow(int sourceRow, const QModelIndex & bool involvesWatchAddress = index.data(TransactionTableModel::WatchonlyRole).toBool(); QString address = index.data(TransactionTableModel::AddressRole).toString(); QString label = index.data(TransactionTableModel::LabelRole).toString(); + QString txid = index.data(TransactionTableModel::TxIDRole).toString(); qint64 amount = llabs(index.data(TransactionTableModel::AmountRole).toLongLong()); int status = index.data(TransactionTableModel::StatusRole).toInt(); @@ -51,8 +50,11 @@ bool TransactionFilterProxy::filterAcceptsRow(int sourceRow, const QModelIndex & return false; if(datetime < dateFrom || datetime > dateTo) return false; - if (!address.contains(addrPrefix, Qt::CaseInsensitive) && !label.contains(addrPrefix, Qt::CaseInsensitive)) + if (!address.contains(m_search_string, Qt::CaseInsensitive) && + ! label.contains(m_search_string, Qt::CaseInsensitive) && + ! txid.contains(m_search_string, Qt::CaseInsensitive)) { return false; + } if(amount < minAmount) return false; @@ -66,9 +68,10 @@ void TransactionFilterProxy::setDateRange(const QDateTime &from, const QDateTime invalidateFilter(); } -void TransactionFilterProxy::setAddressPrefix(const QString &_addrPrefix) +void TransactionFilterProxy::setSearchString(const QString &search_string) { - this->addrPrefix = _addrPrefix; + if (m_search_string == search_string) return; + m_search_string = search_string; invalidateFilter(); } diff --git a/src/qt/transactionfilterproxy.h b/src/qt/transactionfilterproxy.h index 4bdd9ea6c7..226cf3f3b5 100644 --- a/src/qt/transactionfilterproxy.h +++ b/src/qt/transactionfilterproxy.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2014 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -35,7 +35,7 @@ public: }; void setDateRange(const QDateTime &from, const QDateTime &to); - void setAddressPrefix(const QString &addrPrefix); + void setSearchString(const QString &); /** @note Type filter takes a bit field created with TYPE() or ALL_TYPES */ @@ -57,7 +57,7 @@ protected: private: QDateTime dateFrom; QDateTime dateTo; - QString addrPrefix; + QString m_search_string; quint32 typeFilter; WatchOnlyFilter watchOnlyFilter; CAmount minAmount; diff --git a/src/qt/transactionrecord.cpp b/src/qt/transactionrecord.cpp index e3e8377cb9..de3e885e8f 100644 --- a/src/qt/transactionrecord.cpp +++ b/src/qt/transactionrecord.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/transactionrecord.h b/src/qt/transactionrecord.h index ee85acf4ac..29a3cd8de7 100644 --- a/src/qt/transactionrecord.h +++ b/src/qt/transactionrecord.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/transactiontablemodel.cpp b/src/qt/transactiontablemodel.cpp index cc0dc5ef48..626d4c0bdc 100644 --- a/src/qt/transactiontablemodel.cpp +++ b/src/qt/transactiontablemodel.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -80,10 +80,10 @@ public: cachedWallet.clear(); { LOCK2(cs_main, wallet->cs_wallet); - for(std::map<uint256, CWalletTx>::iterator it = wallet->mapWallet.begin(); it != wallet->mapWallet.end(); ++it) + for (const auto& entry : wallet->mapWallet) { - if(TransactionRecord::showTransaction(it->second)) - cachedWallet.append(TransactionRecord::decomposeTransaction(wallet, it->second)); + if (TransactionRecord::showTransaction(entry.second)) + cachedWallet.append(TransactionRecord::decomposeTransaction(wallet, entry.second)); } } } diff --git a/src/qt/transactiontablemodel.h b/src/qt/transactiontablemodel.h index a769707163..8f58962d17 100644 --- a/src/qt/transactiontablemodel.h +++ b/src/qt/transactiontablemodel.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/transactionview.cpp b/src/qt/transactionview.cpp index 92e8e91600..fa43ab750a 100644 --- a/src/qt/transactionview.cpp +++ b/src/qt/transactionview.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -8,7 +8,6 @@ #include <qt/bitcoinunits.h> #include <qt/csvmodelwriter.h> #include <qt/editaddressdialog.h> -#include <qt/guiutil.h> #include <qt/optionsmodel.h> #include <qt/platformstyle.h> #include <qt/sendcoinsdialog.h> @@ -95,11 +94,11 @@ TransactionView::TransactionView(const PlatformStyle *platformStyle, QWidget *pa hlayout->addWidget(typeWidget); - addressWidget = new QLineEdit(this); + search_widget = new QLineEdit(this); #if QT_VERSION >= 0x040700 - addressWidget->setPlaceholderText(tr("Enter address or label to search")); + search_widget->setPlaceholderText(tr("Enter address, transaction id, or label to search")); #endif - hlayout->addWidget(addressWidget); + hlayout->addWidget(search_widget); amountWidget = new QLineEdit(this); #if QT_VERSION >= 0x040700 @@ -187,8 +186,8 @@ TransactionView::TransactionView(const PlatformStyle *platformStyle, QWidget *pa connect(watchOnlyWidget, SIGNAL(activated(int)), this, SLOT(chooseWatchonly(int))); connect(amountWidget, SIGNAL(textChanged(QString)), amount_typing_delay, SLOT(start())); connect(amount_typing_delay, SIGNAL(timeout()), this, SLOT(changedAmount())); - connect(addressWidget, SIGNAL(textChanged(QString)), prefix_typing_delay, SLOT(start())); - connect(prefix_typing_delay, SIGNAL(timeout()), this, SLOT(changedPrefix())); + connect(search_widget, SIGNAL(textChanged(QString)), prefix_typing_delay, SLOT(start())); + connect(prefix_typing_delay, SIGNAL(timeout()), this, SLOT(changedSearch())); connect(view, SIGNAL(doubleClicked(QModelIndex)), this, SIGNAL(doubleClicked(QModelIndex))); connect(view, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(contextualMenu(QPoint))); @@ -326,11 +325,11 @@ void TransactionView::chooseWatchonly(int idx) (TransactionFilterProxy::WatchOnlyFilter)watchOnlyWidget->itemData(idx).toInt()); } -void TransactionView::changedPrefix() +void TransactionView::changedSearch() { if(!transactionProxyModel) return; - transactionProxyModel->setAddressPrefix(addressWidget->text()); + transactionProxyModel->setSearchString(search_widget->text()); } void TransactionView::changedAmount() @@ -366,7 +365,7 @@ void TransactionView::exportClicked() // name, column, role writer.setModel(transactionProxyModel); writer.addColumn(tr("Confirmed"), 0, TransactionTableModel::ConfirmedRole); - if (model && model->haveWatchOnly()) + if (model->haveWatchOnly()) writer.addColumn(tr("Watch-only"), TransactionTableModel::Watchonly); writer.addColumn(tr("Date"), 0, TransactionTableModel::DateRole); writer.addColumn(tr("Type"), TransactionTableModel::Type, Qt::EditRole); diff --git a/src/qt/transactionview.h b/src/qt/transactionview.h index 5b28b34723..82e929b53f 100644 --- a/src/qt/transactionview.h +++ b/src/qt/transactionview.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -66,7 +66,7 @@ private: QComboBox *dateWidget; QComboBox *typeWidget; QComboBox *watchOnlyWidget; - QLineEdit *addressWidget; + QLineEdit *search_widget; QLineEdit *amountWidget; QMenu *contextMenu; @@ -113,7 +113,7 @@ public Q_SLOTS: void chooseType(int idx); void chooseWatchonly(int idx); void changedAmount(); - void changedPrefix(); + void changedSearch(); void exportClicked(); void focusTransaction(const QModelIndex&); diff --git a/src/qt/utilitydialog.cpp b/src/qt/utilitydialog.cpp index 6d5a2f3101..5d4a92f760 100644 --- a/src/qt/utilitydialog.cpp +++ b/src/qt/utilitydialog.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/utilitydialog.h b/src/qt/utilitydialog.h index 738eeed136..d43d9a82c0 100644 --- a/src/qt/utilitydialog.h +++ b/src/qt/utilitydialog.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/walletframe.cpp b/src/qt/walletframe.cpp index 573b3f1412..c0b9d04269 100644 --- a/src/qt/walletframe.cpp +++ b/src/qt/walletframe.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index a38e233608..4d7e977fcb 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -733,12 +733,12 @@ bool WalletModel::hdEnabled() const return wallet->IsHDEnabled(); } -int WalletModel::getDefaultConfirmTarget() const +OutputType WalletModel::getDefaultAddressType() const { - return nTxConfirmTarget; + return g_address_type; } -bool WalletModel::getDefaultWalletRbf() const +int WalletModel::getDefaultConfirmTarget() const { - return fWalletRbf; + return nTxConfirmTarget; } diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h index 028146c187..9e13de79be 100644 --- a/src/qt/walletmodel.h +++ b/src/qt/walletmodel.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -15,6 +15,8 @@ #include <QObject> +enum OutputType : int; + class AddressTableModel; class OptionsModel; class PlatformStyle; @@ -214,9 +216,9 @@ public: bool hdEnabled() const; - int getDefaultConfirmTarget() const; + OutputType getDefaultAddressType() const; - bool getDefaultWalletRbf() const; + int getDefaultConfirmTarget() const; private: CWallet *wallet; diff --git a/src/qt/walletmodeltransaction.cpp b/src/qt/walletmodeltransaction.cpp index 2188b39b92..4b2bef2690 100644 --- a/src/qt/walletmodeltransaction.cpp +++ b/src/qt/walletmodeltransaction.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/walletmodeltransaction.h b/src/qt/walletmodeltransaction.h index 519cf9df99..cd531dba4b 100644 --- a/src/qt/walletmodeltransaction.h +++ b/src/qt/walletmodeltransaction.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2014 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/walletview.cpp b/src/qt/walletview.cpp index a589fad9bd..7eced9289d 100644 --- a/src/qt/walletview.cpp +++ b/src/qt/walletview.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/walletview.h b/src/qt/walletview.h index 4c90874135..30d68e4eff 100644 --- a/src/qt/walletview.h +++ b/src/qt/walletview.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/winshutdownmonitor.cpp b/src/qt/winshutdownmonitor.cpp index aa6c273431..1e7a76efc0 100644 --- a/src/qt/winshutdownmonitor.cpp +++ b/src/qt/winshutdownmonitor.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2016 The Bitcoin Core developers +// Copyright (c) 2014-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/random.cpp b/src/random.cpp index 3075a77182..a845526d8a 100644 --- a/src/random.cpp +++ b/src/random.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/random.h b/src/random.h index 9309917689..ea88670a37 100644 --- a/src/random.h +++ b/src/random.h @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -128,7 +128,7 @@ public: * sure that the underlying OS APIs for all platforms support the number. * (many cap out at 256 bytes). */ -static const ssize_t NUM_OS_RANDOM_BYTES = 32; +static const int NUM_OS_RANDOM_BYTES = 32; /** Get 32 bytes of system entropy. Do not use this in application code: use * GetStrongRandBytes instead. diff --git a/src/rest.cpp b/src/rest.cpp index 86ee7804a3..30e481171f 100644 --- a/src/rest.cpp +++ b/src/rest.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -423,8 +423,8 @@ static bool rest_getutxos(HTTPRequest* req, const std::string& strURIPart) { uint256 txid; int32_t nOutput; - std::string strTxid = uriParts[i].substr(0, uriParts[i].find("-")); - std::string strOutput = uriParts[i].substr(uriParts[i].find("-")+1); + std::string strTxid = uriParts[i].substr(0, uriParts[i].find('-')); + std::string strOutput = uriParts[i].substr(uriParts[i].find('-')+1); if (!ParseInt32(strOutput, &nOutput) || !IsHex(strTxid)) return RESTERR(req, HTTP_BAD_REQUEST, "Parse error"); diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 601965d4c4..346672e45a 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -24,6 +24,7 @@ #include <util.h> #include <utilstrencodings.h> #include <hash.h> +#include <validationinterface.h> #include <warnings.h> #include <stdint.h> @@ -47,18 +48,20 @@ static CUpdatedBlock latestblock; extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry); -double GetDifficulty(const CBlockIndex* blockindex) +/* Calculate the difficulty for a given block index, + * or the block index of the given chain. + */ +double GetDifficulty(const CChain& chain, const CBlockIndex* blockindex) { if (blockindex == nullptr) { - if (chainActive.Tip() == nullptr) + if (chain.Tip() == nullptr) return 1.0; else - blockindex = chainActive.Tip(); + blockindex = chain.Tip(); } int nShift = (blockindex->nBits >> 24) & 0xff; - double dDiff = (double)0x0000ffff / (double)(blockindex->nBits & 0x00ffffff); @@ -76,6 +79,11 @@ double GetDifficulty(const CBlockIndex* blockindex) return dDiff; } +double GetDifficulty(const CBlockIndex* blockindex) +{ + return GetDifficulty(chainActive, blockindex); +} + UniValue blockheaderToJSON(const CBlockIndex* blockindex) { AssertLockHeld(cs_main); @@ -316,6 +324,21 @@ UniValue waitforblockheight(const JSONRPCRequest& request) return ret; } +UniValue syncwithvalidationinterfacequeue(const JSONRPCRequest& request) +{ + if (request.fHelp || request.params.size() > 0) { + throw std::runtime_error( + "syncwithvalidationinterfacequeue\n" + "\nWaits for the validation interface queue to catch up on everything that was there when we entered this function.\n" + "\nExamples:\n" + + HelpExampleCli("syncwithvalidationinterfacequeue","") + + HelpExampleRpc("syncwithvalidationinterfacequeue","") + ); + } + SyncWithValidationInterfaceQueue(); + return NullUniValue; +} + UniValue getdifficulty(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 0) @@ -1113,13 +1136,13 @@ static UniValue BIP9SoftForkDesc(const Consensus::Params& consensusParams, Conse return rv; } -void BIP9SoftForkDescPushBack(UniValue& bip9_softforks, const std::string &name, const Consensus::Params& consensusParams, Consensus::DeploymentPos id) +void BIP9SoftForkDescPushBack(UniValue& bip9_softforks, const Consensus::Params& consensusParams, Consensus::DeploymentPos id) { // Deployments with timeout value of 0 are hidden. // A timeout value of 0 guarantees a softfork will never be activated. // This is used when softfork codes are merged without specifying the deployment schedule. if (consensusParams.vDeployments[id].nTimeout > 0) - bip9_softforks.push_back(Pair(name, BIP9SoftForkDesc(consensusParams, id))); + bip9_softforks.push_back(Pair(VersionBitsDeploymentInfo[id].name, BIP9SoftForkDesc(consensusParams, id))); } UniValue getblockchaininfo(const JSONRPCRequest& request) @@ -1214,8 +1237,9 @@ UniValue getblockchaininfo(const JSONRPCRequest& request) softforks.push_back(SoftForkDesc("bip34", 2, tip, consensusParams)); softforks.push_back(SoftForkDesc("bip66", 3, tip, consensusParams)); softforks.push_back(SoftForkDesc("bip65", 4, tip, consensusParams)); - BIP9SoftForkDescPushBack(bip9_softforks, "csv", consensusParams, Consensus::DEPLOYMENT_CSV); - BIP9SoftForkDescPushBack(bip9_softforks, "segwit", consensusParams, Consensus::DEPLOYMENT_SEGWIT); + for (int pos = Consensus::DEPLOYMENT_CSV; pos != Consensus::MAX_VERSION_BITS_DEPLOYMENTS; ++pos) { + BIP9SoftForkDescPushBack(bip9_softforks, consensusParams, static_cast<Consensus::DeploymentPos>(pos)); + } obj.push_back(Pair("softforks", softforks)); obj.push_back(Pair("bip9_softforks", bip9_softforks)); @@ -1349,7 +1373,8 @@ UniValue mempoolInfoToJSON() ret.push_back(Pair("usage", (int64_t) mempool.DynamicMemoryUsage())); size_t maxmempool = gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000; ret.push_back(Pair("maxmempool", (int64_t) maxmempool)); - ret.push_back(Pair("mempoolminfee", ValueFromAmount(mempool.GetMinFee(maxmempool).GetFeePerK()))); + ret.push_back(Pair("mempoolminfee", ValueFromAmount(std::max(mempool.GetMinFee(maxmempool), ::minRelayTxFee).GetFeePerK()))); + ret.push_back(Pair("minrelaytxfee", ValueFromAmount(::minRelayTxFee.GetFeePerK()))); return ret; } @@ -1366,7 +1391,8 @@ UniValue getmempoolinfo(const JSONRPCRequest& request) " \"bytes\": xxxxx, (numeric) Sum of all virtual transaction sizes as defined in BIP 141. Differs from actual serialized size because witness data is discounted\n" " \"usage\": xxxxx, (numeric) Total memory usage for the mempool\n" " \"maxmempool\": xxxxx, (numeric) Maximum memory usage for the mempool\n" - " \"mempoolminfee\": xxxxx (numeric) Minimum fee rate in " + CURRENCY_UNIT + "/kB for tx to be accepted\n" + " \"mempoolminfee\": xxxxx (numeric) Minimum fee rate in " + CURRENCY_UNIT + "/kB for tx to be accepted. Is the maximum of minrelaytxfee and minimum mempool fee\n" + " \"minrelaytxfee\": xxxxx (numeric) Current minimum relay fee for transactions\n" "}\n" "\nExamples:\n" + HelpExampleCli("getmempoolinfo", "") @@ -1618,6 +1644,7 @@ static const CRPCCommand commands[] = { "hidden", "waitfornewblock", &waitfornewblock, {"timeout"} }, { "hidden", "waitforblock", &waitforblock, {"blockhash","timeout"} }, { "hidden", "waitforblockheight", &waitforblockheight, {"height","timeout"} }, + { "hidden", "syncwithvalidationinterfacequeue", &syncwithvalidationinterfacequeue, {} }, }; void RegisterBlockchainRPCCommands(CRPCTable &t) diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp index a595b6ec27..b88c1bccd5 100644 --- a/src/rpc/client.cpp +++ b/src/rpc/client.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -10,8 +10,6 @@ #include <set> #include <stdint.h> -#include <univalue.h> - class CRPCConvertParam { public: @@ -93,11 +91,13 @@ static const CRPCConvertParam vRPCConvertParams[] = { "createrawtransaction", 1, "outputs" }, { "createrawtransaction", 2, "locktime" }, { "createrawtransaction", 3, "replaceable" }, + { "decoderawtransaction", 1, "iswitness" }, { "signrawtransaction", 1, "prevtxs" }, { "signrawtransaction", 2, "privkeys" }, { "sendrawtransaction", 1, "allowhighfees" }, { "combinerawtransaction", 0, "txs" }, { "fundrawtransaction", 1, "options" }, + { "fundrawtransaction", 2, "iswitness" }, { "gettxout", 1, "n" }, { "gettxout", 2, "include_mempool" }, { "gettxoutproof", 0, "txids" }, @@ -213,7 +213,7 @@ UniValue RPCConvertNamedValues(const std::string &strMethod, const std::vector<s UniValue params(UniValue::VOBJ); for (const std::string &s: strParams) { - size_t pos = s.find("="); + size_t pos = s.find('='); if (pos == std::string::npos) { throw(std::runtime_error("No '=' in named argument '"+s+"', this needs to be present for every argument (even if it is empty)")); } diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 1753ecd3fc..c22d0ac377 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -29,8 +29,6 @@ #include <memory> #include <stdint.h> -#include <univalue.h> - unsigned int ParseConfirmTarget(const UniValue& value) { int target = value.get_int(); diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index b3e22f5f10..c11dda22c4 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -15,6 +15,7 @@ #include <netbase.h> #include <rpc/blockchain.h> #include <rpc/server.h> +#include <rpc/util.h> #include <timedata.h> #include <util.h> #include <utilstrencodings.h> @@ -40,6 +41,46 @@ public: explicit DescribeAddressVisitor(CWallet *_pwallet) : pwallet(_pwallet) {} + void ProcessSubScript(const CScript& subscript, UniValue& obj, bool include_addresses = false) const + { + // Always present: script type and redeemscript + txnouttype which_type; + std::vector<std::vector<unsigned char>> solutions_data; + Solver(subscript, which_type, solutions_data); + obj.pushKV("script", GetTxnOutputType(which_type)); + obj.pushKV("hex", HexStr(subscript.begin(), subscript.end())); + + CTxDestination embedded; + UniValue a(UniValue::VARR); + if (ExtractDestination(subscript, embedded)) { + // Only when the script corresponds to an address. + UniValue subobj = boost::apply_visitor(*this, embedded); + subobj.pushKV("address", EncodeDestination(embedded)); + subobj.pushKV("scriptPubKey", HexStr(subscript.begin(), subscript.end())); + // Always report the pubkey at the top level, so that `getnewaddress()['pubkey']` always works. + if (subobj.exists("pubkey")) obj.pushKV("pubkey", subobj["pubkey"]); + obj.pushKV("embedded", std::move(subobj)); + if (include_addresses) a.push_back(EncodeDestination(embedded)); + } else if (which_type == TX_MULTISIG) { + // Also report some information on multisig scripts (which do not have a corresponding address). + // TODO: abstract out the common functionality between this logic and ExtractDestinations. + obj.pushKV("sigsrequired", solutions_data[0][0]); + UniValue pubkeys(UniValue::VARR); + for (size_t i = 1; i < solutions_data.size() - 1; ++i) { + CPubKey key(solutions_data[i].begin(), solutions_data[i].end()); + if (include_addresses) a.push_back(EncodeDestination(key.GetID())); + pubkeys.push_back(HexStr(key.begin(), key.end())); + } + obj.pushKV("pubkeys", std::move(pubkeys)); + } + + // The "addresses" field is confusing because it refers to public keys using their P2PKH address. + // For that reason, only add the 'addresses' field when needed for backward compatibility. New applications + // can use the 'embedded'->'address' field for P2SH or P2WSH wrapped addresses, and 'pubkeys' for + // inspecting multisig participants. + if (include_addresses) obj.pushKV("addresses", std::move(a)); + } + UniValue operator()(const CNoDestination &dest) const { return UniValue(UniValue::VOBJ); } UniValue operator()(const CKeyID &keyID) const { @@ -60,19 +101,7 @@ public: obj.push_back(Pair("isscript", true)); obj.push_back(Pair("iswitness", false)); if (pwallet && pwallet->GetCScript(scriptID, subscript)) { - std::vector<CTxDestination> addresses; - txnouttype whichType; - int nRequired; - ExtractDestinations(subscript, whichType, addresses, nRequired); - obj.push_back(Pair("script", GetTxnOutputType(whichType))); - obj.push_back(Pair("hex", HexStr(subscript.begin(), subscript.end()))); - UniValue a(UniValue::VARR); - for (const CTxDestination& addr : addresses) { - a.push_back(EncodeDestination(addr)); - } - obj.push_back(Pair("addresses", a)); - if (whichType == TX_MULTISIG) - obj.push_back(Pair("sigsrequired", nRequired)); + ProcessSubScript(subscript, obj, true); } return obj; } @@ -103,7 +132,7 @@ public: uint160 hash; hasher.Write(id.begin(), 32).Finalize(hash.begin()); if (pwallet && pwallet->GetCScript(CScriptID(hash), subscript)) { - obj.push_back(Pair("hex", HexStr(subscript.begin(), subscript.end()))); + ProcessSubScript(subscript, obj); } return obj; } @@ -131,23 +160,32 @@ UniValue validateaddress(const JSONRPCRequest& request) "\nResult:\n" "{\n" " \"isvalid\" : true|false, (boolean) If the address is valid or not. If not, this is the only property returned.\n" - " \"address\" : \"address\", (string) The bitcoin address validated\n" + " \"address\" : \"address\", (string) The bitcoin address validated\n" " \"scriptPubKey\" : \"hex\", (string) The hex encoded scriptPubKey generated by the address\n" " \"ismine\" : true|false, (boolean) If the address is yours or not\n" " \"iswatchonly\" : true|false, (boolean) If the address is watchonly\n" - " \"isscript\" : true|false, (boolean) If the key is a script\n" - " \"script\" : \"type\" (string, optional) The output script type. Possible types: nonstandard, pubkey, pubkeyhash, scripthash, multisig, nulldata, witness_v0_keyhash, witness_v0_scripthash\n" - " \"hex\" : \"hex\", (string, optional) The redeemscript for the p2sh address\n" - " \"addresses\" (string, optional) Array of addresses associated with the known redeemscript\n" + " \"isscript\" : true|false, (boolean, optional) If the address is P2SH or P2WSH. Not included for unknown witness types.\n" + " \"iswitness\" : true|false, (boolean) If the address is P2WPKH, P2WSH, or an unknown witness version\n" + " \"witness_version\" : version (number, optional) For all witness output types, gives the version number.\n" + " \"witness_program\" : \"hex\" (string, optional) For all witness output types, gives the script or key hash present in the address.\n" + " \"script\" : \"type\" (string, optional) The output script type. Only if \"isscript\" is true and the redeemscript is known. Possible types: nonstandard, pubkey, pubkeyhash, scripthash, multisig, nulldata, witness_v0_keyhash, witness_v0_scripthash, witness_unknown\n" + " \"hex\" : \"hex\", (string, optional) The redeemscript for the P2SH or P2WSH address\n" + " \"addresses\" (string, optional) Array of addresses associated with the known redeemscript (only if \"iswitness\" is false). This field is superseded by the \"pubkeys\" field and the address inside \"embedded\".\n" " [\n" " \"address\"\n" " ,...\n" " ]\n" - " \"sigsrequired\" : xxxxx (numeric, optional) Number of signatures required to spend multisig output\n" - " \"pubkey\" : \"publickeyhex\", (string) The hex value of the raw public key\n" + " \"pubkeys\" (string, optional) Array of pubkeys associated with the known redeemscript (only if \"script\" is \"multisig\")\n" + " [\n" + " \"pubkey\"\n" + " ,...\n" + " ]\n" + " \"sigsrequired\" : xxxxx (numeric, optional) Number of signatures required to spend multisig output (only if \"script\" is \"multisig\")\n" + " \"pubkey\" : \"publickeyhex\", (string, optional) The hex value of the raw public key, for single-key addresses (possibly embedded in P2SH or P2WSH)\n" + " \"embedded\" : {...}, (object, optional) information about the address embedded in P2SH or P2WSH, if relevant and known. It includes all validateaddress output fields for the embedded address, excluding \"isvalid\", metadata (\"timestamp\", \"hdkeypath\", \"hdmasterkeyid\") and relation to the wallet (\"ismine\", \"iswatchonly\", \"account\").\n" " \"iscompressed\" : true|false, (boolean) If the address is compressed\n" " \"account\" : \"account\" (string) DEPRECATED. The account associated with the address, \"\" is the default account\n" - " \"timestamp\" : timestamp, (number, optional) The creation time of the key if available in seconds since epoch (Jan 1 1970 GMT)\n" + " \"timestamp\" : timestamp, (number, optional) The creation time of the key if available in seconds since epoch (Jan 1 1970 GMT)\n" " \"hdkeypath\" : \"keypath\" (string, optional) The HD keypath if the key is HD and available\n" " \"hdmasterkeyid\" : \"<hash160>\" (string, optional) The Hash160 of the HD master pubkey\n" "}\n" @@ -187,17 +225,25 @@ UniValue validateaddress(const JSONRPCRequest& request) ret.push_back(Pair("account", pwallet->mapAddressBook[dest].name)); } if (pwallet) { - const auto& meta = pwallet->mapKeyMetadata; - const CKeyID *keyID = boost::get<CKeyID>(&dest); - auto it = keyID ? meta.find(*keyID) : meta.end(); - if (it == meta.end()) { - it = meta.find(CScriptID(scriptPubKey)); + const CKeyMetadata* meta = nullptr; + CKeyID key_id = GetKeyForDestination(*pwallet, dest); + if (!key_id.IsNull()) { + auto it = pwallet->mapKeyMetadata.find(key_id); + if (it != pwallet->mapKeyMetadata.end()) { + meta = &it->second; + } } - if (it != meta.end()) { - ret.push_back(Pair("timestamp", it->second.nCreateTime)); - if (!it->second.hdKeypath.empty()) { - ret.push_back(Pair("hdkeypath", it->second.hdKeypath)); - ret.push_back(Pair("hdmasterkeyid", it->second.hdMasterKeyID.GetHex())); + if (!meta) { + auto it = pwallet->m_script_metadata.find(CScriptID(scriptPubKey)); + if (it != pwallet->m_script_metadata.end()) { + meta = &it->second; + } + } + if (meta) { + ret.push_back(Pair("timestamp", meta->nCreateTime)); + if (!meta->hdKeypath.empty()) { + ret.push_back(Pair("hdkeypath", meta->hdKeypath)); + ret.push_back(Pair("hdmasterkeyid", meta->hdMasterKeyID.GetHex())); } } } @@ -209,88 +255,21 @@ UniValue validateaddress(const JSONRPCRequest& request) // Needed even with !ENABLE_WALLET, to pass (ignored) pointers around class CWallet; -/** - * Used by addmultisigaddress / createmultisig: - */ -CScript _createmultisig_redeemScript(CWallet * const pwallet, const UniValue& params) -{ - int nRequired = params[0].get_int(); - const UniValue& keys = params[1].get_array(); - - // Gather public keys - if (nRequired < 1) - throw std::runtime_error("a multisignature address must require at least one key to redeem"); - if ((int)keys.size() < nRequired) - throw std::runtime_error( - strprintf("not enough keys supplied " - "(got %u keys, but need at least %d to redeem)", keys.size(), nRequired)); - if (keys.size() > 16) - throw std::runtime_error("Number of addresses involved in the multisignature address creation > 16\nReduce the number"); - std::vector<CPubKey> pubkeys; - pubkeys.resize(keys.size()); - for (unsigned int i = 0; i < keys.size(); i++) - { - const std::string& ks = keys[i].get_str(); -#ifdef ENABLE_WALLET - // Case 1: Bitcoin address and we have full public key: - CTxDestination dest = DecodeDestination(ks); - if (pwallet && IsValidDestination(dest)) { - const CKeyID *keyID = boost::get<CKeyID>(&dest); - if (!keyID) { - throw std::runtime_error(strprintf("%s does not refer to a key", ks)); - } - CPubKey vchPubKey; - if (!pwallet->GetPubKey(*keyID, vchPubKey)) { - throw std::runtime_error(strprintf("no full public key for address %s", ks)); - } - if (!vchPubKey.IsFullyValid()) - throw std::runtime_error(" Invalid public key: "+ks); - pubkeys[i] = vchPubKey; - } - - // Case 2: hex public key - else -#endif - if (IsHex(ks)) - { - CPubKey vchPubKey(ParseHex(ks)); - if (!vchPubKey.IsFullyValid()) - throw std::runtime_error(" Invalid public key: "+ks); - pubkeys[i] = vchPubKey; - } - else - { - throw std::runtime_error(" Invalid public key: "+ks); - } - } - CScript result = GetScriptForMultisig(nRequired, pubkeys); - - if (result.size() > MAX_SCRIPT_ELEMENT_SIZE) - throw std::runtime_error( - strprintf("redeemScript exceeds size limit: %d > %d", result.size(), MAX_SCRIPT_ELEMENT_SIZE)); - - return result; -} - UniValue createmultisig(const JSONRPCRequest& request) { -#ifdef ENABLE_WALLET - CWallet * const pwallet = GetWalletForJSONRPCRequest(request); -#else - CWallet * const pwallet = nullptr; -#endif - if (request.fHelp || request.params.size() < 2 || request.params.size() > 2) { std::string msg = "createmultisig nrequired [\"key\",...]\n" "\nCreates a multi-signature address with n signature of m keys required.\n" "It returns a json object with the address and redeemScript.\n" - + "DEPRECATION WARNING: Using addresses with createmultisig is deprecated. Clients must\n" + "transition to using addmultisigaddress to create multisig addresses with addresses known\n" + "to the wallet before upgrading to v0.17. To use the deprecated functionality, start bitcoind with -deprecatedrpc=createmultisig\n" "\nArguments:\n" - "1. nrequired (numeric, required) The number of required signatures out of the n keys or addresses.\n" - "2. \"keys\" (string, required) A json array of keys which are bitcoin addresses or hex-encoded public keys\n" + "1. nrequired (numeric, required) The number of required signatures out of the n keys or addresses.\n" + "2. \"keys\" (string, required) A json array of hex-encoded public keys\n" " [\n" - " \"key\" (string) bitcoin address or hex-encoded public key\n" + " \"key\" (string) The hex-encoded public key\n" " ,...\n" " ]\n" @@ -301,16 +280,37 @@ UniValue createmultisig(const JSONRPCRequest& request) "}\n" "\nExamples:\n" - "\nCreate a multisig address from 2 addresses\n" - + HelpExampleCli("createmultisig", "2 \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"") + + "\nCreate a multisig address from 2 public keys\n" + + HelpExampleCli("createmultisig", "2 \"[\\\"03789ed0bb717d88f7d321a368d905e7430207ebbd82bd342cf11ae157a7ace5fd\\\",\\\"03dbc6764b8884a92e871274b87583e6d5c2a58819473e17e107ef3f6aa5a61626\\\"]\"") + "\nAs a json rpc call\n" - + HelpExampleRpc("createmultisig", "2, \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"") + + HelpExampleRpc("createmultisig", "2, \"[\\\"03789ed0bb717d88f7d321a368d905e7430207ebbd82bd342cf11ae157a7ace5fd\\\",\\\"03dbc6764b8884a92e871274b87583e6d5c2a58819473e17e107ef3f6aa5a61626\\\"]\"") ; throw std::runtime_error(msg); } + int required = request.params[0].get_int(); + + // Get the public keys + const UniValue& keys = request.params[1].get_array(); + std::vector<CPubKey> pubkeys; + for (unsigned int i = 0; i < keys.size(); ++i) { + if (IsHex(keys[i].get_str()) && (keys[i].get_str().length() == 66 || keys[i].get_str().length() == 130)) { + pubkeys.push_back(HexToPubKey(keys[i].get_str())); + } else { +#ifdef ENABLE_WALLET + CWallet* const pwallet = GetWalletForJSONRPCRequest(request); + if (IsDeprecatedRPCEnabled("createmultisig") && EnsureWalletIsAvailable(pwallet, false)) { + pubkeys.push_back(AddrToPubKey(pwallet, keys[i].get_str())); + } else +#endif + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Invalid public key: %s\nNote that from v0.16, createmultisig no longer accepts addresses." + " Clients must transition to using addmultisigaddress to create multisig addresses with addresses known to the wallet before upgrading to v0.17." + " To use the deprecated functionality, start bitcoind with -deprecatedrpc=createmultisig", keys[i].get_str())); + } + } + // Construct using pay-to-script-hash: - CScript inner = _createmultisig_redeemScript(pwallet, request.params); + CScript inner = CreateMultisigRedeemscript(required, pubkeys); CScriptID innerID(inner); UniValue result(UniValue::VOBJ); @@ -533,6 +533,9 @@ uint32_t getCategoryMask(UniValue cats) { if (!GetLogCategory(&flag, &cat)) { throw JSONRPCError(RPC_INVALID_PARAMETER, "unknown logging category " + cat); } + if (flag == BCLog::NONE) { + return 0; + } mask |= flag; } return mask; @@ -542,16 +545,32 @@ UniValue logging(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() > 2) { throw std::runtime_error( - "logging [include,...] <exclude>\n" + "logging ( <include> <exclude> )\n" "Gets and sets the logging configuration.\n" - "When called without an argument, returns the list of categories that are currently being debug logged.\n" - "When called with arguments, adds or removes categories from debug logging.\n" + "When called without an argument, returns the list of categories with status that are currently being debug logged or not.\n" + "When called with arguments, adds or removes categories from debug logging and return the lists above.\n" + "The arguments are evaluated in order \"include\", \"exclude\".\n" + "If an item is both included and excluded, it will thus end up being excluded.\n" "The valid logging categories are: " + ListLogCategories() + "\n" - "libevent logging is configured on startup and cannot be modified by this RPC during runtime." - "Arguments:\n" - "1. \"include\" (array of strings) add debug logging for these categories.\n" - "2. \"exclude\" (array of strings) remove debug logging for these categories.\n" - "\nResult: <categories> (string): a list of the logging categories that are active.\n" + "In addition, the following are available as category names with special meanings:\n" + " - \"all\", \"1\" : represent all logging categories.\n" + " - \"none\", \"0\" : even if other logging categories are specified, ignore all of them.\n" + "\nArguments:\n" + "1. \"include\" (array of strings, optional) A json array of categories to add debug logging\n" + " [\n" + " \"category\" (string) the valid logging category\n" + " ,...\n" + " ]\n" + "2. \"exclude\" (array of strings, optional) A json array of categories to remove debug logging\n" + " [\n" + " \"category\" (string) the valid logging category\n" + " ,...\n" + " ]\n" + "\nResult:\n" + "{ (json object where keys are the logging categories, and values indicates its status\n" + " \"category\": 0|1, (numeric) if being debug logged or not. 0:inactive, 1:active\n" + " ...\n" + "}\n" "\nExamples:\n" + HelpExampleCli("logging", "\"[\\\"all\\\"]\" \"[\\\"http\\\"]\"") + HelpExampleRpc("logging", "[\"all\"], \"[libevent]\"") @@ -604,6 +623,18 @@ UniValue echo(const JSONRPCRequest& request) return request.params; } +static UniValue getinfo_deprecated(const JSONRPCRequest& request) +{ + throw JSONRPCError(RPC_METHOD_NOT_FOUND, + "getinfo\n" + "\nThis call was removed in version 0.16.0. Use the appropriate fields from:\n" + "- getblockchaininfo: blocks, difficulty, chain\n" + "- getnetworkinfo: version, protocolversion, timeoffset, connections, proxy, relayfee, warnings\n" + "- getwalletinfo: balance, keypoololdest, keypoolsize, paytxfee, unlocked_until, walletversion\n" + "\nbitcoin-cli has the option -getinfo to collect and format these in the old format." + ); +} + static const CRPCCommand commands[] = { // category name actor (function) argNames // --------------------- ------------------------ ----------------------- ---------- @@ -618,6 +649,7 @@ static const CRPCCommand commands[] = { "hidden", "setmocktime", &setmocktime, {"timestamp"}}, { "hidden", "echo", &echo, {"arg0","arg1","arg2","arg3","arg4","arg5","arg6","arg7","arg8","arg9"}}, { "hidden", "echojson", &echo, {"arg0","arg1","arg2","arg3","arg4","arg5","arg6","arg7","arg8","arg9"}}, + { "hidden", "getinfo", &getinfo_deprecated, {}}, }; void RegisterMiscRPCCommands(CRPCTable &t) diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index 322a3e0cbd..59b376c59a 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -516,7 +516,7 @@ UniValue setban(const JSONRPCRequest& request) CNetAddr netAddr; bool isSubnet = false; - if (request.params[0].get_str().find("/") != std::string::npos) + if (request.params[0].get_str().find('/') != std::string::npos) isSubnet = true; if (!isSubnet) { @@ -571,11 +571,11 @@ UniValue listbanned(const JSONRPCRequest& request) g_connman->GetBanned(banMap); UniValue bannedAddresses(UniValue::VARR); - for (banmap_t::iterator it = banMap.begin(); it != banMap.end(); it++) + for (const auto& entry : banMap) { - CBanEntry banEntry = (*it).second; + const CBanEntry& banEntry = entry.second; UniValue rec(UniValue::VOBJ); - rec.push_back(Pair("address", (*it).first.ToString())); + rec.push_back(Pair("address", entry.first.ToString())); rec.push_back(Pair("banned_until", banEntry.nBanUntil)); rec.push_back(Pair("ban_created", banEntry.nCreateTime)); rec.push_back(Pair("ban_reason", banEntry.banReasonToString())); diff --git a/src/rpc/protocol.cpp b/src/rpc/protocol.cpp index 4cb28c2104..ddc1bb6232 100644 --- a/src/rpc/protocol.cpp +++ b/src/rpc/protocol.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -12,7 +12,6 @@ #include <utiltime.h> #include <version.h> -#include <stdint.h> #include <fstream> /** diff --git a/src/rpc/protocol.h b/src/rpc/protocol.h index 4b9bd41994..00b92f1956 100644 --- a/src/rpc/protocol.h +++ b/src/rpc/protocol.h @@ -1,5 +1,5 @@ // Copyright (c) 2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index e65959bf0e..82399e1567 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -64,12 +64,15 @@ void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry) UniValue getrawtransaction(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) + if (request.fHelp || request.params.size() < 1 || request.params.size() > 3) throw std::runtime_error( - "getrawtransaction \"txid\" ( verbose )\n" + "getrawtransaction \"txid\" ( verbose \"blockhash\" )\n" "\nNOTE: By default this function only works for mempool transactions. If the -txindex option is\n" - "enabled, it also works for blockchain transactions.\n" + "enabled, it also works for blockchain transactions. If the block which contains the transaction\n" + "is known, its hash can be provided even for nodes without -txindex. Note that if a blockhash is\n" + "provided, only that block will be searched and if the transaction is in the mempool or other\n" + "blocks, or if this node does not have the given block available, the transaction will not be found.\n" "DEPRECATED: for now, it also works for transactions with unspent outputs.\n" "\nReturn the raw transaction data.\n" @@ -78,13 +81,15 @@ UniValue getrawtransaction(const JSONRPCRequest& request) "\nArguments:\n" "1. \"txid\" (string, required) The transaction id\n" - "2. verbose (bool, optional, default=false) If false, return a string, otherwise return a json object\n" + "2. verbose (bool, optional, default=false) If false, return a string, otherwise return a json object\n" + "3. \"blockhash\" (string, optional) The block in which to look for the transaction\n" "\nResult (if verbose is not set or set to false):\n" "\"data\" (string) The serialized, hex-encoded data for 'txid'\n" "\nResult (if verbose is set to true):\n" "{\n" + " \"in_active_chain\": b, (bool) Whether specified block is in the active chain or not (only present with explicit \"blockhash\" argument)\n" " \"hex\" : \"data\", (string) The serialized, hex-encoded data for 'txid'\n" " \"txid\" : \"id\", (string) The transaction id (same as provided)\n" " \"hash\" : \"id\", (string) The transaction hash (differs from txid for witness transactions)\n" @@ -132,42 +137,56 @@ UniValue getrawtransaction(const JSONRPCRequest& request) + HelpExampleCli("getrawtransaction", "\"mytxid\"") + HelpExampleCli("getrawtransaction", "\"mytxid\" true") + HelpExampleRpc("getrawtransaction", "\"mytxid\", true") + + HelpExampleCli("getrawtransaction", "\"mytxid\" false \"myblockhash\"") + + HelpExampleCli("getrawtransaction", "\"mytxid\" true \"myblockhash\"") ); LOCK(cs_main); + bool in_active_chain = true; uint256 hash = ParseHashV(request.params[0], "parameter 1"); + CBlockIndex* blockindex = nullptr; // Accept either a bool (true) or a num (>=1) to indicate verbose output. bool fVerbose = false; if (!request.params[1].isNull()) { - if (request.params[1].isNum()) { - if (request.params[1].get_int() != 0) { - fVerbose = true; - } - } - else if(request.params[1].isBool()) { - if(request.params[1].isTrue()) { - fVerbose = true; - } - } - else { - throw JSONRPCError(RPC_TYPE_ERROR, "Invalid type provided. Verbose parameter must be a boolean."); + fVerbose = request.params[1].isNum() ? (request.params[1].get_int() != 0) : request.params[1].get_bool(); + } + + if (!request.params[2].isNull()) { + uint256 blockhash = ParseHashV(request.params[2], "parameter 3"); + BlockMap::iterator it = mapBlockIndex.find(blockhash); + if (it == mapBlockIndex.end()) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block hash not found"); } + blockindex = it->second; + in_active_chain = chainActive.Contains(blockindex); } CTransactionRef tx; - uint256 hashBlock; - if (!GetTransaction(hash, tx, Params().GetConsensus(), hashBlock, true)) - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string(fTxIndex ? "No such mempool or blockchain transaction" - : "No such mempool transaction. Use -txindex to enable blockchain transaction queries") + - ". Use gettransaction for wallet transactions."); + uint256 hash_block; + if (!GetTransaction(hash, tx, Params().GetConsensus(), hash_block, true, blockindex)) { + std::string errmsg; + if (blockindex) { + if (!(blockindex->nStatus & BLOCK_HAVE_DATA)) { + throw JSONRPCError(RPC_MISC_ERROR, "Block not available"); + } + errmsg = "No such transaction found in the provided block"; + } else { + errmsg = fTxIndex + ? "No such mempool or blockchain transaction" + : "No such mempool transaction. Use -txindex to enable blockchain transaction queries"; + } + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, errmsg + ". Use gettransaction for wallet transactions."); + } - if (!fVerbose) + if (!fVerbose) { return EncodeHexTx(*tx, RPCSerializationFlags()); + } UniValue result(UniValue::VOBJ); - TxToJSON(*tx, hashBlock, result); + if (blockindex) result.push_back(Pair("in_active_chain", in_active_chain)); + TxToJSON(*tx, hash_block, result); return result; } @@ -330,7 +349,7 @@ UniValue createrawtransaction(const JSONRPCRequest& request) + HelpExampleRpc("createrawtransaction", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\", \"{\\\"data\\\":\\\"00010203\\\"}\"") ); - RPCTypeCheck(request.params, {UniValue::VARR, UniValue::VOBJ, UniValue::VNUM}, true); + RPCTypeCheck(request.params, {UniValue::VARR, UniValue::VOBJ, UniValue::VNUM, UniValue::VBOOL}, true); if (request.params[0].isNull() || request.params[1].isNull()) throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, arguments 1 and 2 must be non-null"); @@ -422,13 +441,15 @@ UniValue createrawtransaction(const JSONRPCRequest& request) UniValue decoderawtransaction(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 1) + if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) throw std::runtime_error( - "decoderawtransaction \"hexstring\"\n" + "decoderawtransaction \"hexstring\" ( iswitness )\n" "\nReturn a JSON object representing the serialized, hex-encoded transaction.\n" "\nArguments:\n" "1. \"hexstring\" (string, required) The transaction hex string\n" + "2. iswitness (boolean, optional) Whether the transaction hex is a serialized witness transaction\n" + " If iswitness is not present, heuristic tests will be used in decoding\n" "\nResult:\n" "{\n" @@ -476,12 +497,16 @@ UniValue decoderawtransaction(const JSONRPCRequest& request) ); LOCK(cs_main); - RPCTypeCheck(request.params, {UniValue::VSTR}); + RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VBOOL}); CMutableTransaction mtx; - if (!DecodeHexTx(mtx, request.params[0].get_str(), true)) + bool try_witness = request.params[1].isNull() ? true : request.params[1].get_bool(); + bool try_no_witness = request.params[1].isNull() ? true : !request.params[1].get_bool(); + + if (!DecodeHexTx(mtx, request.params[0].get_str(), try_no_witness, try_witness)) { throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed"); + } UniValue result(UniValue::VOBJ); TxToUniv(CTransaction(std::move(mtx)), uint256(), result, false); @@ -970,6 +995,10 @@ UniValue sendrawtransaction(const JSONRPCRequest& request) } } else if (fHaveChain) { throw JSONRPCError(RPC_TRANSACTION_ALREADY_IN_CHAIN, "transaction already in block chain"); + } else { + // Make sure we don't block forever if re-sending + // a transaction already in mempool. + promise.set_value(); } } // cs_main @@ -991,9 +1020,9 @@ UniValue sendrawtransaction(const JSONRPCRequest& request) static const CRPCCommand commands[] = { // category name actor (function) argNames // --------------------- ------------------------ ----------------------- ---------- - { "rawtransactions", "getrawtransaction", &getrawtransaction, {"txid","verbose"} }, + { "rawtransactions", "getrawtransaction", &getrawtransaction, {"txid","verbose","blockhash"} }, { "rawtransactions", "createrawtransaction", &createrawtransaction, {"inputs","outputs","locktime","replaceable"} }, - { "rawtransactions", "decoderawtransaction", &decoderawtransaction, {"hexstring"} }, + { "rawtransactions", "decoderawtransaction", &decoderawtransaction, {"hexstring","iswitness"} }, { "rawtransactions", "decodescript", &decodescript, {"hexstring"} }, { "rawtransactions", "sendrawtransaction", &sendrawtransaction, {"hexstring","allowhighfees"} }, { "rawtransactions", "combinerawtransaction", &combinerawtransaction, {"txs"} }, diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index fa81398272..e5b4f6ca77 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -14,8 +14,6 @@ #include <util.h> #include <utilstrencodings.h> -#include <univalue.h> - #include <boost/bind.hpp> #include <boost/signals2/signal.hpp> #include <boost/algorithm/string/case_conv.hpp> // for to_upper() @@ -160,8 +158,8 @@ std::string CRPCTable::help(const std::string& strCommand, const JSONRPCRequest& std::set<rpcfn_type> setDone; std::vector<std::pair<std::string, const CRPCCommand*> > vCommands; - for (std::map<std::string, const CRPCCommand*>::const_iterator mi = mapCommands.begin(); mi != mapCommands.end(); ++mi) - vCommands.push_back(make_pair(mi->second->category + mi->first, mi->second)); + for (const auto& entry : mapCommands) + vCommands.push_back(make_pair(entry.second->category + entry.first, entry.second)); sort(vCommands.begin(), vCommands.end()); JSONRPCRequest jreq(helpreq); diff --git a/src/rpc/server.h b/src/rpc/server.h index cd201bf316..075940cb90 100644 --- a/src/rpc/server.h +++ b/src/rpc/server.h @@ -1,5 +1,5 @@ // Copyright (c) 2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/rpc/util.cpp b/src/rpc/util.cpp new file mode 100644 index 0000000000..09ded4e46e --- /dev/null +++ b/src/rpc/util.cpp @@ -0,0 +1,68 @@ +// Copyright (c) 2017 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 <base58.h> +#include <keystore.h> +#include <pubkey.h> +#include <rpc/protocol.h> +#include <rpc/util.h> +#include <tinyformat.h> +#include <utilstrencodings.h> + +// Converts a hex string to a public key if possible +CPubKey HexToPubKey(const std::string& hex_in) +{ + if (!IsHex(hex_in)) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid public key: " + hex_in); + } + CPubKey vchPubKey(ParseHex(hex_in)); + if (!vchPubKey.IsFullyValid()) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid public key: " + hex_in); + } + return vchPubKey; +} + +// Retrieves a public key for an address from the given CKeyStore +CPubKey AddrToPubKey(CKeyStore* const keystore, const std::string& addr_in) +{ + CTxDestination dest = DecodeDestination(addr_in); + if (!IsValidDestination(dest)) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address: " + addr_in); + } + CKeyID key = GetKeyForDestination(*keystore, dest); + if (key.IsNull()) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("%s does not refer to a key", addr_in)); + } + CPubKey vchPubKey; + if (!keystore->GetPubKey(key, vchPubKey)) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("no full public key for address %s", addr_in)); + } + if (!vchPubKey.IsFullyValid()) { + throw JSONRPCError(RPC_INTERNAL_ERROR, "Wallet contains an invalid public key"); + } + return vchPubKey; +} + +// Creates a multisig redeemscript from a given list of public keys and number required. +CScript CreateMultisigRedeemscript(const int required, const std::vector<CPubKey>& pubkeys) +{ + // Gather public keys + if (required < 1) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "a multisignature address must require at least one key to redeem"); + } + if ((int)pubkeys.size() < required) { + throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("not enough keys supplied (got %u keys, but need at least %d to redeem)", pubkeys.size(), required)); + } + if (pubkeys.size() > 16) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "Number of keys involved in the multisignature address creation > 16\nReduce the number"); + } + + CScript result = GetScriptForMultisig(required, pubkeys); + + if (result.size() > MAX_SCRIPT_ELEMENT_SIZE) { + throw JSONRPCError(RPC_INVALID_PARAMETER, (strprintf("redeemScript exceeds size limit: %d > %d", result.size(), MAX_SCRIPT_ELEMENT_SIZE))); + } + + return result; +} diff --git a/src/rpc/util.h b/src/rpc/util.h new file mode 100644 index 0000000000..568a4260ba --- /dev/null +++ b/src/rpc/util.h @@ -0,0 +1,19 @@ +// Copyright (c) 2017 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_RPC_UTIL_H +#define BITCOIN_RPC_UTIL_H + +#include <string> +#include <vector> + +class CKeyStore; +class CPubKey; +class CScript; + +CPubKey HexToPubKey(const std::string& hex_in); +CPubKey AddrToPubKey(CKeyStore* const keystore, const std::string& addr_in); +CScript CreateMultisigRedeemscript(const int required, const std::vector<CPubKey>& pubkeys); + +#endif // BITCOIN_RPC_UTIL_H diff --git a/src/scheduler.cpp b/src/scheduler.cpp index 260f6fa60e..a94f6b2a66 100644 --- a/src/scheduler.cpp +++ b/src/scheduler.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2016 The Bitcoin Core developers +// Copyright (c) 2015-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -206,3 +206,8 @@ void SingleThreadedSchedulerClient::EmptyQueue() { should_continue = !m_callbacks_pending.empty(); } } + +size_t SingleThreadedSchedulerClient::CallbacksPending() { + LOCK(m_cs_callbacks_pending); + return m_callbacks_pending.size(); +} diff --git a/src/scheduler.h b/src/scheduler.h index b99f165343..a41838a295 100644 --- a/src/scheduler.h +++ b/src/scheduler.h @@ -1,4 +1,4 @@ -// Copyright (c) 2015 The Bitcoin Core developers +// Copyright (c) 2015-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -108,6 +108,8 @@ public: // Processes all remaining queue members on the calling thread, blocking until queue is empty // Must be called after the CScheduler has no remaining processing threads! void EmptyQueue(); + + size_t CallbacksPending(); }; #endif diff --git a/src/script/bitcoinconsensus.cpp b/src/script/bitcoinconsensus.cpp index 77edc85b8c..7d3587e2c2 100644 --- a/src/script/bitcoinconsensus.cpp +++ b/src/script/bitcoinconsensus.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/script/bitcoinconsensus.h b/src/script/bitcoinconsensus.h index f09cd59b92..bb94c17528 100644 --- a/src/script/bitcoinconsensus.h +++ b/src/script/bitcoinconsensus.h @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp index d6348f17d8..2cdff7ee57 100644 --- a/src/script/interpreter.cpp +++ b/src/script/interpreter.cpp @@ -1,11 +1,10 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <script/interpreter.h> -#include <primitives/transaction.h> #include <crypto/ripemd160.h> #include <crypto/sha1.h> #include <crypto/sha256.h> @@ -174,7 +173,13 @@ bool static IsLowDERSignature(const valtype &vchSig, ScriptError* serror) { if (!IsValidSignatureEncoding(vchSig)) { return set_error(serror, SCRIPT_ERR_SIG_DER); } + // https://bitcoin.stackexchange.com/a/12556: + // Also note that inside transaction signatures, an extra hashtype byte + // follows the actual signature data. std::vector<unsigned char> vchSigCopy(vchSig.begin(), vchSig.begin() + vchSig.size() - 1); + // If the S value is above the order of the curve divided by two, its + // complement modulo the order could have been used instead, which is + // one byte shorter when encoded correctly. if (!CPubKey::CheckLowS(vchSigCopy)) { return set_error(serror, SCRIPT_ERR_SIG_HIGH_S); } @@ -349,9 +354,6 @@ bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript& { if (!(flags & SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY)) { // not enabled; treat as a NOP2 - if (flags & SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) { - return set_error(serror, SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS); - } break; } @@ -391,9 +393,6 @@ bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript& { if (!(flags & SCRIPT_VERIFY_CHECKSEQUENCEVERIFY)) { // not enabled; treat as a NOP3 - if (flags & SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) { - return set_error(serror, SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS); - } break; } diff --git a/src/script/interpreter.h b/src/script/interpreter.h index 2eae68179e..e12329be76 100644 --- a/src/script/interpreter.h +++ b/src/script/interpreter.h @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -27,37 +27,40 @@ enum SIGHASH_ANYONECANPAY = 0x80, }; -/** Script verification flags */ +/** Script verification flags. + * + * All flags are intended to be soft forks: the set of acceptable scripts under + * flags (A | B) is a subset of the acceptable scripts under flag (A). + */ enum { SCRIPT_VERIFY_NONE = 0, - // Evaluate P2SH subscripts (softfork safe, BIP16). + // Evaluate P2SH subscripts (BIP16). SCRIPT_VERIFY_P2SH = (1U << 0), // Passing a non-strict-DER signature or one with undefined hashtype to a checksig operation causes script failure. // Evaluating a pubkey that is not (0x04 + 64 bytes) or (0x02 or 0x03 + 32 bytes) by checksig causes script failure. - // (softfork safe, but not used or intended as a consensus rule). + // (not used or intended as a consensus rule). SCRIPT_VERIFY_STRICTENC = (1U << 1), - // Passing a non-strict-DER signature to a checksig operation causes script failure (softfork safe, BIP62 rule 1) + // Passing a non-strict-DER signature to a checksig operation causes script failure (BIP62 rule 1) SCRIPT_VERIFY_DERSIG = (1U << 2), // Passing a non-strict-DER signature or one with S > order/2 to a checksig operation causes script failure - // (softfork safe, BIP62 rule 5). + // (BIP62 rule 5). SCRIPT_VERIFY_LOW_S = (1U << 3), - // verify dummy stack item consumed by CHECKMULTISIG is of zero-length (softfork safe, BIP62 rule 7). + // verify dummy stack item consumed by CHECKMULTISIG is of zero-length (BIP62 rule 7). SCRIPT_VERIFY_NULLDUMMY = (1U << 4), - // Using a non-push operator in the scriptSig causes script failure (softfork safe, BIP62 rule 2). + // Using a non-push operator in the scriptSig causes script failure (BIP62 rule 2). SCRIPT_VERIFY_SIGPUSHONLY = (1U << 5), // Require minimal encodings for all push operations (OP_0... OP_16, OP_1NEGATE where possible, direct // pushes up to 75 bytes, OP_PUSHDATA up to 255 bytes, OP_PUSHDATA2 for anything larger). Evaluating // any other push causes the script to fail (BIP62 rule 3). // In addition, whenever a stack element is interpreted as a number, it must be of minimal length (BIP62 rule 4). - // (softfork safe) SCRIPT_VERIFY_MINIMALDATA = (1U << 6), // Discourage use of NOPs reserved for upgrades (NOP1-10) @@ -68,12 +71,14 @@ enum // discouraged NOPs fails the script. This verification flag will never be // a mandatory flag applied to scripts in a block. NOPs that are not // executed, e.g. within an unexecuted IF ENDIF block, are *not* rejected. + // NOPs that have associated forks to give them new meaning (CLTV, CSV) + // are not subject to this rule. SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS = (1U << 7), // Require that only a single stack element remains after evaluation. This changes the success criterion from // "At least one stack element must remain, and when interpreted as a boolean, it must be true" to // "Exactly one stack element must remain, and when interpreted as a boolean, it must be true". - // (softfork safe, BIP62 rule 6) + // (BIP62 rule 6) // Note: CLEANSTACK should never be used without P2SH or WITNESS. SCRIPT_VERIFY_CLEANSTACK = (1U << 8), diff --git a/src/script/ismine.cpp b/src/script/ismine.cpp index 60bef3b701..d0dd272550 100644 --- a/src/script/ismine.cpp +++ b/src/script/ismine.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -8,7 +8,6 @@ #include <key.h> #include <keystore.h> #include <script/script.h> -#include <script/standard.h> #include <script/sign.h> diff --git a/src/script/ismine.h b/src/script/ismine.h index 77ffa82432..b54879cc15 100644 --- a/src/script/ismine.h +++ b/src/script/ismine.h @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/script/script.cpp b/src/script/script.cpp index a7bfb170eb..65e5405ebd 100644 --- a/src/script/script.cpp +++ b/src/script/script.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/script/script.h b/src/script/script.h index 263db62edf..bedf5f9be5 100644 --- a/src/script/script.h +++ b/src/script/script.h @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/script/script_error.cpp b/src/script/script_error.cpp index 32aa639ac4..dbceb1f740 100644 --- a/src/script/script_error.cpp +++ b/src/script/script_error.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/script/sigcache.cpp b/src/script/sigcache.cpp index 88d1d67559..9638b12f99 100644 --- a/src/script/sigcache.cpp +++ b/src/script/sigcache.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/script/sigcache.h b/src/script/sigcache.h index 1019061fbb..1309d57cc6 100644 --- a/src/script/sigcache.h +++ b/src/script/sigcache.h @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/script/sign.cpp b/src/script/sign.cpp index 117a4d8a52..838e502a0a 100644 --- a/src/script/sign.cpp +++ b/src/script/sign.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -422,3 +422,22 @@ bool DummySignatureCreator::CreateSig(std::vector<unsigned char>& vchSig, const vchSig[6 + 33 + 32] = SIGHASH_ALL; return true; } + +bool IsSolvable(const CKeyStore& store, const CScript& script) +{ + // This check is to make sure that the script we created can actually be solved for and signed by us + // if we were to have the private keys. This is just to make sure that the script is valid and that, + // if found in a transaction, we would still accept and relay that transaction. In particular, + // it will reject witness outputs that require signing with an uncompressed public key. + DummySignatureCreator creator(&store); + SignatureData sigs; + // Make sure that STANDARD_SCRIPT_VERIFY_FLAGS includes SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, the most + // important property this function is designed to test for. + static_assert(STANDARD_SCRIPT_VERIFY_FLAGS & SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, "IsSolvable requires standard script flags to include WITNESS_PUBKEYTYPE"); + if (ProduceSignature(creator, script, sigs)) { + // VerifyScript check is just defensive, and should never fail. + assert(VerifyScript(sigs.scriptSig, script, &sigs.scriptWitness, STANDARD_SCRIPT_VERIFY_FLAGS, creator.Checker())); + return true; + } + return false; +} diff --git a/src/script/sign.h b/src/script/sign.h index 400c0c0865..97c0014cd0 100644 --- a/src/script/sign.h +++ b/src/script/sign.h @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -81,4 +81,10 @@ SignatureData CombineSignatures(const CScript& scriptPubKey, const BaseSignature SignatureData DataFromTransaction(const CMutableTransaction& tx, unsigned int nIn); void UpdateTransaction(CMutableTransaction& tx, unsigned int nIn, const SignatureData& data); +/* Check whether we know how to sign for an output like this, assuming we + * have all private keys. While this function does not need private keys, the passed + * keystore is used to look up public keys and redeemscripts by hash. + * Solvability is unrelated to whether we consider this output to be ours. */ +bool IsSolvable(const CKeyStore& store, const CScript& script); + #endif // BITCOIN_SCRIPT_SIGN_H diff --git a/src/script/standard.cpp b/src/script/standard.cpp index b7b33fade6..cfb3c58588 100644 --- a/src/script/standard.cpp +++ b/src/script/standard.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -348,19 +348,14 @@ CScript GetScriptForWitness(const CScript& redeemscript) std::vector<std::vector<unsigned char> > vSolutions; if (Solver(redeemscript, typ, vSolutions)) { if (typ == TX_PUBKEY) { - unsigned char h160[20]; - CHash160().Write(&vSolutions[0][0], vSolutions[0].size()).Finalize(h160); - ret << OP_0 << std::vector<unsigned char>(&h160[0], &h160[20]); - return ret; + return GetScriptForDestination(WitnessV0KeyHash(Hash160(vSolutions[0].begin(), vSolutions[0].end()))); } else if (typ == TX_PUBKEYHASH) { - ret << OP_0 << vSolutions[0]; - return ret; + return GetScriptForDestination(WitnessV0KeyHash(vSolutions[0])); } } uint256 hash; CSHA256().Write(&redeemscript[0], redeemscript.size()).Finalize(hash.begin()); - ret << OP_0 << ToByteVector(hash); - return ret; + return GetScriptForDestination(WitnessV0ScriptHash(hash)); } bool IsValidDestination(const CTxDestination& dest) { diff --git a/src/script/standard.h b/src/script/standard.h index 3eeeabdc15..3b2838a5bb 100644 --- a/src/script/standard.h +++ b/src/script/standard.h @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -73,8 +73,19 @@ public: friend bool operator<(const CNoDestination &a, const CNoDestination &b) { return true; } }; -struct WitnessV0ScriptHash : public uint256 {}; -struct WitnessV0KeyHash : public uint160 {}; +struct WitnessV0ScriptHash : public uint256 +{ + WitnessV0ScriptHash() : uint256() {} + explicit WitnessV0ScriptHash(const uint256& hash) : uint256(hash) {} + using uint256::uint256; +}; + +struct WitnessV0KeyHash : public uint160 +{ + WitnessV0KeyHash() : uint160() {} + explicit WitnessV0KeyHash(const uint160& hash) : uint160(hash) {} + using uint160::uint160; +}; //! CTxDestination subtype to encode any future Witness version struct WitnessUnknown @@ -144,6 +155,10 @@ bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet) * addressRet is populated with a single value and nRequiredRet is set to 1. * Returns true if successful. Currently does not extract address from * pay-to-witness scripts. + * + * Note: this function confuses destinations (a subset of CScripts that are + * encodable as an address) with key identifiers (of keys involved in a + * CScript), and its use should be phased out. */ bool ExtractDestinations(const CScript& scriptPubKey, txnouttype& typeRet, std::vector<CTxDestination>& addressRet, int& nRequiredRet); @@ -164,6 +179,9 @@ CScript GetScriptForMultisig(int nRequired, const std::vector<CPubKey>& keys); * Generate a pay-to-witness script for the given redeem script. If the redeem * script is P2PK or P2PKH, this returns a P2WPKH script, otherwise it returns a * P2WSH script. + * + * TODO: replace calls to GetScriptForWitness with GetScriptForDestination using + * the various witness-specific CTxDestination subtypes. */ CScript GetScriptForWitness(const CScript& redeemscript); diff --git a/src/serialize.h b/src/serialize.h index 62ecde4823..dcc8d8691e 100644 --- a/src/serialize.h +++ b/src/serialize.h @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -732,8 +732,8 @@ template<typename Stream, typename K, typename T, typename Pred, typename A> void Serialize(Stream& os, const std::map<K, T, Pred, A>& m) { WriteCompactSize(os, m.size()); - for (typename std::map<K, T, Pred, A>::const_iterator mi = m.begin(); mi != m.end(); ++mi) - Serialize(os, (*mi)); + for (const auto& entry : m) + Serialize(os, entry); } template<typename Stream, typename K, typename T, typename Pred, typename A> diff --git a/src/streams.h b/src/streams.h index a212691f6d..98e25178e1 100644 --- a/src/streams.h +++ b/src/streams.h @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -241,8 +241,8 @@ public: const_reference operator[](size_type pos) const { return vch[pos + nReadPos]; } reference operator[](size_type pos) { return vch[pos + nReadPos]; } void clear() { vch.clear(); nReadPos = 0; } - iterator insert(iterator it, const char& x=char()) { return vch.insert(it, x); } - void insert(iterator it, size_type n, const char& x) { vch.insert(it, n, x); } + iterator insert(iterator it, const char x=char()) { return vch.insert(it, x); } + void insert(iterator it, size_type n, const char x) { vch.insert(it, n, x); } value_type* data() { return vch.data() + nReadPos; } const value_type* data() const { return vch.data() + nReadPos; } diff --git a/src/support/allocators/secure.h b/src/support/allocators/secure.h index 7cd031bfe8..0249afa499 100644 --- a/src/support/allocators/secure.h +++ b/src/support/allocators/secure.h @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/support/allocators/zeroafterfree.h b/src/support/allocators/zeroafterfree.h index 23ef96c13f..78ff1ad024 100644 --- a/src/support/allocators/zeroafterfree.h +++ b/src/support/allocators/zeroafterfree.h @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2015 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/support/cleanse.cpp b/src/support/cleanse.cpp index 82cdfe707b..9bf7eda785 100644 --- a/src/support/cleanse.cpp +++ b/src/support/cleanse.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2015 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -7,6 +7,10 @@ #include <cstring> +#if defined(_MSC_VER) +#include <Windows.h> // For SecureZeroMemory. +#endif + /* Compilers have a bad habit of removing "superfluous" memset calls that * are trying to zero memory. For example, when memset()ing a buffer and * then free()ing it, the compiler might decide that the memset is @@ -32,7 +36,7 @@ void memory_cleanse(void *ptr, size_t len) might try to eliminate "superfluous" memsets. If there's an easy way to detect memset_s, it would be better to use that. */ #if defined(_MSC_VER) - __asm; + SecureZeroMemory(ptr, len); #else __asm__ __volatile__("" : : "r"(ptr) : "memory"); #endif diff --git a/src/support/cleanse.h b/src/support/cleanse.h index f020216c73..69c27df519 100644 --- a/src/support/cleanse.h +++ b/src/support/cleanse.h @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2015 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/support/events.h b/src/support/events.h index cc6d29aecd..7ad51f319c 100644 --- a/src/support/events.h +++ b/src/support/events.h @@ -1,4 +1,4 @@ -// Copyright (c) 2016 The Bitcoin Core developers +// Copyright (c) 2016-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/support/lockedpool.cpp b/src/support/lockedpool.cpp index 98e8694181..d92ab02d6b 100644 --- a/src/support/lockedpool.cpp +++ b/src/support/lockedpool.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2016 The Bitcoin Core developers +// Copyright (c) 2016-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/support/lockedpool.h b/src/support/lockedpool.h index 834f0371e2..fc85e6c73c 100644 --- a/src/support/lockedpool.h +++ b/src/support/lockedpool.h @@ -1,4 +1,4 @@ -// Copyright (c) 2016 The Bitcoin Core developers +// Copyright (c) 2016-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/sync.cpp b/src/sync.cpp index fcc6ddc354..ae6e721466 100644 --- a/src/sync.cpp +++ b/src/sync.cpp @@ -1,17 +1,19 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 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 <sync.h> +#include <set> #include <util.h> #include <utilstrencodings.h> #include <stdio.h> -#include <boost/thread.hpp> - #ifdef DEBUG_LOCKCONTENTION +#if !defined(HAVE_THREAD_LOCAL) +static_assert(false, "thread_local is not supported"); +#endif void PrintLockContention(const char* pszName, const char* pszFile, int nLine) { LogPrintf("LOCKCONTENTION: %s\n", pszName); @@ -45,8 +47,8 @@ struct CLockLocation { return mutexName + " " + sourceFile + ":" + itostr(sourceLine) + (fTry ? " (TRY)" : ""); } - bool fTry; private: + bool fTry; std::string mutexName; std::string sourceFile; int sourceLine; @@ -67,10 +69,10 @@ struct LockData { LockOrders lockorders; InvLockOrders invlockorders; - boost::mutex dd_mutex; + std::mutex dd_mutex; } static lockdata; -boost::thread_specific_ptr<LockStack> lockstack; +static thread_local std::unique_ptr<LockStack> lockstack; static void potential_deadlock_detected(const std::pair<void*, void*>& mismatch, const LockStack& s1, const LockStack& s2) { @@ -100,12 +102,12 @@ static void potential_deadlock_detected(const std::pair<void*, void*>& mismatch, static void push_lock(void* c, const CLockLocation& locklocation) { - if (lockstack.get() == nullptr) + if (!lockstack) lockstack.reset(new LockStack); - boost::unique_lock<boost::mutex> lock(lockdata.dd_mutex); + std::lock_guard<std::mutex> lock(lockdata.dd_mutex); - (*lockstack).push_back(std::make_pair(c, locklocation)); + lockstack->push_back(std::make_pair(c, locklocation)); for (const std::pair<void*, CLockLocation> & i : (*lockstack)) { if (i.first == c) @@ -171,7 +173,7 @@ void DeleteLock(void* cs) // We're already shutting down. return; } - boost::unique_lock<boost::mutex> lock(lockdata.dd_mutex); + std::lock_guard<std::mutex> lock(lockdata.dd_mutex); std::pair<void*, void*> item = std::make_pair(cs, nullptr); LockOrders::iterator it = lockdata.lockorders.lower_bound(item); while (it != lockdata.lockorders.end() && it->first.first == cs) { diff --git a/src/sync.h b/src/sync.h index b0889be767..3c451af376 100644 --- a/src/sync.h +++ b/src/sync.h @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -8,8 +8,6 @@ #include <threadsafety.h> -#include <boost/thread/condition_variable.hpp> -#include <boost/thread/mutex.hpp> #include <condition_variable> #include <thread> #include <mutex> @@ -196,8 +194,8 @@ public: class CSemaphore { private: - boost::condition_variable condition; - boost::mutex mutex; + std::condition_variable condition; + std::mutex mutex; int value; public: @@ -205,16 +203,14 @@ public: void wait() { - boost::unique_lock<boost::mutex> lock(mutex); - while (value < 1) { - condition.wait(lock); - } + std::unique_lock<std::mutex> lock(mutex); + condition.wait(lock, [&]() { return value >= 1; }); value--; } bool try_wait() { - boost::unique_lock<boost::mutex> lock(mutex); + std::lock_guard<std::mutex> lock(mutex); if (value < 1) return false; value--; @@ -224,7 +220,7 @@ public: void post() { { - boost::unique_lock<boost::mutex> lock(mutex); + std::lock_guard<std::mutex> lock(mutex); value++; } condition.notify_one(); diff --git a/src/test/DoS_tests.cpp b/src/test/DoS_tests.cpp index 6be176a1ad..abc31e6181 100644 --- a/src/test/DoS_tests.cpp +++ b/src/test/DoS_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/test/README.md b/src/test/README.md index dbaa9c27f3..01da32109b 100644 --- a/src/test/README.md +++ b/src/test/README.md @@ -52,4 +52,4 @@ examine `uint256_tests.cpp`. For further reading, I found the following website to be helpful in explaining how the boost unit test framework works: -[http://www.alittlemadness.com/2009/03/31/c-unit-testing-with-boosttest/](http://www.alittlemadness.com/2009/03/31/c-unit-testing-with-boosttest/). +[http://www.alittlemadness.com/2009/03/31/c-unit-testing-with-boosttest/](http://archive.is/dRBGf). diff --git a/src/test/addrman_tests.cpp b/src/test/addrman_tests.cpp index 609b1a05d3..b338d6d366 100644 --- a/src/test/addrman_tests.cpp +++ b/src/test/addrman_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2016 The Bitcoin Core developers +// Copyright (c) 2012-2017 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 <addrman.h> diff --git a/src/test/allocator_tests.cpp b/src/test/allocator_tests.cpp index 83fa3b76be..c177f0bf00 100644 --- a/src/test/allocator_tests.cpp +++ b/src/test/allocator_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2016 The Bitcoin Core developers +// Copyright (c) 2012-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/test/amount_tests.cpp b/src/test/amount_tests.cpp index 7ebbd22c5d..854146102e 100644 --- a/src/test/amount_tests.cpp +++ b/src/test/amount_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2016 The Bitcoin Core developers +// Copyright (c) 2016-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/test/arith_uint256_tests.cpp b/src/test/arith_uint256_tests.cpp index eb3148a1de..21a1153ad0 100644 --- a/src/test/arith_uint256_tests.cpp +++ b/src/test/arith_uint256_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/test/base32_tests.cpp b/src/test/base32_tests.cpp index abf236b953..b9ac62a437 100644 --- a/src/test/base32_tests.cpp +++ b/src/test/base32_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2015 The Bitcoin Core developers +// Copyright (c) 2012-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/test/base58_tests.cpp b/src/test/base58_tests.cpp index 3156cc53d0..a2d4f82695 100644 --- a/src/test/base58_tests.cpp +++ b/src/test/base58_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/test/base64_tests.cpp b/src/test/base64_tests.cpp index 46b3a04f35..b31f73f3b5 100644 --- a/src/test/base64_tests.cpp +++ b/src/test/base64_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/test/bip32_tests.cpp b/src/test/bip32_tests.cpp index e3e727439b..438ddc177d 100644 --- a/src/test/bip32_tests.cpp +++ b/src/test/bip32_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2013-2015 The Bitcoin Core developers +// Copyright (c) 2013-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/test/blockchain_tests.cpp b/src/test/blockchain_tests.cpp new file mode 100644 index 0000000000..55fdd2c071 --- /dev/null +++ b/src/test/blockchain_tests.cpp @@ -0,0 +1,126 @@ +#include <boost/test/unit_test.hpp> + +#include "stdlib.h" + +#include "rpc/blockchain.cpp" +#include "test/test_bitcoin.h" + +/* Equality between doubles is imprecise. Comparison should be done + * with a small threshold of tolerance, rather than exact equality. + */ +bool DoubleEquals(double a, double b, double epsilon) +{ + return std::abs(a - b) < epsilon; +} + +CBlockIndex* CreateBlockIndexWithNbits(uint32_t nbits) +{ + CBlockIndex* block_index = new CBlockIndex(); + block_index->nHeight = 46367; + block_index->nTime = 1269211443; + block_index->nBits = nbits; + return block_index; +} + +CChain CreateChainWithNbits(uint32_t nbits) +{ + CBlockIndex* block_index = CreateBlockIndexWithNbits(nbits); + CChain chain; + chain.SetTip(block_index); + return chain; +} + +void RejectDifficultyMismatch(double difficulty, double expected_difficulty) { + BOOST_CHECK_MESSAGE( + DoubleEquals(difficulty, expected_difficulty, 0.00001), + "Difficulty was " + std::to_string(difficulty) + + " but was expected to be " + std::to_string(expected_difficulty)); +} + +/* Given a BlockIndex with the provided nbits, + * verify that the expected difficulty results. + */ +void TestDifficulty(uint32_t nbits, double expected_difficulty) +{ + CBlockIndex* block_index = CreateBlockIndexWithNbits(nbits); + /* Since we are passing in block index explicitly, + * there is no need to set up anything within the chain itself. + */ + CChain chain; + + double difficulty = GetDifficulty(chain, block_index); + delete block_index; + + RejectDifficultyMismatch(difficulty, expected_difficulty); +} + +BOOST_FIXTURE_TEST_SUITE(blockchain_difficulty_tests, BasicTestingSetup) + +BOOST_AUTO_TEST_CASE(get_difficulty_for_very_low_target) +{ + TestDifficulty(0x1f111111, 0.000001); +} + +BOOST_AUTO_TEST_CASE(get_difficulty_for_low_target) +{ + TestDifficulty(0x1ef88f6f, 0.000016); +} + +BOOST_AUTO_TEST_CASE(get_difficulty_for_mid_target) +{ + TestDifficulty(0x1df88f6f, 0.004023); +} + +BOOST_AUTO_TEST_CASE(get_difficulty_for_high_target) +{ + TestDifficulty(0x1cf88f6f, 1.029916); +} + +BOOST_AUTO_TEST_CASE(get_difficulty_for_very_high_target) +{ + TestDifficulty(0x12345678, 5913134931067755359633408.0); +} + +// Verify that difficulty is 1.0 for an empty chain. +BOOST_AUTO_TEST_CASE(get_difficulty_for_null_tip) +{ + CChain chain; + double difficulty = GetDifficulty(chain, nullptr); + RejectDifficultyMismatch(difficulty, 1.0); +} + +/* Verify that if difficulty is based upon the block index + * in the chain, if no block index is explicitly specified. + */ +BOOST_AUTO_TEST_CASE(get_difficulty_for_null_block_index) +{ + CChain chain = CreateChainWithNbits(0x1df88f6f); + + double difficulty = GetDifficulty(chain, nullptr); + delete chain.Tip(); + + double expected_difficulty = 0.004023; + + RejectDifficultyMismatch(difficulty, expected_difficulty); +} + +/* Verify that difficulty is based upon the explicitly specified + * block index rather than being taken from the provided chain, + * when both are present. + */ +BOOST_AUTO_TEST_CASE(get_difficulty_for_block_index_overrides_tip) +{ + CChain chain = CreateChainWithNbits(0x1df88f6f); + /* This block index's nbits should be used + * instead of the chain's when calculating difficulty. + */ + CBlockIndex* override_block_index = CreateBlockIndexWithNbits(0x12345678); + + double difficulty = GetDifficulty(chain, override_block_index); + delete chain.Tip(); + delete override_block_index; + + RejectDifficultyMismatch(difficulty, 5913134931067755359633408.0); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/blockencodings_tests.cpp b/src/test/blockencodings_tests.cpp index 718b5bdfb9..32330e0548 100644 --- a/src/test/blockencodings_tests.cpp +++ b/src/test/blockencodings_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/test/bloom_tests.cpp b/src/test/bloom_tests.cpp index fdd30be0b1..af5533b109 100644 --- a/src/test/bloom_tests.cpp +++ b/src/test/bloom_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2016 The Bitcoin Core developers +// Copyright (c) 2012-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/test/bswap_tests.cpp b/src/test/bswap_tests.cpp index ab4f08b999..f22f513e87 100644 --- a/src/test/bswap_tests.cpp +++ b/src/test/bswap_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2016 The Bitcoin Core developers +// Copyright (c) 2016-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/test/checkqueue_tests.cpp b/src/test/checkqueue_tests.cpp index d8ad0d9165..42f9dd0600 100644 --- a/src/test/checkqueue_tests.cpp +++ b/src/test/checkqueue_tests.cpp @@ -24,7 +24,7 @@ // otherwise. BOOST_FIXTURE_TEST_SUITE(checkqueue_tests, TestingSetup) -static const int QUEUE_BATCH_SIZE = 128; +static const unsigned int QUEUE_BATCH_SIZE = 128; struct FakeCheck { bool operator()() diff --git a/src/test/coins_tests.cpp b/src/test/coins_tests.cpp index 7c3d02ba63..36e271295a 100644 --- a/src/test/coins_tests.cpp +++ b/src/test/coins_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2016 The Bitcoin Core developers +// Copyright (c) 2014-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -81,8 +81,8 @@ public: // Manually recompute the dynamic usage of the whole data, and compare it. size_t ret = memusage::DynamicUsage(cacheCoins); size_t count = 0; - for (CCoinsMap::iterator it = cacheCoins.begin(); it != cacheCoins.end(); it++) { - ret += it->second.coin.DynamicMemoryUsage(); + for (const auto& entry : cacheCoins) { + ret += entry.second.coin.DynamicMemoryUsage(); ++count; } BOOST_CHECK_EQUAL(GetCacheSize(), count); @@ -189,15 +189,15 @@ BOOST_AUTO_TEST_CASE(coins_cache_simulation_test) // Once every 1000 iterations and at the end, verify the full cache. if (InsecureRandRange(1000) == 1 || i == NUM_SIMULATION_ITERATIONS - 1) { - for (auto it = result.begin(); it != result.end(); it++) { - bool have = stack.back()->HaveCoin(it->first); - const Coin& coin = stack.back()->AccessCoin(it->first); + for (const auto& entry : result) { + bool have = stack.back()->HaveCoin(entry.first); + const Coin& coin = stack.back()->AccessCoin(entry.first); BOOST_CHECK(have == !coin.IsSpent()); - BOOST_CHECK(coin == it->second); + BOOST_CHECK(coin == entry.second); if (coin.IsSpent()) { missed_an_entry = true; } else { - BOOST_CHECK(stack.back()->HaveCoinInCache(it->first)); + BOOST_CHECK(stack.back()->HaveCoinInCache(entry.first)); found_an_entry = true; } } @@ -420,11 +420,11 @@ BOOST_AUTO_TEST_CASE(updatecoins_simulation_test) // Once every 1000 iterations and at the end, verify the full cache. if (InsecureRandRange(1000) == 1 || i == NUM_SIMULATION_ITERATIONS - 1) { - for (auto it = result.begin(); it != result.end(); it++) { - bool have = stack.back()->HaveCoin(it->first); - const Coin& coin = stack.back()->AccessCoin(it->first); + for (const auto& entry : result) { + bool have = stack.back()->HaveCoin(entry.first); + const Coin& coin = stack.back()->AccessCoin(entry.first); BOOST_CHECK(have == !coin.IsSpent()); - BOOST_CHECK(coin == it->second); + BOOST_CHECK(coin == entry.second); } } diff --git a/src/test/compress_tests.cpp b/src/test/compress_tests.cpp index 87e75d8020..3c26013622 100644 --- a/src/test/compress_tests.cpp +++ b/src/test/compress_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2015 The Bitcoin Core developers +// Copyright (c) 2012-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/test/crypto_tests.cpp b/src/test/crypto_tests.cpp index a63d62bb37..cdfc664d56 100644 --- a/src/test/crypto_tests.cpp +++ b/src/test/crypto_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2016 The Bitcoin Core developers +// Copyright (c) 2014-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -340,6 +340,22 @@ BOOST_AUTO_TEST_CASE(hmac_sha256_testvectors) { "647320746f20626520686173686564206265666f7265206265696e6720757365" "642062792074686520484d414320616c676f726974686d2e", "9b09ffa71b942fcb27635fbcd5b0e944bfdc63644f0713938a7f51535c3a35e2"); + // Test case with key length 63 bytes. + TestHMACSHA256("4a6566654a6566654a6566654a6566654a6566654a6566654a6566654a656665" + "4a6566654a6566654a6566654a6566654a6566654a6566654a6566654a6566", + "7768617420646f2079612077616e7420666f72206e6f7468696e673f", + "9de4b546756c83516720a4ad7fe7bdbeac4298c6fdd82b15f895a6d10b0769a6"); + // Test case with key length 64 bytes. + TestHMACSHA256("4a6566654a6566654a6566654a6566654a6566654a6566654a6566654a656665" + "4a6566654a6566654a6566654a6566654a6566654a6566654a6566654a656665", + "7768617420646f2079612077616e7420666f72206e6f7468696e673f", + "528c609a4c9254c274585334946b7c2661bad8f1fc406b20f6892478d19163dd"); + // Test case with key length 65 bytes. + TestHMACSHA256("4a6566654a6566654a6566654a6566654a6566654a6566654a6566654a656665" + "4a6566654a6566654a6566654a6566654a6566654a6566654a6566654a656665" + "4a", + "7768617420646f2079612077616e7420666f72206e6f7468696e673f", + "d06af337f359a2330deffb8e3cbe4b5b7aa8ca1f208528cdbd245d5dc63c4483"); } BOOST_AUTO_TEST_CASE(hmac_sha512_testvectors) { @@ -383,6 +399,31 @@ BOOST_AUTO_TEST_CASE(hmac_sha512_testvectors) { "642062792074686520484d414320616c676f726974686d2e", "e37b6a775dc87dbaa4dfa9f96e5e3ffddebd71f8867289865df5a32d20cdc944" "b6022cac3c4982b10d5eeb55c3e4de15134676fb6de0446065c97440fa8c6a58"); + // Test case with key length 127 bytes. + TestHMACSHA512("4a6566654a6566654a6566654a6566654a6566654a6566654a6566654a656665" + "4a6566654a6566654a6566654a6566654a6566654a6566654a6566654a656665" + "4a6566654a6566654a6566654a6566654a6566654a6566654a6566654a656665" + "4a6566654a6566654a6566654a6566654a6566654a6566654a6566654a6566", + "7768617420646f2079612077616e7420666f72206e6f7468696e673f", + "267424dfb8eeb999f3e5ec39a4fe9fd14c923e6187e0897063e5c9e02b2e624a" + "c04413e762977df71a9fb5d562b37f89dfdfb930fce2ed1fa783bbc2a203d80e"); + // Test case with key length 128 bytes. + TestHMACSHA512("4a6566654a6566654a6566654a6566654a6566654a6566654a6566654a656665" + "4a6566654a6566654a6566654a6566654a6566654a6566654a6566654a656665" + "4a6566654a6566654a6566654a6566654a6566654a6566654a6566654a656665" + "4a6566654a6566654a6566654a6566654a6566654a6566654a6566654a656665", + "7768617420646f2079612077616e7420666f72206e6f7468696e673f", + "43aaac07bb1dd97c82c04df921f83b16a68d76815cd1a30d3455ad43a3d80484" + "2bb35462be42cc2e4b5902de4d204c1c66d93b47d1383e3e13a3788687d61258"); + // Test case with key length 129 bytes. + TestHMACSHA512("4a6566654a6566654a6566654a6566654a6566654a6566654a6566654a656665" + "4a6566654a6566654a6566654a6566654a6566654a6566654a6566654a656665" + "4a6566654a6566654a6566654a6566654a6566654a6566654a6566654a656665" + "4a6566654a6566654a6566654a6566654a6566654a6566654a6566654a656665" + "4a", + "7768617420646f2079612077616e7420666f72206e6f7468696e673f", + "0b273325191cfc1b4b71d5075c8fcad67696309d292b1dad2cd23983a35feb8e" + "fb29795e79f2ef27f68cb1e16d76178c307a67beaad9456fac5fdffeadb16e2c"); } BOOST_AUTO_TEST_CASE(aes_testvectors) { diff --git a/src/test/cuckoocache_tests.cpp b/src/test/cuckoocache_tests.cpp index 32d46da984..51ebfc3800 100644 --- a/src/test/cuckoocache_tests.cpp +++ b/src/test/cuckoocache_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2016 The Bitcoin Core developers +// Copyright (c) 2012-2017 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 <boost/test/unit_test.hpp> diff --git a/src/test/data/script_tests.json b/src/test/data/script_tests.json index 698e898231..63f43c0fc6 100644 --- a/src/test/data/script_tests.json +++ b/src/test/data/script_tests.json @@ -862,8 +862,6 @@ ["Ensure 100% coverage of discouraged NOPS"], ["1", "NOP1", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"], -["1", "CHECKLOCKTIMEVERIFY", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"], -["1", "CHECKSEQUENCEVERIFY", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"], ["1", "NOP4", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"], ["1", "NOP5", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"], ["1", "NOP6", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"], diff --git a/src/test/data/tx_valid.json b/src/test/data/tx_valid.json index ad74b7cf1b..a845083636 100644 --- a/src/test/data/tx_valid.json +++ b/src/test/data/tx_valid.json @@ -56,6 +56,12 @@ [[["0000000000000000000000000000000000000000000000000000000000000200", 0, "1"], ["0000000000000000000000000000000000000000000000000000000000000100", 0, "DUP HASH160 0x14 0xe52b482f2faa8ecbf0db344f93c84ac908557f33 EQUALVERIFY CHECKSIG"]], "01000000020002000000000000000000000000000000000000000000000000000000000000000000000151ffffffff0001000000000000000000000000000000000000000000000000000000000000000000006b483045022100c9cdd08798a28af9d1baf44a6c77bcc7e279f47dc487c8c899911bc48feaffcc0220503c5c50ae3998a733263c5c0f7061b483e2b56c4c41b456e7d2f5a78a74c077032102d5c25adb51b61339d2b05315791e21bbe80ea470a49db0135720983c905aace0ffffffff010000000000000000015100000000", "P2SH"], +["The following tests SIGHASH_SINGLE|SIGHASHANYONECANPAY inputs"], +[[["437a1002eb125dec0f93f635763e0ae45f28ff8e81d82945753d0107611cd390", 1, "DUP HASH160 0x14 0x383fb81cb0a3fc724b5e08cf8bbd404336d711f6 EQUALVERIFY CHECKSIG"], + ["2d48d32ccad087bcda0ac5b31555bd58d1d2568184cbc8e752dd2be2684af03f", 1, "DUP HASH160 0x14 0x275ec2a233e5b23d43fa19e7bf9beb0cb3996117 EQUALVERIFY CHECKSIG"], + ["c76168ef1a272a4f176e55e73157ecfce040cfad16a5272f6296eb7089dca846", 1, "DUP HASH160 0x14 0x34fea2c5a75414fd945273ae2d029ce1f28dafcf EQUALVERIFY CHECKSIG"]], +"010000000390d31c6107013d754529d8818eff285fe40a3e7635f6930fec5d12eb02107a43010000006b483045022100f40815ae3c81a0dd851cc8d376d6fd226c88416671346a9033468cca2cdcc6c202204f764623903e6c4bed1b734b75d82c40f1725e4471a55ad4f51218f86130ac038321033d710ab45bb54ac99618ad23b3c1da661631aa25f23bfe9d22b41876f1d46e4effffffff3ff04a68e22bdd52e7c8cb848156d2d158bd5515b3c50adabc87d0ca2cd3482d010000006a4730440220598d263c107004008e9e26baa1e770be30fd31ee55ded1898f7c00da05a75977022045536bead322ca246779698b9c3df3003377090f41afeca7fb2ce9e328ec4af2832102b738b531def73020bd637f32935924cc88549c8206976226d968edd3a42fc2d7ffffffff46a8dc8970eb96622f27a516adcf40e0fcec5731e7556e174f2a271aef6861c7010000006b483045022100c5b90a777a9fdc90c208dbef7290d1fc1be651f47151ee4ccff646872a454cf90220640cfbc4550446968fbbe9d12528f3adf7d87b31541569c59e790db8a220482583210391332546e22bbe8fe3af54addfad6f8b83d05fa4f5e047593d4c07ae938795beffffffff028036be26000000001976a914ddfb29efad43a667465ac59ff14dc6442a1adfca88ac3d5cba01000000001976a914b64dde7a505a13ca986c40e86e984a8dc81368b688ac00000000", "P2SH"], + ["An invalid P2SH Transaction"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x7a052c840ba73af26755de42cf01cc9e0a49fef0 EQUAL"]], "010000000100010000000000000000000000000000000000000000000000000000000000000000000009085768617420697320ffffffff010000000000000000015100000000", "NONE"], diff --git a/src/test/dbwrapper_tests.cpp b/src/test/dbwrapper_tests.cpp index 2e1e4da72f..754a86344f 100644 --- a/src/test/dbwrapper_tests.cpp +++ b/src/test/dbwrapper_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2016 The Bitcoin Core developers +// Copyright (c) 2012-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/test/getarg_tests.cpp b/src/test/getarg_tests.cpp index 3c39258693..cd603b7f58 100644 --- a/src/test/getarg_tests.cpp +++ b/src/test/getarg_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2015 The Bitcoin Core developers +// Copyright (c) 2012-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/test/hash_tests.cpp b/src/test/hash_tests.cpp index 68f445d142..0de0a17904 100644 --- a/src/test/hash_tests.cpp +++ b/src/test/hash_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2013-2016 The Bitcoin Core developers +// Copyright (c) 2013-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/test/key_tests.cpp b/src/test/key_tests.cpp index 7b9d7a6398..55ee1ecf6b 100644 --- a/src/test/key_tests.cpp +++ b/src/test/key_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2015 The Bitcoin Core developers +// Copyright (c) 2012-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/test/limitedmap_tests.cpp b/src/test/limitedmap_tests.cpp index 90730cd7b5..a4bd63cdef 100644 --- a/src/test/limitedmap_tests.cpp +++ b/src/test/limitedmap_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2016 The Bitcoin Core developers +// Copyright (c) 2012-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/test/main_tests.cpp b/src/test/main_tests.cpp index 4be32f7628..a833a5cb1e 100644 --- a/src/test/main_tests.cpp +++ b/src/test/main_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2016 The Bitcoin Core developers +// Copyright (c) 2014-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/test/mempool_tests.cpp b/src/test/mempool_tests.cpp index a694b870fe..1766c6a093 100644 --- a/src/test/mempool_tests.cpp +++ b/src/test/mempool_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -287,35 +287,6 @@ BOOST_AUTO_TEST_CASE(MempoolIndexingTest) pool.removeRecursive(pool.mapTx.find(tx9.GetHash())->GetTx()); pool.removeRecursive(pool.mapTx.find(tx8.GetHash())->GetTx()); - /* Now check the sort on the mining score index. - * Final order should be: - * - * tx7 (2M) - * tx2 (20k) - * tx4 (15000) - * tx1/tx5 (10000) - * tx3/6 (0) - * (Ties resolved by hash) - */ - sortedOrder.clear(); - sortedOrder.push_back(tx7.GetHash().ToString()); - sortedOrder.push_back(tx2.GetHash().ToString()); - sortedOrder.push_back(tx4.GetHash().ToString()); - if (tx1.GetHash() < tx5.GetHash()) { - sortedOrder.push_back(tx5.GetHash().ToString()); - sortedOrder.push_back(tx1.GetHash().ToString()); - } else { - sortedOrder.push_back(tx1.GetHash().ToString()); - sortedOrder.push_back(tx5.GetHash().ToString()); - } - if (tx3.GetHash() < tx6.GetHash()) { - sortedOrder.push_back(tx6.GetHash().ToString()); - sortedOrder.push_back(tx3.GetHash().ToString()); - } else { - sortedOrder.push_back(tx3.GetHash().ToString()); - sortedOrder.push_back(tx6.GetHash().ToString()); - } - CheckSort<mining_score>(pool, sortedOrder); } BOOST_AUTO_TEST_CASE(MempoolAncestorIndexingTest) @@ -427,6 +398,23 @@ BOOST_AUTO_TEST_CASE(MempoolAncestorIndexingTest) sortedOrder.erase(sortedOrder.end()-2); sortedOrder.insert(sortedOrder.begin(), tx7.GetHash().ToString()); CheckSort<ancestor_score>(pool, sortedOrder); + + // High-fee parent, low-fee child + // tx7 -> tx8 + CMutableTransaction tx8 = CMutableTransaction(); + tx8.vin.resize(1); + tx8.vin[0].prevout = COutPoint(tx7.GetHash(), 0); + tx8.vin[0].scriptSig = CScript() << OP_11; + tx8.vout.resize(1); + tx8.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL; + tx8.vout[0].nValue = 10*COIN; + + // Check that we sort by min(feerate, ancestor_feerate): + // set the fee so that the ancestor feerate is above tx1/5, + // but the transaction's own feerate is lower + pool.addUnchecked(tx8.GetHash(), entry.Fee(5000LL).FromTx(tx8)); + sortedOrder.insert(sortedOrder.end()-1, tx8.GetHash().ToString()); + CheckSort<ancestor_score>(pool, sortedOrder); } diff --git a/src/test/merkle_tests.cpp b/src/test/merkle_tests.cpp index ee48d96ad9..72a2672352 100644 --- a/src/test/merkle_tests.cpp +++ b/src/test/merkle_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2016 The Bitcoin Core developers +// Copyright (c) 2015-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp index b1a2032ea8..d9f6772c2d 100644 --- a/src/test/miner_tests.cpp +++ b/src/test/miner_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -26,6 +26,17 @@ BOOST_FIXTURE_TEST_SUITE(miner_tests, TestingSetup) +// BOOST_CHECK_EXCEPTION predicates to check the specific validation error +class HasReason { +public: + HasReason(const std::string& reason) : m_reason(reason) {} + bool operator() (const std::runtime_error& e) const { + return std::string(e.what()).find(m_reason) != std::string::npos; + }; +private: + const std::string m_reason; +}; + static CFeeRate blockMinFeeRate = CFeeRate(DEFAULT_BLOCK_MIN_TX_FEE); static BlockAssembler AssemblerForTest(const CChainParams& params) { @@ -205,7 +216,6 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) entry.nFee = 11; entry.nHeight = 11; - LOCK(cs_main); fCheckpointsEnabled = false; // Simple block creation, nothing special yet: @@ -218,27 +228,32 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) for (unsigned int i = 0; i < sizeof(blockinfo)/sizeof(*blockinfo); ++i) { CBlock *pblock = &pblocktemplate->block; // pointer for convenience - pblock->nVersion = 1; - pblock->nTime = chainActive.Tip()->GetMedianTimePast()+1; - CMutableTransaction txCoinbase(*pblock->vtx[0]); - txCoinbase.nVersion = 1; - txCoinbase.vin[0].scriptSig = CScript(); - txCoinbase.vin[0].scriptSig.push_back(blockinfo[i].extranonce); - txCoinbase.vin[0].scriptSig.push_back(chainActive.Height()); - txCoinbase.vout.resize(1); // Ignore the (optional) segwit commitment added by CreateNewBlock (as the hardcoded nonces don't account for this) - txCoinbase.vout[0].scriptPubKey = CScript(); - pblock->vtx[0] = MakeTransactionRef(std::move(txCoinbase)); - if (txFirst.size() == 0) - baseheight = chainActive.Height(); - if (txFirst.size() < 4) - txFirst.push_back(pblock->vtx[0]); - pblock->hashMerkleRoot = BlockMerkleRoot(*pblock); - pblock->nNonce = blockinfo[i].nonce; + { + LOCK(cs_main); + pblock->nVersion = 1; + pblock->nTime = chainActive.Tip()->GetMedianTimePast()+1; + CMutableTransaction txCoinbase(*pblock->vtx[0]); + txCoinbase.nVersion = 1; + txCoinbase.vin[0].scriptSig = CScript(); + txCoinbase.vin[0].scriptSig.push_back(blockinfo[i].extranonce); + txCoinbase.vin[0].scriptSig.push_back(chainActive.Height()); + txCoinbase.vout.resize(1); // Ignore the (optional) segwit commitment added by CreateNewBlock (as the hardcoded nonces don't account for this) + txCoinbase.vout[0].scriptPubKey = CScript(); + pblock->vtx[0] = MakeTransactionRef(std::move(txCoinbase)); + if (txFirst.size() == 0) + baseheight = chainActive.Height(); + if (txFirst.size() < 4) + txFirst.push_back(pblock->vtx[0]); + pblock->hashMerkleRoot = BlockMerkleRoot(*pblock); + pblock->nNonce = blockinfo[i].nonce; + } std::shared_ptr<const CBlock> shared_pblock = std::make_shared<const CBlock>(*pblock); BOOST_CHECK(ProcessNewBlock(chainparams, shared_pblock, true, nullptr)); pblock->hashPrevBlock = pblock->GetHash(); } + LOCK(cs_main); + // Just to make sure we can still make simple blocks BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey)); @@ -264,7 +279,8 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) mempool.addUnchecked(hash, entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(spendsCoinbase).FromTx(tx)); tx.vin[0].prevout.hash = hash; } - BOOST_CHECK_THROW(AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error); + + BOOST_CHECK_EXCEPTION(AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error, HasReason("bad-blk-sigops")); mempool.clear(); tx.vin[0].prevout.hash = txFirst[0]->GetHash(); @@ -304,7 +320,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) // orphan in mempool, template creation fails hash = tx.GetHash(); mempool.addUnchecked(hash, entry.Fee(LOWFEE).Time(GetTime()).FromTx(tx)); - BOOST_CHECK_THROW(AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error); + BOOST_CHECK_EXCEPTION(AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error, HasReason("bad-txns-inputs-missingorspent")); mempool.clear(); // child with higher feerate than parent @@ -332,7 +348,8 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) hash = tx.GetHash(); // give it a fee so it'll get mined mempool.addUnchecked(hash, entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(false).FromTx(tx)); - BOOST_CHECK_THROW(AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error); + // Should throw bad-cb-multiple + BOOST_CHECK_EXCEPTION(AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error, HasReason("bad-cb-multiple")); mempool.clear(); // double spend txn pair in mempool, template creation fails @@ -345,7 +362,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) tx.vout[0].scriptPubKey = CScript() << OP_2; hash = tx.GetHash(); mempool.addUnchecked(hash, entry.Fee(HIGHFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx)); - BOOST_CHECK_THROW(AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error); + BOOST_CHECK_EXCEPTION(AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error, HasReason("bad-txns-inputs-missingorspent")); mempool.clear(); // subsidy changing @@ -389,7 +406,8 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) tx.vout[0].nValue -= LOWFEE; hash = tx.GetHash(); mempool.addUnchecked(hash, entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(false).FromTx(tx)); - BOOST_CHECK_THROW(AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error); + // Should throw block-validation-failed + BOOST_CHECK_EXCEPTION(AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error, HasReason("block-validation-failed")); mempool.clear(); // Delete the dummy blocks again. diff --git a/src/test/multisig_tests.cpp b/src/test/multisig_tests.cpp index ffba7d6d22..72d9d3d75c 100644 --- a/src/test/multisig_tests.cpp +++ b/src/test/multisig_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/test/net_tests.cpp b/src/test/net_tests.cpp index b4176a2b85..ca57f58905 100644 --- a/src/test/net_tests.cpp +++ b/src/test/net_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2016 The Bitcoin Core developers +// Copyright (c) 2012-2017 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 <addrman.h> diff --git a/src/test/netbase_tests.cpp b/src/test/netbase_tests.cpp index f3a9b1fc65..027214e512 100644 --- a/src/test/netbase_tests.cpp +++ b/src/test/netbase_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2016 The Bitcoin Core developers +// Copyright (c) 2012-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/test/pmt_tests.cpp b/src/test/pmt_tests.cpp index b7b632be3a..4825c92296 100644 --- a/src/test/pmt_tests.cpp +++ b/src/test/pmt_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2016 The Bitcoin Core developers +// Copyright (c) 2012-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/test/policyestimator_tests.cpp b/src/test/policyestimator_tests.cpp index d8026e4468..8d288ec993 100644 --- a/src/test/policyestimator_tests.cpp +++ b/src/test/policyestimator_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/test/pow_tests.cpp b/src/test/pow_tests.cpp index 2837537c9a..26b2f5d0d7 100644 --- a/src/test/pow_tests.cpp +++ b/src/test/pow_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2015 The Bitcoin Core developers +// Copyright (c) 2015-2017 The Bitcoin Core developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/test/prevector_tests.cpp b/src/test/prevector_tests.cpp index 1327d67650..db9162c0db 100644 --- a/src/test/prevector_tests.cpp +++ b/src/test/prevector_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2016 The Bitcoin Core developers +// Copyright (c) 2015-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/test/raii_event_tests.cpp b/src/test/raii_event_tests.cpp index 781b1e242d..7bc81c7f64 100644 --- a/src/test/raii_event_tests.cpp +++ b/src/test/raii_event_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2016 The Bitcoin Core developers +// Copyright (c) 2016-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/test/reverselock_tests.cpp b/src/test/reverselock_tests.cpp index 86d6161e20..0a91c65afa 100644 --- a/src/test/reverselock_tests.cpp +++ b/src/test/reverselock_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2016 The Bitcoin Core developers +// Copyright (c) 2015-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/test/rpc_tests.cpp b/src/test/rpc_tests.cpp index 710d09ead6..ed86413b2f 100644 --- a/src/test/rpc_tests.cpp +++ b/src/test/rpc_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2016 The Bitcoin Core developers +// Copyright (c) 2012-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -65,7 +65,9 @@ BOOST_AUTO_TEST_CASE(rpc_rawparams) BOOST_CHECK_EQUAL(find_value(r.get_obj(), "size").get_int(), 193); BOOST_CHECK_EQUAL(find_value(r.get_obj(), "version").get_int(), 1); BOOST_CHECK_EQUAL(find_value(r.get_obj(), "locktime").get_int(), 0); - BOOST_CHECK_THROW(r = CallRPC(std::string("decoderawtransaction ")+rawtx+" extra"), std::runtime_error); + BOOST_CHECK_THROW(CallRPC(std::string("decoderawtransaction ")+rawtx+" extra"), std::runtime_error); + BOOST_CHECK_NO_THROW(r = CallRPC(std::string("decoderawtransaction ")+rawtx+" false")); + BOOST_CHECK_THROW(r = CallRPC(std::string("decoderawtransaction ")+rawtx+" false extra"), std::runtime_error); BOOST_CHECK_THROW(CallRPC("signrawtransaction"), std::runtime_error); BOOST_CHECK_THROW(CallRPC("signrawtransaction null"), std::runtime_error); diff --git a/src/test/sanity_tests.cpp b/src/test/sanity_tests.cpp index b3ec6d34c7..e97ad2ee6a 100644 --- a/src/test/sanity_tests.cpp +++ b/src/test/sanity_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2015 The Bitcoin Core developers +// Copyright (c) 2012-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/test/scheduler_tests.cpp b/src/test/scheduler_tests.cpp index 7e86eed1c5..760f933abc 100644 --- a/src/test/scheduler_tests.cpp +++ b/src/test/scheduler_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2016 The Bitcoin Core developers +// Copyright (c) 2012-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/test/script_P2SH_tests.cpp b/src/test/script_P2SH_tests.cpp index 5a64aa3959..63d211dd97 100644 --- a/src/test/script_P2SH_tests.cpp +++ b/src/test/script_P2SH_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2016 The Bitcoin Core developers +// Copyright (c) 2012-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/test/script_standard_tests.cpp b/src/test/script_standard_tests.cpp index 19060eccc9..cd30fbeda7 100644 --- a/src/test/script_standard_tests.cpp +++ b/src/test/script_standard_tests.cpp @@ -508,12 +508,7 @@ BOOST_AUTO_TEST_CASE(script_standard_IsMine) scriptPubKey.clear(); scriptPubKey << OP_0 << ToByteVector(pubkeys[0].GetID()); - // Keystore has key, but no P2SH redeemScript - result = IsMine(keystore, scriptPubKey, isInvalid); - BOOST_CHECK_EQUAL(result, ISMINE_NO); - BOOST_CHECK(!isInvalid); - - // Keystore has key and P2SH redeemScript + // Keystore implicitly has key and P2SH redeemScript keystore.AddCScript(scriptPubKey); result = IsMine(keystore, scriptPubKey, isInvalid); BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE); diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp index 57b3e501af..c7a497f3a7 100644 --- a/src/test/script_tests.cpp +++ b/src/test/script_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -166,6 +166,17 @@ void DoTest(const CScript& scriptPubKey, const CScript& scriptSig, const CScript CMutableTransaction tx2 = tx; BOOST_CHECK_MESSAGE(VerifyScript(scriptSig, scriptPubKey, &scriptWitness, flags, MutableTransactionSignatureChecker(&tx, 0, txCredit.vout[0].nValue), &err) == expect, message); BOOST_CHECK_MESSAGE(err == scriptError, std::string(FormatScriptError(err)) + " where " + std::string(FormatScriptError((ScriptError_t)scriptError)) + " expected: " + message); + + // Verify that removing flags from a passing test or adding flags to a failing test does not change the result. + for (int i = 0; i < 16; ++i) { + int extra_flags = InsecureRandBits(16); + int combined_flags = expect ? (flags & ~extra_flags) : (flags | extra_flags); + // Weed out some invalid flag combinations. + if (combined_flags & SCRIPT_VERIFY_CLEANSTACK && ~combined_flags & (SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS)) continue; + if (combined_flags & SCRIPT_VERIFY_WITNESS && ~combined_flags & SCRIPT_VERIFY_P2SH) continue; + BOOST_CHECK_MESSAGE(VerifyScript(scriptSig, scriptPubKey, &scriptWitness, combined_flags, MutableTransactionSignatureChecker(&tx, 0, txCredit.vout[0].nValue), &err) == expect, message + strprintf(" (with flags %x)", combined_flags)); + } + #if defined(HAVE_CONSENSUS_LIB) CDataStream stream(SER_NETWORK, PROTOCOL_VERSION); stream << tx2; diff --git a/src/test/scriptnum10.h b/src/test/scriptnum10.h index ad15427a9b..9e88866cb0 100644 --- a/src/test/scriptnum10.h +++ b/src/test/scriptnum10.h @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2015 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/test/scriptnum_tests.cpp b/src/test/scriptnum_tests.cpp index aef500174a..cd6e27d248 100644 --- a/src/test/scriptnum_tests.cpp +++ b/src/test/scriptnum_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2015 The Bitcoin Core developers +// Copyright (c) 2012-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/test/serialize_tests.cpp b/src/test/serialize_tests.cpp index 28ed2bfeb0..4595519435 100644 --- a/src/test/serialize_tests.cpp +++ b/src/test/serialize_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2016 The Bitcoin Core developers +// Copyright (c) 2012-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/test/sighash_tests.cpp b/src/test/sighash_tests.cpp index d97e106287..32cd3a50b0 100644 --- a/src/test/sighash_tests.cpp +++ b/src/test/sighash_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2013-2016 The Bitcoin Core developers +// Copyright (c) 2013-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/test/sigopcount_tests.cpp b/src/test/sigopcount_tests.cpp index 891cd1e1d8..b4d8a2419e 100644 --- a/src/test/sigopcount_tests.cpp +++ b/src/test/sigopcount_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2016 The Bitcoin Core developers +// Copyright (c) 2012-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/test/skiplist_tests.cpp b/src/test/skiplist_tests.cpp index 1ffd9f2b42..25c7e54808 100644 --- a/src/test/skiplist_tests.cpp +++ b/src/test/skiplist_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2016 The Bitcoin Core developers +// Copyright (c) 2014-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/test/streams_tests.cpp b/src/test/streams_tests.cpp index 3636e6c332..1108dab584 100644 --- a/src/test/streams_tests.cpp +++ b/src/test/streams_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2016 The Bitcoin Core developers +// Copyright (c) 2012-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp index 419106194e..bdd44489f4 100644 --- a/src/test/test_bitcoin.cpp +++ b/src/test/test_bitcoin.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -8,15 +8,9 @@ #include <consensus/consensus.h> #include <consensus/validation.h> #include <crypto/sha256.h> -#include <fs.h> -#include <key.h> #include <validation.h> #include <miner.h> #include <net_processing.h> -#include <pubkey.h> -#include <random.h> -#include <txdb.h> -#include <txmempool.h> #include <ui_interface.h> #include <streams.h> #include <rpc/server.h> @@ -75,9 +69,9 @@ TestingSetup::TestingSetup(const std::string& chainName) : BasicTestingSetup(cha fs::create_directories(pathTemp); gArgs.ForceSetArg("-datadir", pathTemp.string()); - // Note that because we don't bother running a scheduler thread here, - // callbacks via CValidationInterface are unreliable, but that's OK, - // our unit tests aren't testing multiple parts of the code at once. + // We have to run a scheduler thread to prevent ActivateBestChain + // from blocking due to queue overrun. + threadGroup.create_thread(boost::bind(&CScheduler::serviceQueue, &scheduler)); GetMainSignals().RegisterBackgroundSignalScheduler(scheduler); mempool.setSanityCheck(1.0); diff --git a/src/test/test_bitcoin.h b/src/test/test_bitcoin.h index 80a9cbaeea..944835cccf 100644 --- a/src/test/test_bitcoin.h +++ b/src/test/test_bitcoin.h @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2016 The Bitcoin Core developers +// Copyright (c) 2015-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/test/test_bitcoin_fuzzy.cpp b/src/test/test_bitcoin_fuzzy.cpp index 319d81187a..aaba2095e0 100644 --- a/src/test/test_bitcoin_fuzzy.cpp +++ b/src/test/test_bitcoin_fuzzy.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/test/test_bitcoin_main.cpp b/src/test/test_bitcoin_main.cpp index 8d81ff6fc6..64408e9c5b 100644 --- a/src/test/test_bitcoin_main.cpp +++ b/src/test/test_bitcoin_main.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/test/timedata_tests.cpp b/src/test/timedata_tests.cpp index 9ff95bd2b0..5d93bc1efe 100644 --- a/src/test/timedata_tests.cpp +++ b/src/test/timedata_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. // diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp index 34a182722d..edfb35d155 100644 --- a/src/test/transaction_tests.cpp +++ b/src/test/transaction_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/test/txvalidation_tests.cpp b/src/test/txvalidation_tests.cpp new file mode 100644 index 0000000000..2d1eb7b772 --- /dev/null +++ b/src/test/txvalidation_tests.cpp @@ -0,0 +1,61 @@ +// Copyright (c) 2017 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 <validation.h> +#include <txmempool.h> +#include <amount.h> +#include <consensus/validation.h> +#include <primitives/transaction.h> +#include <script/script.h> +#include <test/test_bitcoin.h> + +#include <boost/test/unit_test.hpp> + + +BOOST_AUTO_TEST_SUITE(txvalidation_tests) + +/** + * Ensure that the mempool won't accept coinbase transactions. + */ +BOOST_FIXTURE_TEST_CASE(tx_mempool_reject_coinbase, TestChain100Setup) +{ + CScript scriptPubKey = CScript() << ToByteVector(coinbaseKey.GetPubKey()) << OP_CHECKSIG; + CMutableTransaction coinbaseTx; + + coinbaseTx.nVersion = 1; + coinbaseTx.vin.resize(1); + coinbaseTx.vout.resize(1); + coinbaseTx.vin[0].scriptSig = CScript() << OP_11 << OP_EQUAL; + coinbaseTx.vout[0].nValue = 1 * CENT; + coinbaseTx.vout[0].scriptPubKey = scriptPubKey; + + assert(CTransaction(coinbaseTx).IsCoinBase()); + + CValidationState state; + + LOCK(cs_main); + + unsigned int initialPoolSize = mempool.size(); + + BOOST_CHECK_EQUAL( + false, + AcceptToMemoryPool(mempool, state, MakeTransactionRef(coinbaseTx), + nullptr /* pfMissingInputs */, + nullptr /* plTxnReplaced */, + true /* bypass_limits */, + 0 /* nAbsurdFee */)); + + // Check that the transaction hasn't been added to mempool. + BOOST_CHECK_EQUAL(mempool.size(), initialPoolSize); + + // Check that the validation state reflects the unsuccessful attempt. + BOOST_CHECK(state.IsInvalid()); + BOOST_CHECK_EQUAL(state.GetRejectReason(), "coinbase"); + + int nDoS; + BOOST_CHECK_EQUAL(state.IsInvalid(nDoS), true); + BOOST_CHECK_EQUAL(nDoS, 100); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/txvalidationcache_tests.cpp b/src/test/txvalidationcache_tests.cpp index fa49b9c33b..9ec9d6cba3 100644 --- a/src/test/txvalidationcache_tests.cpp +++ b/src/test/txvalidationcache_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -66,7 +66,6 @@ BOOST_FIXTURE_TEST_CASE(tx_mempool_block_doublespend, TestChain100Setup) // Test 1: block with both of those transactions should be rejected. block = CreateAndProcessBlock(spends, scriptPubKey); - LOCK(cs_main); BOOST_CHECK(chainActive.Tip()->GetBlockHash() != block.GetHash()); // Test 2: ... and should be rejected if spend1 is in the memory pool @@ -103,7 +102,7 @@ BOOST_FIXTURE_TEST_CASE(tx_mempool_block_doublespend, TestChain100Setup) // should fail. // Capture this interaction with the upgraded_nop argument: set it when evaluating // any script flag that is implemented as an upgraded NOP code. -void ValidateCheckInputsForAllFlags(CMutableTransaction &tx, uint32_t failing_flags, bool add_to_cache, bool upgraded_nop) +void ValidateCheckInputsForAllFlags(CMutableTransaction &tx, uint32_t failing_flags, bool add_to_cache) { PrecomputedTransactionData txdata(tx); // If we add many more flags, this loop can get too expensive, but we can @@ -124,12 +123,6 @@ void ValidateCheckInputsForAllFlags(CMutableTransaction &tx, uint32_t failing_fl // CheckInputs should succeed iff test_flags doesn't intersect with // failing_flags bool expected_return_value = !(test_flags & failing_flags); - if (expected_return_value && upgraded_nop) { - // If the script flag being tested corresponds to an upgraded NOP, - // then script execution should fail if DISCOURAGE_UPGRADABLE_NOPS - // is set. - expected_return_value = !(test_flags & SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS); - } BOOST_CHECK_EQUAL(ret, expected_return_value); // Test the caching @@ -196,12 +189,12 @@ BOOST_FIXTURE_TEST_CASE(checkinputs_test, TestChain100Setup) spend_tx.vin[0].scriptSig << vchSig; } - LOCK(cs_main); - // Test that invalidity under a set of flags doesn't preclude validity // under other (eg consensus) flags. // spend_tx is invalid according to DERSIG { + LOCK(cs_main); + CValidationState state; PrecomputedTransactionData ptd_spend_tx(spend_tx); @@ -218,16 +211,18 @@ BOOST_FIXTURE_TEST_CASE(checkinputs_test, TestChain100Setup) // not present. Don't add these checks to the cache, so that we can // test later that block validation works fine in the absence of cached // successes. - ValidateCheckInputsForAllFlags(spend_tx, SCRIPT_VERIFY_DERSIG | SCRIPT_VERIFY_LOW_S | SCRIPT_VERIFY_STRICTENC, false, false); + ValidateCheckInputsForAllFlags(spend_tx, SCRIPT_VERIFY_DERSIG | SCRIPT_VERIFY_LOW_S | SCRIPT_VERIFY_STRICTENC, false); + } - // And if we produce a block with this tx, it should be valid (DERSIG not - // enabled yet), even though there's no cache entry. - CBlock block; + // And if we produce a block with this tx, it should be valid (DERSIG not + // enabled yet), even though there's no cache entry. + CBlock block; - block = CreateAndProcessBlock({spend_tx}, p2pk_scriptPubKey); - BOOST_CHECK(chainActive.Tip()->GetBlockHash() == block.GetHash()); - BOOST_CHECK(pcoinsTip->GetBestBlock() == block.GetHash()); - } + block = CreateAndProcessBlock({spend_tx}, p2pk_scriptPubKey); + BOOST_CHECK(chainActive.Tip()->GetBlockHash() == block.GetHash()); + BOOST_CHECK(pcoinsTip->GetBestBlock() == block.GetHash()); + + LOCK(cs_main); // Test P2SH: construct a transaction that is valid without P2SH, and // then test validity with P2SH. @@ -243,7 +238,7 @@ BOOST_FIXTURE_TEST_CASE(checkinputs_test, TestChain100Setup) std::vector<unsigned char> vchSig2(p2pk_scriptPubKey.begin(), p2pk_scriptPubKey.end()); invalid_under_p2sh_tx.vin[0].scriptSig << vchSig2; - ValidateCheckInputsForAllFlags(invalid_under_p2sh_tx, SCRIPT_VERIFY_P2SH, true, false); + ValidateCheckInputsForAllFlags(invalid_under_p2sh_tx, SCRIPT_VERIFY_P2SH, true); } // Test CHECKLOCKTIMEVERIFY @@ -266,7 +261,7 @@ BOOST_FIXTURE_TEST_CASE(checkinputs_test, TestChain100Setup) vchSig.push_back((unsigned char)SIGHASH_ALL); invalid_with_cltv_tx.vin[0].scriptSig = CScript() << vchSig << 101; - ValidateCheckInputsForAllFlags(invalid_with_cltv_tx, SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY, true, true); + ValidateCheckInputsForAllFlags(invalid_with_cltv_tx, SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY, true); // Make it valid, and check again invalid_with_cltv_tx.vin[0].scriptSig = CScript() << vchSig << 100; @@ -294,7 +289,7 @@ BOOST_FIXTURE_TEST_CASE(checkinputs_test, TestChain100Setup) vchSig.push_back((unsigned char)SIGHASH_ALL); invalid_with_csv_tx.vin[0].scriptSig = CScript() << vchSig << 101; - ValidateCheckInputsForAllFlags(invalid_with_csv_tx, SCRIPT_VERIFY_CHECKSEQUENCEVERIFY, true, true); + ValidateCheckInputsForAllFlags(invalid_with_csv_tx, SCRIPT_VERIFY_CHECKSEQUENCEVERIFY, true); // Make it valid, and check again invalid_with_csv_tx.vin[0].scriptSig = CScript() << vchSig << 100; @@ -323,11 +318,11 @@ BOOST_FIXTURE_TEST_CASE(checkinputs_test, TestChain100Setup) UpdateTransaction(valid_with_witness_tx, 0, sigdata); // This should be valid under all script flags. - ValidateCheckInputsForAllFlags(valid_with_witness_tx, 0, true, false); + ValidateCheckInputsForAllFlags(valid_with_witness_tx, 0, true); // Remove the witness, and check that it is now invalid. valid_with_witness_tx.vin[0].scriptWitness.SetNull(); - ValidateCheckInputsForAllFlags(valid_with_witness_tx, SCRIPT_VERIFY_WITNESS, true, false); + ValidateCheckInputsForAllFlags(valid_with_witness_tx, SCRIPT_VERIFY_WITNESS, true); } { @@ -352,7 +347,7 @@ BOOST_FIXTURE_TEST_CASE(checkinputs_test, TestChain100Setup) } // This should be valid under all script flags - ValidateCheckInputsForAllFlags(tx, 0, true, false); + ValidateCheckInputsForAllFlags(tx, 0, true); // Check that if the second input is invalid, but the first input is // valid, the transaction is not cached. diff --git a/src/test/uint256_tests.cpp b/src/test/uint256_tests.cpp index 40ef9adb2e..ad5478e829 100644 --- a/src/test/uint256_tests.cpp +++ b/src/test/uint256_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 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 <arith_uint256.h> diff --git a/src/test/univalue_tests.cpp b/src/test/univalue_tests.cpp deleted file mode 100644 index 7386204437..0000000000 --- a/src/test/univalue_tests.cpp +++ /dev/null @@ -1,333 +0,0 @@ -// Copyright (c) 2014 BitPay Inc. -// 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. - -#include <stdint.h> -#include <vector> -#include <string> -#include <map> -#include <univalue.h> -#include <test/test_bitcoin.h> - -#include <boost/test/unit_test.hpp> - -BOOST_FIXTURE_TEST_SUITE(univalue_tests, BasicTestingSetup) - -BOOST_AUTO_TEST_CASE(univalue_constructor) -{ - UniValue v1; - BOOST_CHECK(v1.isNull()); - - UniValue v2(UniValue::VSTR); - BOOST_CHECK(v2.isStr()); - - UniValue v3(UniValue::VSTR, "foo"); - BOOST_CHECK(v3.isStr()); - BOOST_CHECK_EQUAL(v3.getValStr(), "foo"); - - UniValue numTest; - BOOST_CHECK(numTest.setNumStr("82")); - BOOST_CHECK(numTest.isNum()); - BOOST_CHECK_EQUAL(numTest.getValStr(), "82"); - - uint64_t vu64 = 82; - UniValue v4(vu64); - BOOST_CHECK(v4.isNum()); - BOOST_CHECK_EQUAL(v4.getValStr(), "82"); - - int64_t vi64 = -82; - UniValue v5(vi64); - BOOST_CHECK(v5.isNum()); - BOOST_CHECK_EQUAL(v5.getValStr(), "-82"); - - int vi = -688; - UniValue v6(vi); - BOOST_CHECK(v6.isNum()); - BOOST_CHECK_EQUAL(v6.getValStr(), "-688"); - - double vd = -7.21; - UniValue v7(vd); - BOOST_CHECK(v7.isNum()); - BOOST_CHECK_EQUAL(v7.getValStr(), "-7.21"); - - std::string vs("yawn"); - UniValue v8(vs); - BOOST_CHECK(v8.isStr()); - BOOST_CHECK_EQUAL(v8.getValStr(), "yawn"); - - const char *vcs = "zappa"; - UniValue v9(vcs); - BOOST_CHECK(v9.isStr()); - BOOST_CHECK_EQUAL(v9.getValStr(), "zappa"); -} - -BOOST_AUTO_TEST_CASE(univalue_typecheck) -{ - UniValue v1; - BOOST_CHECK(v1.setNumStr("1")); - BOOST_CHECK(v1.isNum()); - BOOST_CHECK_THROW(v1.get_bool(), std::runtime_error); - - UniValue v2; - BOOST_CHECK(v2.setBool(true)); - BOOST_CHECK_EQUAL(v2.get_bool(), true); - BOOST_CHECK_THROW(v2.get_int(), std::runtime_error); - - UniValue v3; - BOOST_CHECK(v3.setNumStr("32482348723847471234")); - BOOST_CHECK_THROW(v3.get_int64(), std::runtime_error); - BOOST_CHECK(v3.setNumStr("1000")); - BOOST_CHECK_EQUAL(v3.get_int64(), 1000); - - UniValue v4; - BOOST_CHECK(v4.setNumStr("2147483648")); - BOOST_CHECK_EQUAL(v4.get_int64(), 2147483648); - BOOST_CHECK_THROW(v4.get_int(), std::runtime_error); - BOOST_CHECK(v4.setNumStr("1000")); - BOOST_CHECK_EQUAL(v4.get_int(), 1000); - BOOST_CHECK_THROW(v4.get_str(), std::runtime_error); - BOOST_CHECK_EQUAL(v4.get_real(), 1000); - BOOST_CHECK_THROW(v4.get_array(), std::runtime_error); - BOOST_CHECK_THROW(v4.getKeys(), std::runtime_error); - BOOST_CHECK_THROW(v4.getValues(), std::runtime_error); - BOOST_CHECK_THROW(v4.get_obj(), std::runtime_error); - - UniValue v5; - BOOST_CHECK(v5.read("[true, 10]")); - BOOST_CHECK_NO_THROW(v5.get_array()); - std::vector<UniValue> vals = v5.getValues(); - BOOST_CHECK_THROW(vals[0].get_int(), std::runtime_error); - BOOST_CHECK_EQUAL(vals[0].get_bool(), true); - - BOOST_CHECK_EQUAL(vals[1].get_int(), 10); - BOOST_CHECK_THROW(vals[1].get_bool(), std::runtime_error); -} - -BOOST_AUTO_TEST_CASE(univalue_set) -{ - UniValue v(UniValue::VSTR, "foo"); - v.clear(); - BOOST_CHECK(v.isNull()); - BOOST_CHECK_EQUAL(v.getValStr(), ""); - - BOOST_CHECK(v.setObject()); - BOOST_CHECK(v.isObject()); - BOOST_CHECK_EQUAL(v.size(), 0); - BOOST_CHECK_EQUAL(v.getType(), UniValue::VOBJ); - BOOST_CHECK(v.empty()); - - BOOST_CHECK(v.setArray()); - BOOST_CHECK(v.isArray()); - BOOST_CHECK_EQUAL(v.size(), 0); - - BOOST_CHECK(v.setStr("zum")); - BOOST_CHECK(v.isStr()); - BOOST_CHECK_EQUAL(v.getValStr(), "zum"); - - BOOST_CHECK(v.setFloat(-1.01)); - BOOST_CHECK(v.isNum()); - BOOST_CHECK_EQUAL(v.getValStr(), "-1.01"); - - BOOST_CHECK(v.setInt((int)1023)); - BOOST_CHECK(v.isNum()); - BOOST_CHECK_EQUAL(v.getValStr(), "1023"); - - BOOST_CHECK(v.setInt((int64_t)-1023LL)); - BOOST_CHECK(v.isNum()); - BOOST_CHECK_EQUAL(v.getValStr(), "-1023"); - - BOOST_CHECK(v.setInt((uint64_t)1023ULL)); - BOOST_CHECK(v.isNum()); - BOOST_CHECK_EQUAL(v.getValStr(), "1023"); - - BOOST_CHECK(v.setNumStr("-688")); - BOOST_CHECK(v.isNum()); - BOOST_CHECK_EQUAL(v.getValStr(), "-688"); - - BOOST_CHECK(v.setBool(false)); - BOOST_CHECK_EQUAL(v.isBool(), true); - BOOST_CHECK_EQUAL(v.isTrue(), false); - BOOST_CHECK_EQUAL(v.isFalse(), true); - BOOST_CHECK_EQUAL(v.getBool(), false); - - BOOST_CHECK(v.setBool(true)); - BOOST_CHECK_EQUAL(v.isBool(), true); - BOOST_CHECK_EQUAL(v.isTrue(), true); - BOOST_CHECK_EQUAL(v.isFalse(), false); - BOOST_CHECK_EQUAL(v.getBool(), true); - - BOOST_CHECK(!v.setNumStr("zombocom")); - - BOOST_CHECK(v.setNull()); - BOOST_CHECK(v.isNull()); -} - -BOOST_AUTO_TEST_CASE(univalue_array) -{ - UniValue arr(UniValue::VARR); - - UniValue v((int64_t)1023LL); - BOOST_CHECK(arr.push_back(v)); - - std::string vStr("zippy"); - BOOST_CHECK(arr.push_back(vStr)); - - const char *s = "pippy"; - BOOST_CHECK(arr.push_back(s)); - - std::vector<UniValue> vec; - v.setStr("boing"); - vec.push_back(v); - - v.setStr("going"); - vec.push_back(v); - - BOOST_CHECK(arr.push_backV(vec)); - - BOOST_CHECK_EQUAL(arr.empty(), false); - BOOST_CHECK_EQUAL(arr.size(), 5); - - BOOST_CHECK_EQUAL(arr[0].getValStr(), "1023"); - BOOST_CHECK_EQUAL(arr[1].getValStr(), "zippy"); - BOOST_CHECK_EQUAL(arr[2].getValStr(), "pippy"); - BOOST_CHECK_EQUAL(arr[3].getValStr(), "boing"); - BOOST_CHECK_EQUAL(arr[4].getValStr(), "going"); - - BOOST_CHECK_EQUAL(arr[999].getValStr(), ""); - - arr.clear(); - BOOST_CHECK(arr.empty()); - BOOST_CHECK_EQUAL(arr.size(), 0); -} - -BOOST_AUTO_TEST_CASE(univalue_object) -{ - UniValue obj(UniValue::VOBJ); - std::string strKey, strVal; - UniValue v; - - strKey = "age"; - v.setInt(100); - BOOST_CHECK(obj.pushKV(strKey, v)); - - strKey = "first"; - strVal = "John"; - BOOST_CHECK(obj.pushKV(strKey, strVal)); - - strKey = "last"; - const char *cVal = "Smith"; - BOOST_CHECK(obj.pushKV(strKey, cVal)); - - strKey = "distance"; - BOOST_CHECK(obj.pushKV(strKey, (int64_t) 25)); - - strKey = "time"; - BOOST_CHECK(obj.pushKV(strKey, (uint64_t) 3600)); - - strKey = "calories"; - BOOST_CHECK(obj.pushKV(strKey, (int) 12)); - - strKey = "temperature"; - BOOST_CHECK(obj.pushKV(strKey, (double) 90.012)); - - UniValue obj2(UniValue::VOBJ); - BOOST_CHECK(obj2.pushKV("cat1", 9000)); - BOOST_CHECK(obj2.pushKV("cat2", 12345)); - - BOOST_CHECK(obj.pushKVs(obj2)); - - BOOST_CHECK_EQUAL(obj.empty(), false); - BOOST_CHECK_EQUAL(obj.size(), 9); - - BOOST_CHECK_EQUAL(obj["age"].getValStr(), "100"); - BOOST_CHECK_EQUAL(obj["first"].getValStr(), "John"); - BOOST_CHECK_EQUAL(obj["last"].getValStr(), "Smith"); - BOOST_CHECK_EQUAL(obj["distance"].getValStr(), "25"); - BOOST_CHECK_EQUAL(obj["time"].getValStr(), "3600"); - BOOST_CHECK_EQUAL(obj["calories"].getValStr(), "12"); - BOOST_CHECK_EQUAL(obj["temperature"].getValStr(), "90.012"); - BOOST_CHECK_EQUAL(obj["cat1"].getValStr(), "9000"); - BOOST_CHECK_EQUAL(obj["cat2"].getValStr(), "12345"); - - BOOST_CHECK_EQUAL(obj["nyuknyuknyuk"].getValStr(), ""); - - BOOST_CHECK(obj.exists("age")); - BOOST_CHECK(obj.exists("first")); - BOOST_CHECK(obj.exists("last")); - BOOST_CHECK(obj.exists("distance")); - BOOST_CHECK(obj.exists("time")); - BOOST_CHECK(obj.exists("calories")); - BOOST_CHECK(obj.exists("temperature")); - BOOST_CHECK(obj.exists("cat1")); - BOOST_CHECK(obj.exists("cat2")); - - BOOST_CHECK(!obj.exists("nyuknyuknyuk")); - - std::map<std::string, UniValue::VType> objTypes; - objTypes["age"] = UniValue::VNUM; - objTypes["first"] = UniValue::VSTR; - objTypes["last"] = UniValue::VSTR; - objTypes["distance"] = UniValue::VNUM; - objTypes["time"] = UniValue::VNUM; - objTypes["calories"] = UniValue::VNUM; - objTypes["temperature"] = UniValue::VNUM; - objTypes["cat1"] = UniValue::VNUM; - objTypes["cat2"] = UniValue::VNUM; - BOOST_CHECK(obj.checkObject(objTypes)); - - objTypes["cat2"] = UniValue::VSTR; - BOOST_CHECK(!obj.checkObject(objTypes)); - - obj.clear(); - BOOST_CHECK(obj.empty()); - BOOST_CHECK_EQUAL(obj.size(), 0); -} - -static const char *json1 = -"[1.10000000,{\"key1\":\"str\\u0000\",\"key2\":800,\"key3\":{\"name\":\"martian http://test.com\"}}]"; - -BOOST_AUTO_TEST_CASE(univalue_readwrite) -{ - UniValue v; - BOOST_CHECK(v.read(json1)); - - std::string strJson1(json1); - BOOST_CHECK(v.read(strJson1)); - - BOOST_CHECK(v.isArray()); - BOOST_CHECK_EQUAL(v.size(), 2); - - BOOST_CHECK_EQUAL(v[0].getValStr(), "1.10000000"); - - UniValue obj = v[1]; - BOOST_CHECK(obj.isObject()); - BOOST_CHECK_EQUAL(obj.size(), 3); - - BOOST_CHECK(obj["key1"].isStr()); - std::string correctValue("str"); - correctValue.push_back('\0'); - BOOST_CHECK_EQUAL(obj["key1"].getValStr(), correctValue); - BOOST_CHECK(obj["key2"].isNum()); - BOOST_CHECK_EQUAL(obj["key2"].getValStr(), "800"); - BOOST_CHECK(obj["key3"].isObject()); - - BOOST_CHECK_EQUAL(strJson1, v.write()); - - /* Check for (correctly reporting) a parsing error if the initial - JSON construct is followed by more stuff. Note that whitespace - is, of course, exempt. */ - - BOOST_CHECK(v.read(" {}\n ")); - BOOST_CHECK(v.isObject()); - BOOST_CHECK(v.read(" []\n ")); - BOOST_CHECK(v.isArray()); - - BOOST_CHECK(!v.read("@{}")); - BOOST_CHECK(!v.read("{} garbage")); - BOOST_CHECK(!v.read("[]{}")); - BOOST_CHECK(!v.read("{}[]")); - BOOST_CHECK(!v.read("{} 42")); -} - -BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp index 998090cd9b..55d60d95e9 100644 --- a/src/test/util_tests.cpp +++ b/src/test/util_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -121,7 +121,7 @@ BOOST_AUTO_TEST_CASE(util_ParseParameters) testArgs.ParseParameters(1, (char**)argv_test); BOOST_CHECK(testArgs.GetMapArgs().empty() && testArgs.GetMapMultiArgs().empty()); - testArgs.ParseParameters(5, (char**)argv_test); + testArgs.ParseParameters(7, (char**)argv_test); // expectation: -ignored is ignored (program name argument), // -a, -b and -ccc end up in map, -d ignored because it is after // a non-option argument (non-GNU option parsing) diff --git a/src/test/versionbits_tests.cpp b/src/test/versionbits_tests.cpp index 7029b347dd..12f113655a 100644 --- a/src/test/versionbits_tests.cpp +++ b/src/test/versionbits_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2016 The Bitcoin Core developers +// Copyright (c) 2014-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/threadinterrupt.cpp b/src/threadinterrupt.cpp index 7bcacc3014..5d932091cb 100644 --- a/src/threadinterrupt.cpp +++ b/src/threadinterrupt.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/timedata.cpp b/src/timedata.cpp index b91cf01723..a803b2fc87 100644 --- a/src/timedata.cpp +++ b/src/timedata.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2016 The Bitcoin Core developers +// Copyright (c) 2014-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/timedata.h b/src/timedata.h index bc5451b19b..23584f67e5 100644 --- a/src/timedata.h +++ b/src/timedata.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2016 The Bitcoin Core developers +// Copyright (c) 2014-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/torcontrol.cpp b/src/torcontrol.cpp index 46f39d65a0..c45b5dac0d 100644 --- a/src/torcontrol.cpp +++ b/src/torcontrol.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2016 The Bitcoin Core developers +// Copyright (c) 2015-2017 The Bitcoin Core developers // Copyright (c) 2017 The Zcash developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/torcontrol.h b/src/torcontrol.h index a01eeefeb8..20514f7bbf 100644 --- a/src/torcontrol.h +++ b/src/torcontrol.h @@ -1,4 +1,4 @@ -// Copyright (c) 2015 The Bitcoin Core developers +// Copyright (c) 2015-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/txdb.cpp b/src/txdb.cpp index 7a8e854b55..293d43c7b3 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/txdb.h b/src/txdb.h index 2e8095e3cd..3edeb4648e 100644 --- a/src/txdb.h +++ b/src/txdb.h @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/txmempool.cpp b/src/txmempool.cpp index 392323808f..d1edde284f 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -906,8 +906,8 @@ bool CCoinsViewMemPool::GetCoin(const COutPoint &outpoint, Coin &coin) const { size_t CTxMemPool::DynamicMemoryUsage() const { LOCK(cs); - // Estimate the overhead of mapTx to be 15 pointers + an allocation, as no exact formula for boost::multi_index_contained is implemented. - return memusage::MallocUsage(sizeof(CTxMemPoolEntry) + 15 * sizeof(void*)) * mapTx.size() + memusage::DynamicUsage(mapNextTx) + memusage::DynamicUsage(mapDeltas) + memusage::DynamicUsage(mapLinks) + memusage::DynamicUsage(vTxHashes) + cachedInnerUsage; + // Estimate the overhead of mapTx to be 12 pointers + an allocation, as no exact formula for boost::multi_index_contained is implemented. + return memusage::MallocUsage(sizeof(CTxMemPoolEntry) + 12 * sizeof(void*)) * mapTx.size() + memusage::DynamicUsage(mapNextTx) + memusage::DynamicUsage(mapDeltas) + memusage::DynamicUsage(mapLinks) + memusage::DynamicUsage(vTxHashes) + cachedInnerUsage; } void CTxMemPool::RemoveStaged(setEntries &stage, bool updateDescendants, MemPoolRemovalReason reason) { diff --git a/src/txmempool.h b/src/txmempool.h index 346585ab11..d6f8e7094b 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -204,20 +204,16 @@ struct mempoolentry_txid class CompareTxMemPoolEntryByDescendantScore { public: - bool operator()(const CTxMemPoolEntry& a, const CTxMemPoolEntry& b) + bool operator()(const CTxMemPoolEntry& a, const CTxMemPoolEntry& b) const { - bool fUseADescendants = UseDescendantScore(a); - bool fUseBDescendants = UseDescendantScore(b); + double a_mod_fee, a_size, b_mod_fee, b_size; - double aModFee = fUseADescendants ? a.GetModFeesWithDescendants() : a.GetModifiedFee(); - double aSize = fUseADescendants ? a.GetSizeWithDescendants() : a.GetTxSize(); - - double bModFee = fUseBDescendants ? b.GetModFeesWithDescendants() : b.GetModifiedFee(); - double bSize = fUseBDescendants ? b.GetSizeWithDescendants() : b.GetTxSize(); + GetModFeeAndSize(a, a_mod_fee, a_size); + GetModFeeAndSize(b, b_mod_fee, b_size); // Avoid division by rewriting (a/b > c/d) as (a*d > c*b). - double f1 = aModFee * bSize; - double f2 = aSize * bModFee; + double f1 = a_mod_fee * b_size; + double f2 = a_size * b_mod_fee; if (f1 == f2) { return a.GetTime() >= b.GetTime(); @@ -225,12 +221,21 @@ public: return f1 < f2; } - // Calculate which score to use for an entry (avoiding division). - bool UseDescendantScore(const CTxMemPoolEntry &a) + // Return the fee/size we're using for sorting this entry. + void GetModFeeAndSize(const CTxMemPoolEntry &a, double &mod_fee, double &size) const { + // Compare feerate with descendants to feerate of the transaction, and + // return the fee/size for the max. double f1 = (double)a.GetModifiedFee() * a.GetSizeWithDescendants(); double f2 = (double)a.GetModFeesWithDescendants() * a.GetTxSize(); - return f2 > f1; + + if (f2 > f1) { + mod_fee = a.GetModFeesWithDescendants(); + size = a.GetSizeWithDescendants(); + } else { + mod_fee = a.GetModifiedFee(); + size = a.GetTxSize(); + } } }; @@ -241,7 +246,7 @@ public: class CompareTxMemPoolEntryByScore { public: - bool operator()(const CTxMemPoolEntry& a, const CTxMemPoolEntry& b) + bool operator()(const CTxMemPoolEntry& a, const CTxMemPoolEntry& b) const { double f1 = (double)a.GetModifiedFee() * b.GetTxSize(); double f2 = (double)b.GetModifiedFee() * a.GetTxSize(); @@ -255,39 +260,59 @@ public: class CompareTxMemPoolEntryByEntryTime { public: - bool operator()(const CTxMemPoolEntry& a, const CTxMemPoolEntry& b) + bool operator()(const CTxMemPoolEntry& a, const CTxMemPoolEntry& b) const { return a.GetTime() < b.GetTime(); } }; +/** \class CompareTxMemPoolEntryByAncestorScore + * + * Sort an entry by min(score/size of entry's tx, score/size with all ancestors). + */ class CompareTxMemPoolEntryByAncestorFee { public: - bool operator()(const CTxMemPoolEntry& a, const CTxMemPoolEntry& b) + template<typename T> + bool operator()(const T& a, const T& b) const { - double aFees = a.GetModFeesWithAncestors(); - double aSize = a.GetSizeWithAncestors(); + double a_mod_fee, a_size, b_mod_fee, b_size; - double bFees = b.GetModFeesWithAncestors(); - double bSize = b.GetSizeWithAncestors(); + GetModFeeAndSize(a, a_mod_fee, a_size); + GetModFeeAndSize(b, b_mod_fee, b_size); // Avoid division by rewriting (a/b > c/d) as (a*d > c*b). - double f1 = aFees * bSize; - double f2 = aSize * bFees; + double f1 = a_mod_fee * b_size; + double f2 = a_size * b_mod_fee; if (f1 == f2) { return a.GetTx().GetHash() < b.GetTx().GetHash(); } - return f1 > f2; } + + // Return the fee/size we're using for sorting this entry. + template <typename T> + void GetModFeeAndSize(const T &a, double &mod_fee, double &size) const + { + // Compare feerate with ancestors to feerate of the transaction, and + // return the fee/size for the min. + double f1 = (double)a.GetModifiedFee() * a.GetSizeWithAncestors(); + double f2 = (double)a.GetModFeesWithAncestors() * a.GetTxSize(); + + if (f1 > f2) { + mod_fee = a.GetModFeesWithAncestors(); + size = a.GetSizeWithAncestors(); + } else { + mod_fee = a.GetModifiedFee(); + size = a.GetTxSize(); + } + } }; // Multi_index tag names struct descendant_score {}; struct entry_time {}; -struct mining_score {}; struct ancestor_score {}; class CBlockPolicyEstimator; @@ -356,7 +381,6 @@ public: * - transaction hash * - feerate [we use max(feerate of tx, feerate of tx with all descendants)] * - time in mempool - * - mining score (feerate modified by any fee deltas from PrioritiseTransaction) * * Note: the term "descendant" refers to in-mempool transactions that depend on * this one, while "ancestor" refers to in-mempool transactions that a given @@ -446,12 +470,6 @@ public: boost::multi_index::identity<CTxMemPoolEntry>, CompareTxMemPoolEntryByEntryTime >, - // sorted by score (for mining prioritization) - boost::multi_index::ordered_unique< - boost::multi_index::tag<mining_score>, - boost::multi_index::identity<CTxMemPoolEntry>, - CompareTxMemPoolEntryByScore - >, // sorted by fee rate with ancestors boost::multi_index::ordered_non_unique< boost::multi_index::tag<ancestor_score>, diff --git a/src/ui_interface.cpp b/src/ui_interface.cpp index c0f7defa46..72e04f488a 100644 --- a/src/ui_interface.cpp +++ b/src/ui_interface.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2010-2016 The Bitcoin Core developers +// Copyright (c) 2010-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/ui_interface.h b/src/ui_interface.h index 7f68c578ee..33099b4e73 100644 --- a/src/ui_interface.h +++ b/src/ui_interface.h @@ -1,5 +1,5 @@ // Copyright (c) 2010 Satoshi Nakamoto -// Copyright (c) 2012-2016 The Bitcoin Core developers +// Copyright (c) 2012-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/uint256.cpp b/src/uint256.cpp index b7255231c1..82c2e01576 100644 --- a/src/uint256.cpp +++ b/src/uint256.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/uint256.h b/src/uint256.h index e45c990dae..e090f10231 100644 --- a/src/uint256.h +++ b/src/uint256.h @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/undo.h b/src/undo.h index b482fd3089..1f10c6652c 100644 --- a/src/undo.h +++ b/src/undo.h @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/univalue/.travis.yml b/src/univalue/.travis.yml index 132743d349..43a1ed362e 100644 --- a/src/univalue/.travis.yml +++ b/src/univalue/.travis.yml @@ -25,7 +25,6 @@ addons: - pkg-config before_script: - - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew uninstall libtool; brew install libtool; fi - if [ -n "$USE_SHELL" ]; then export CONFIG_SHELL="$USE_SHELL"; fi - test -n "$USE_SHELL" && eval '"$USE_SHELL" -c "./autogen.sh"' || ./autogen.sh diff --git a/src/univalue/test/object.cpp b/src/univalue/test/object.cpp index 02446292a1..679cc9f143 100644 --- a/src/univalue/test/object.cpp +++ b/src/univalue/test/object.cpp @@ -19,9 +19,10 @@ #define BOOST_CHECK_THROW(stmt, excMatch) { \ try { \ (stmt); \ + assert(0 && "No exception caught"); \ } catch (excMatch & e) { \ } catch (...) { \ - assert(0); \ + assert(0 && "Wrong exception caught"); \ } \ } #define BOOST_CHECK_NO_THROW(stmt) { \ diff --git a/src/util.cpp b/src/util.cpp index b87dd091be..80eed24ffd 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -1,20 +1,14 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 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 defined(HAVE_CONFIG_H) -#include <config/bitcoin-config.h> -#endif - #include <util.h> #include <chainparamsbase.h> -#include <fs.h> #include <random.h> #include <serialize.h> #include <utilstrencodings.h> -#include <utiltime.h> #include <stdarg.h> @@ -78,6 +72,7 @@ #include <boost/algorithm/string/case_conv.hpp> // for to_lower() #include <boost/algorithm/string/predicate.hpp> // for startswith() and endswith() +#include <boost/interprocess/sync/file_lock.hpp> #include <boost/program_options/detail/config_file.hpp> #include <boost/thread.hpp> #include <openssl/crypto.h> @@ -89,6 +84,7 @@ const int64_t nStartupTime = GetTime(); const char * const BITCOIN_CONF_FILENAME = "bitcoin.conf"; const char * const BITCOIN_PID_FILENAME = "bitcoind.pid"; +const char * const DEFAULT_DEBUGLOGFILE = "debug.log"; ArgsManager gArgs; bool fPrintToConsole = false; @@ -189,26 +185,40 @@ static void DebugPrintInit() vMsgsBeforeOpenLog = new std::list<std::string>; } -void OpenDebugLog() +fs::path GetDebugLogPath() +{ + fs::path logfile(gArgs.GetArg("-debuglogfile", DEFAULT_DEBUGLOGFILE)); + if (logfile.is_absolute()) { + return logfile; + } else { + return GetDataDir() / logfile; + } +} + +bool OpenDebugLog() { boost::call_once(&DebugPrintInit, debugPrintInitFlag); boost::mutex::scoped_lock scoped_lock(*mutexDebugLog); assert(fileout == nullptr); assert(vMsgsBeforeOpenLog); - fs::path pathDebug = GetDataDir() / "debug.log"; + fs::path pathDebug = GetDebugLogPath(); + fileout = fsbridge::fopen(pathDebug, "a"); - if (fileout) { - setbuf(fileout, nullptr); // unbuffered - // dump buffered messages from before we opened the log - while (!vMsgsBeforeOpenLog->empty()) { - FileWriteStr(vMsgsBeforeOpenLog->front(), fileout); - vMsgsBeforeOpenLog->pop_front(); - } + if (!fileout) { + return false; + } + + setbuf(fileout, nullptr); // unbuffered + // dump buffered messages from before we opened the log + while (!vMsgsBeforeOpenLog->empty()) { + FileWriteStr(vMsgsBeforeOpenLog->front(), fileout); + vMsgsBeforeOpenLog->pop_front(); } delete vMsgsBeforeOpenLog; vMsgsBeforeOpenLog = nullptr; + return true; } struct CLogCategoryDesc @@ -220,6 +230,7 @@ struct CLogCategoryDesc const CLogCategoryDesc LogCategories[] = { {BCLog::NONE, "0"}, + {BCLog::NONE, "none"}, {BCLog::NET, "net"}, {BCLog::TOR, "tor"}, {BCLog::MEMPOOL, "mempool"}, @@ -354,7 +365,7 @@ int LogPrintStr(const std::string &str) // reopen the log file, if requested if (fReopenDebugLog) { fReopenDebugLog = false; - fs::path pathDebug = GetDataDir() / "debug.log"; + fs::path pathDebug = GetDebugLogPath(); if (fsbridge::freopen(pathDebug,"a",fileout) != nullptr) setbuf(fileout, nullptr); // unbuffered } @@ -365,6 +376,27 @@ int LogPrintStr(const std::string &str) return ret; } +bool LockDirectory(const fs::path& directory, const std::string lockfile_name, bool probe_only) +{ + fs::path pathLockFile = directory / lockfile_name; + FILE* file = fsbridge::fopen(pathLockFile, "a"); // empty lock file; created if it doesn't exist. + if (file) fclose(file); + + try { + static std::map<std::string, boost::interprocess::file_lock> locks; + boost::interprocess::file_lock& lock = locks.emplace(pathLockFile.string(), pathLockFile.string().c_str()).first->second; + if (!lock.try_lock()) { + return false; + } + if (probe_only) { + lock.unlock(); + } + } catch (const boost::interprocess::interprocess_exception& e) { + return error("Error while attempting to lock directory %s: %s", directory.string(), e.what()); + } + return true; +} + /** Interpret string as boolean, for argument parsing */ static bool InterpretBool(const std::string& strValue) { @@ -574,7 +606,10 @@ const fs::path &GetDataDir(bool fNetSpecific) if (fNetSpecific) path /= BaseParams().DataDir(); - fs::create_directories(path); + if (fs::create_directories(path)) { + // This is the first run, create wallets subdirectory too + fs::create_directories(path / "wallets"); + } return path; } @@ -620,6 +655,9 @@ void ArgsManager::ReadConfigFile(const std::string& confPath) } // If datadir is changed in .conf file: ClearDatadirCache(); + if (!fs::is_directory(GetDataDir(false))) { + throw std::runtime_error(strprintf("specified data directory \"%s\" does not exist.", gArgs.GetArg("-datadir", "").c_str())); + } } #ifndef WIN32 @@ -770,7 +808,7 @@ void ShrinkDebugFile() // Amount of debug.log to save at end when shrinking (must fit in memory) constexpr size_t RECENT_DEBUG_HISTORY_SIZE = 10 * 1000000; // Scroll debug.log if it's getting too big - fs::path pathLog = GetDataDir() / "debug.log"; + fs::path pathLog = GetDebugLogPath(); FILE* file = fsbridge::fopen(pathLog, "r"); // If debug.log file is more than 10% bigger the RECENT_DEBUG_HISTORY_SIZE // trim it down by saving only the last RECENT_DEBUG_HISTORY_SIZE bytes diff --git a/src/util.h b/src/util.h index be5c99567d..277b4c66af 100644 --- a/src/util.h +++ b/src/util.h @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -28,6 +28,7 @@ #include <vector> #include <boost/signals2/signal.hpp> +#include <boost/thread/condition_variable.hpp> // for boost::thread_interrupted // Application startup time (used for uptime calculation) int64_t GetStartupTime(); @@ -35,6 +36,7 @@ int64_t GetStartupTime(); static const bool DEFAULT_LOGTIMEMICROS = false; static const bool DEFAULT_LOGIPS = false; static const bool DEFAULT_LOGTIMESTAMPS = true; +extern const char * const DEFAULT_DEBUGLOGFILE; /** Signals for translation. */ class CTranslationInterface @@ -132,6 +134,10 @@ template<typename T, typename... Args> static inline void MarkUsed(const T& t, c MarkUsed(args...); } +// Be conservative when using LogPrintf/error or other things which +// unconditionally log to debug.log! It should not be the case that an inbound +// peer can fill up a users disk with debug.log entries. + #ifdef USE_COVERAGE #define LogPrintf(...) do { MarkUsed(__VA_ARGS__); } while(0) #define LogPrint(category, ...) do { MarkUsed(__VA_ARGS__); } while(0) @@ -167,6 +173,7 @@ bool TruncateFile(FILE *file, unsigned int length); int RaiseFileDescriptorLimit(int nMinFD); void AllocateFileRange(FILE *file, unsigned int offset, unsigned int length); bool RenameOver(fs::path src, fs::path dest); +bool LockDirectory(const fs::path& directory, const std::string lockfile_name, bool probe_only=false); bool TryCreateDirectories(const fs::path& p); fs::path GetDefaultDataDir(); const fs::path &GetDataDir(bool fNetSpecific = true); @@ -179,7 +186,8 @@ void CreatePidFile(const fs::path &path, pid_t pid); #ifdef WIN32 fs::path GetSpecialFolderPath(int nFolder, bool fCreate = true); #endif -void OpenDebugLog(); +fs::path GetDebugLogPath(); +bool OpenDebugLog(); void ShrinkDebugFile(); void runCommand(const std::string& strCommand); diff --git a/src/utilmoneystr.cpp b/src/utilmoneystr.cpp index 656d7c51b7..ea8a817ac4 100644 --- a/src/utilmoneystr.cpp +++ b/src/utilmoneystr.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2015 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/utilmoneystr.h b/src/utilmoneystr.h index b1a4499e90..1cbec49858 100644 --- a/src/utilmoneystr.h +++ b/src/utilmoneystr.h @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2015 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/utilstrencodings.cpp b/src/utilstrencodings.cpp index d90713ed6a..52158e9804 100644 --- a/src/utilstrencodings.cpp +++ b/src/utilstrencodings.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/utilstrencodings.h b/src/utilstrencodings.h index af33f0e5f8..994e6abbad 100644 --- a/src/utilstrencodings.h +++ b/src/utilstrencodings.h @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/utiltime.cpp b/src/utiltime.cpp index ca11cf341f..e908173135 100644 --- a/src/utiltime.cpp +++ b/src/utiltime.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/utiltime.h b/src/utiltime.h index 8ae8540b89..56cc31da67 100644 --- a/src/utiltime.h +++ b/src/utiltime.h @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2015 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/validation.cpp b/src/validation.cpp index 99ea1433f9..8cee0dfac3 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -15,7 +15,6 @@ #include <consensus/tx_verify.h> #include <consensus/validation.h> #include <cuckoocache.h> -#include <fs.h> #include <hash.h> #include <init.h> #include <policy/fees.h> @@ -39,10 +38,9 @@ #include <utilmoneystr.h> #include <utilstrencodings.h> #include <validationinterface.h> -#include <versionbits.h> #include <warnings.h> -#include <atomic> +#include <future> #include <sstream> #include <boost/algorithm/string/replace.hpp> @@ -59,48 +57,7 @@ /** * Global state */ - -CCriticalSection cs_main; - -BlockMap mapBlockIndex; -CChain chainActive; -CBlockIndex *pindexBestHeader = nullptr; -CWaitableCriticalSection csBestBlock; -CConditionVariable cvBlockChange; -int nScriptCheckThreads = 0; -std::atomic_bool fImporting(false); -std::atomic_bool fReindex(false); -bool fTxIndex = false; -bool fHavePruned = false; -bool fPruneMode = false; -bool fIsBareMultisigStd = DEFAULT_PERMIT_BAREMULTISIG; -bool fRequireStandard = true; -bool fCheckBlockIndex = false; -bool fCheckpointsEnabled = DEFAULT_CHECKPOINTS_ENABLED; -size_t nCoinCacheUsage = 5000 * 300; -uint64_t nPruneTarget = 0; -int64_t nMaxTipAge = DEFAULT_MAX_TIP_AGE; -bool fEnableReplacement = DEFAULT_ENABLE_REPLACEMENT; - -uint256 hashAssumeValid; -arith_uint256 nMinimumChainWork; - -CFeeRate minRelayTxFee = CFeeRate(DEFAULT_MIN_RELAY_TX_FEE); -CAmount maxTxFee = DEFAULT_TRANSACTION_MAXFEE; - -CBlockPolicyEstimator feeEstimator; -CTxMemPool mempool(&feeEstimator); - -static void CheckBlockIndex(const Consensus::Params& consensusParams); - -/** Constant stuff for coinbase transactions we create: */ -CScript COINBASE_FLAGS; - -const std::string strMessageMagic = "Bitcoin Signed Message:\n"; - -// Internal stuff namespace { - struct CBlockIndexWorkComparator { bool operator()(const CBlockIndex *pa, const CBlockIndex *pb) const { @@ -121,28 +78,39 @@ namespace { return false; } }; +} // anon namespace - CBlockIndex *pindexBestInvalid; +enum DisconnectResult +{ + DISCONNECT_OK, // All good. + DISCONNECT_UNCLEAN, // Rolled back, but UTXO set was inconsistent with block. + DISCONNECT_FAILED // Something else went wrong. +}; +class ConnectTrace; + +/** + * CChainState stores and provides an API to update our local knowledge of the + * current best chain and header tree. + * + * It generally provides access to the current block tree, as well as functions + * to provide new data, which it will appropriately validate and incorporate in + * its state as necessary. + * + * Eventually, the API here is targeted at being exposed externally as a + * consumable libconsensus library, so any functions added must only call + * other class member functions, pure functions in other parts of the consensus + * library, callbacks via the validation interface, or read/write-to-disk + * functions (eventually this will also be via callbacks). + */ +class CChainState { +private: /** * The set of all CBlockIndex entries with BLOCK_VALID_TRANSACTIONS (for itself and all ancestors) and * as good as our current tip or better. Entries may be failed, though, and pruning nodes may be * missing the data for the block. */ std::set<CBlockIndex*, CBlockIndexWorkComparator> setBlockIndexCandidates; - /** All pairs A->B, where A (or one of its ancestors) misses transactions, but B has transactions. - * Pruned nodes may have entries where B is missing data. - */ - std::multimap<CBlockIndex*, CBlockIndex*> mapBlocksUnlinked; - - CCriticalSection cs_LastBlockFile; - std::vector<CBlockFileInfo> vinfoBlockFile; - int nLastBlockFile = 0; - /** Global flag to indicate we should check to see if there are - * block/undo files that should be deleted. Set on startup - * or if we allocate more file space when we're in prune mode - */ - bool fCheckForPruning = false; /** * Every received block is assigned a unique and increasing identifier, so we @@ -176,6 +144,113 @@ namespace { */ std::set<CBlockIndex*> g_failed_blocks; +public: + CChain chainActive; + BlockMap mapBlockIndex; + std::multimap<CBlockIndex*, CBlockIndex*> mapBlocksUnlinked; + CBlockIndex *pindexBestInvalid = nullptr; + + bool LoadBlockIndex(const Consensus::Params& consensus_params, CBlockTreeDB& blocktree); + + bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams, std::shared_ptr<const CBlock> pblock); + + bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex); + bool AcceptBlock(const std::shared_ptr<const CBlock>& pblock, CValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex, bool fRequested, const CDiskBlockPos* dbp, bool* fNewBlock); + + // Block (dis)connection on a given view: + DisconnectResult DisconnectBlock(const CBlock& block, const CBlockIndex* pindex, CCoinsViewCache& view); + bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, + CCoinsViewCache& view, const CChainParams& chainparams, bool fJustCheck = false); + + // Block disconnection on our pcoinsTip: + bool DisconnectTip(CValidationState& state, const CChainParams& chainparams, DisconnectedBlockTransactions *disconnectpool); + + // Manual block validity manipulation: + bool PreciousBlock(CValidationState& state, const CChainParams& params, CBlockIndex *pindex); + bool InvalidateBlock(CValidationState& state, const CChainParams& chainparams, CBlockIndex *pindex); + bool ResetBlockFailureFlags(CBlockIndex *pindex); + + bool ReplayBlocks(const CChainParams& params, CCoinsView* view); + bool RewindBlockIndex(const CChainParams& params); + bool LoadGenesisBlock(const CChainParams& chainparams); + + void PruneBlockIndexCandidates(); + + void UnloadBlockIndex(); + +private: + bool ActivateBestChainStep(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexMostWork, const std::shared_ptr<const CBlock>& pblock, bool& fInvalidFound, ConnectTrace& connectTrace); + bool ConnectTip(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexNew, const std::shared_ptr<const CBlock>& pblock, ConnectTrace& connectTrace, DisconnectedBlockTransactions &disconnectpool); + + CBlockIndex* AddToBlockIndex(const CBlockHeader& block); + /** Create a new block index entry for a given block hash */ + CBlockIndex * InsertBlockIndex(const uint256& hash); + void CheckBlockIndex(const Consensus::Params& consensusParams); + + void InvalidBlockFound(CBlockIndex *pindex, const CValidationState &state); + CBlockIndex* FindMostWorkChain(); + bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBlockIndex *pindexNew, const CDiskBlockPos& pos, const Consensus::Params& consensusParams); + + + bool RollforwardBlock(const CBlockIndex* pindex, CCoinsViewCache& inputs, const CChainParams& params); +} g_chainstate; + + + +CCriticalSection cs_main; + +BlockMap& mapBlockIndex = g_chainstate.mapBlockIndex; +CChain& chainActive = g_chainstate.chainActive; +CBlockIndex *pindexBestHeader = nullptr; +CWaitableCriticalSection csBestBlock; +CConditionVariable cvBlockChange; +int nScriptCheckThreads = 0; +std::atomic_bool fImporting(false); +std::atomic_bool fReindex(false); +bool fTxIndex = false; +bool fHavePruned = false; +bool fPruneMode = false; +bool fIsBareMultisigStd = DEFAULT_PERMIT_BAREMULTISIG; +bool fRequireStandard = true; +bool fCheckBlockIndex = false; +bool fCheckpointsEnabled = DEFAULT_CHECKPOINTS_ENABLED; +size_t nCoinCacheUsage = 5000 * 300; +uint64_t nPruneTarget = 0; +int64_t nMaxTipAge = DEFAULT_MAX_TIP_AGE; +bool fEnableReplacement = DEFAULT_ENABLE_REPLACEMENT; + +uint256 hashAssumeValid; +arith_uint256 nMinimumChainWork; + +CFeeRate minRelayTxFee = CFeeRate(DEFAULT_MIN_RELAY_TX_FEE); +CAmount maxTxFee = DEFAULT_TRANSACTION_MAXFEE; + +CBlockPolicyEstimator feeEstimator; +CTxMemPool mempool(&feeEstimator); + +/** Constant stuff for coinbase transactions we create: */ +CScript COINBASE_FLAGS; + +const std::string strMessageMagic = "Bitcoin Signed Message:\n"; + +// Internal stuff +namespace { + CBlockIndex *&pindexBestInvalid = g_chainstate.pindexBestInvalid; + + /** All pairs A->B, where A (or one of its ancestors) misses transactions, but B has transactions. + * Pruned nodes may have entries where B is missing data. + */ + std::multimap<CBlockIndex*, CBlockIndex*>& mapBlocksUnlinked = g_chainstate.mapBlocksUnlinked; + + CCriticalSection cs_LastBlockFile; + std::vector<CBlockFileInfo> vinfoBlockFile; + int nLastBlockFile = 0; + /** Global flag to indicate we should check to see if there are + * block/undo files that should be deleted. Set on startup + * or if we allocate more file space when we're in prune mode + */ + bool fCheckForPruning = false; + /** Dirty block index entries. */ std::set<CBlockIndex*> setDirtyBlockIndex; @@ -926,47 +1001,51 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa return AcceptToMemoryPoolWithTime(chainparams, pool, state, tx, pfMissingInputs, GetTime(), plTxnReplaced, bypass_limits, nAbsurdFee); } -/** Return transaction in txOut, and if it was found inside a block, its hash is placed in hashBlock */ -bool GetTransaction(const uint256 &hash, CTransactionRef &txOut, const Consensus::Params& consensusParams, uint256 &hashBlock, bool fAllowSlow) +/** + * Return transaction in txOut, and if it was found inside a block, its hash is placed in hashBlock. + * If blockIndex is provided, the transaction is fetched from the corresponding block. + */ +bool GetTransaction(const uint256& hash, CTransactionRef& txOut, const Consensus::Params& consensusParams, uint256& hashBlock, bool fAllowSlow, CBlockIndex* blockIndex) { - CBlockIndex *pindexSlow = nullptr; + CBlockIndex* pindexSlow = blockIndex; LOCK(cs_main); - CTransactionRef ptx = mempool.get(hash); - if (ptx) - { - txOut = ptx; - return true; - } - - if (fTxIndex) { - CDiskTxPos postx; - if (pblocktree->ReadTxIndex(hash, postx)) { - CAutoFile file(OpenBlockFile(postx, true), SER_DISK, CLIENT_VERSION); - if (file.IsNull()) - return error("%s: OpenBlockFile failed", __func__); - CBlockHeader header; - try { - file >> header; - fseek(file.Get(), postx.nTxOffset, SEEK_CUR); - file >> txOut; - } catch (const std::exception& e) { - return error("%s: Deserialize or I/O error - %s", __func__, e.what()); - } - hashBlock = header.GetHash(); - if (txOut->GetHash() != hash) - return error("%s: txid mismatch", __func__); + if (!blockIndex) { + CTransactionRef ptx = mempool.get(hash); + if (ptx) { + txOut = ptx; return true; } - // transaction not found in index, nothing more can be done - return false; - } + if (fTxIndex) { + CDiskTxPos postx; + if (pblocktree->ReadTxIndex(hash, postx)) { + CAutoFile file(OpenBlockFile(postx, true), SER_DISK, CLIENT_VERSION); + if (file.IsNull()) + return error("%s: OpenBlockFile failed", __func__); + CBlockHeader header; + try { + file >> header; + fseek(file.Get(), postx.nTxOffset, SEEK_CUR); + file >> txOut; + } catch (const std::exception& e) { + return error("%s: Deserialize or I/O error - %s", __func__, e.what()); + } + hashBlock = header.GetHash(); + if (txOut->GetHash() != hash) + return error("%s: txid mismatch", __func__); + return true; + } + + // transaction not found in index, nothing more can be done + return false; + } - if (fAllowSlow) { // use coin database to locate block that contains transaction, and scan it - const Coin& coin = AccessByTxid(*pcoinsTip, hash); - if (!coin.IsSpent()) pindexSlow = chainActive[coin.nHeight]; + if (fAllowSlow) { // use coin database to locate block that contains transaction, and scan it + const Coin& coin = AccessByTxid(*pcoinsTip, hash); + if (!coin.IsSpent()) pindexSlow = chainActive[coin.nHeight]; + } } if (pindexSlow) { @@ -1042,7 +1121,13 @@ bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos, const Consensus: bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex, const Consensus::Params& consensusParams) { - if (!ReadBlockFromDisk(block, pindex->GetBlockPos(), consensusParams)) + CDiskBlockPos blockPos; + { + LOCK(cs_main); + blockPos = pindex->GetBlockPos(); + } + + if (!ReadBlockFromDisk(block, blockPos, consensusParams)) return false; if (block.GetHash() != pindex->GetBlockHash()) return error("ReadBlockFromDisk(CBlock&, CBlockIndex*): GetHash() doesn't match index for %s at %s", @@ -1197,7 +1282,7 @@ void static InvalidChainFound(CBlockIndex* pindexNew) CheckForkWarningConditions(); } -void static InvalidBlockFound(CBlockIndex *pindex, const CValidationState &state) { +void CChainState::InvalidBlockFound(CBlockIndex *pindex, const CValidationState &state) { if (!state.CorruptionPossible()) { pindex->nStatus |= BLOCK_FAILED_VALID; g_failed_blocks.insert(pindex); @@ -1380,8 +1465,13 @@ bool UndoWriteToDisk(const CBlockUndo& blockundo, CDiskBlockPos& pos, const uint return true; } -bool UndoReadFromDisk(CBlockUndo& blockundo, const CDiskBlockPos& pos, const uint256& hashBlock) +static bool UndoReadFromDisk(CBlockUndo& blockundo, const CBlockIndex *pindex) { + CDiskBlockPos pos = pindex->GetUndoPos(); + if (pos.IsNull()) { + return error("%s: no undo data available", __func__); + } + // Open history file to read CAutoFile filein(OpenUndoFile(pos, true), SER_DISK, CLIENT_VERSION); if (filein.IsNull()) @@ -1391,7 +1481,7 @@ bool UndoReadFromDisk(CBlockUndo& blockundo, const CDiskBlockPos& pos, const uin uint256 hashChecksum; CHashVerifier<CAutoFile> verifier(&filein); // We need a CHashVerifier as reserializing may lose data try { - verifier << hashBlock; + verifier << pindex->pprev->GetBlockHash(); verifier >> blockundo; filein >> hashChecksum; } @@ -1426,13 +1516,6 @@ bool AbortNode(CValidationState& state, const std::string& strMessage, const std } // namespace -enum DisconnectResult -{ - DISCONNECT_OK, // All good. - DISCONNECT_UNCLEAN, // Rolled back, but UTXO set was inconsistent with block. - DISCONNECT_FAILED // Something else went wrong. -}; - /** * Restore the UTXO in a Coin at a given COutPoint * @param undo The Coin to be restored. @@ -1469,17 +1552,12 @@ int ApplyTxInUndo(Coin&& undo, CCoinsViewCache& view, const COutPoint& out) /** Undo the effects of this block (with given index) on the UTXO set represented by coins. * When FAILED is returned, view is left in an indeterminate state. */ -static DisconnectResult DisconnectBlock(const CBlock& block, const CBlockIndex* pindex, CCoinsViewCache& view) +DisconnectResult CChainState::DisconnectBlock(const CBlock& block, const CBlockIndex* pindex, CCoinsViewCache& view) { bool fClean = true; CBlockUndo blockUndo; - CDiskBlockPos pos = pindex->GetUndoPos(); - if (pos.IsNull()) { - error("DisconnectBlock(): no undo data available"); - return DISCONNECT_FAILED; - } - if (!UndoReadFromDisk(blockUndo, pos, pindex->pprev->GetBlockHash())) { + if (!UndoReadFromDisk(blockUndo, pindex)) { error("DisconnectBlock(): failure reading undo data"); return DISCONNECT_FAILED; } @@ -1556,6 +1634,45 @@ void static FlushBlockFile(bool fFinalize = false) static bool FindUndoPos(CValidationState &state, int nFile, CDiskBlockPos &pos, unsigned int nAddSize); +static bool WriteUndoDataForBlock(const CBlockUndo& blockundo, CValidationState& state, CBlockIndex* pindex, const CChainParams& chainparams) +{ + // Write undo information to disk + if (pindex->GetUndoPos().IsNull()) { + 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())) + return AbortNode(state, "Failed to write undo data"); + + // update nUndoPos in block index + pindex->nUndoPos = _pos.nPos; + pindex->nStatus |= BLOCK_HAVE_UNDO; + setDirtyBlockIndex.insert(pindex); + } + + return true; +} + +static bool WriteTxIndexDataForBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex) +{ + if (!fTxIndex) return true; + + CDiskTxPos pos(pindex->GetBlockPos(), GetSizeOfCompactSize(block.vtx.size())); + std::vector<std::pair<uint256, CDiskTxPos> > vPos; + vPos.reserve(block.vtx.size()); + for (const CTransactionRef& tx : block.vtx) + { + vPos.push_back(std::make_pair(tx->GetHash(), pos)); + pos.nTxOffset += ::GetSerializeSize(*tx, SER_DISK, CLIENT_VERSION); + } + + if (!pblocktree->WriteTxIndex(vPos)) { + return AbortNode(state, "Failed to write transaction index"); + } + + return true; +} + static CCheckQueue<CScriptCheck> scriptcheckqueue(128); void ThreadScriptCheck() { @@ -1656,8 +1773,8 @@ static int64_t nBlocksTotal = 0; /** Apply the effects of this block (with given index) on the UTXO set represented by coins. * Validity checks that depend on the UTXO set are also done; ConnectBlock() * can fail if those validity checks fail (among other reasons). */ -static bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, - CCoinsViewCache& view, const CChainParams& chainparams, bool fJustCheck = false) +bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, + CCoinsViewCache& view, const CChainParams& chainparams, bool fJustCheck) { AssertLockHeld(cs_main); assert(pindex); @@ -1667,6 +1784,18 @@ static bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockInd int64_t nTimeStart = GetTimeMicros(); // Check it again in case a previous version let a bad block in + // NOTE: We don't currently (re-)invoke ContextualCheckBlock() or + // ContextualCheckBlockHeader() here. This means that if we add a new + // consensus rule that is enforced in one of those two functions, then we + // may have let in a block that violates the rule prior to updating the + // software, and we would NOT be enforcing the rule here. Fully solving + // upgrade from one software version to the next after a consensus rule + // change is potentially tricky and issue-specific (see RewindBlockIndex() + // for one general approach that was used for BIP 141 deployment). + // Also, currently the rule against blocks more than 2 hours in the future + // is enforced in ContextualCheckBlockHeader(); we wouldn't want to + // re-enforce that rule here (at least until we make it impossible for + // GetAdjustedTime() to go backward). if (!CheckBlock(block, state, chainparams.GetConsensus(), !fJustCheck, !fJustCheck)) return error("%s: Consensus::CheckBlock: %s", __func__, FormatStateMessage(state)); @@ -1771,9 +1900,6 @@ static bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockInd CAmount nFees = 0; int nInputs = 0; int64_t nSigOpsCost = 0; - CDiskTxPos pos(pindex->GetBlockPos(), GetSizeOfCompactSize(block.vtx.size())); - std::vector<std::pair<uint256, CDiskTxPos> > vPos; - vPos.reserve(block.vtx.size()); blockundo.vtxundo.reserve(block.vtx.size() - 1); std::vector<PrecomputedTransactionData> txdata; txdata.reserve(block.vtx.size()); // Required so that pointers to individual PrecomputedTransactionData don't get invalidated @@ -1834,9 +1960,6 @@ static bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockInd blockundo.vtxundo.push_back(CTxUndo()); } UpdateCoins(tx, view, i == 0 ? undoDummy : blockundo.vtxundo.back(), pindex->nHeight); - - vPos.push_back(std::make_pair(tx.GetHash(), pos)); - pos.nTxOffset += ::GetSerializeSize(tx, SER_DISK, CLIENT_VERSION); } int64_t nTime3 = GetTimeMicros(); nTimeConnect += nTime3 - nTime2; LogPrint(BCLog::BENCH, " - Connect %u transactions: %.2fms (%.3fms/tx, %.3fms/txin) [%.2fs (%.2fms/blk)]\n", (unsigned)block.vtx.size(), MILLI * (nTime3 - nTime2), MILLI * (nTime3 - nTime2) / block.vtx.size(), nInputs <= 1 ? 0 : MILLI * (nTime3 - nTime2) / (nInputs-1), nTimeConnect * MICRO, nTimeConnect * MILLI / nBlocksTotal); @@ -1856,28 +1979,16 @@ static bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockInd if (fJustCheck) return true; - // Write undo information to disk - 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)) - return error("ConnectBlock(): FindUndoPos failed"); - 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->nStatus |= BLOCK_HAVE_UNDO; - } + if (!WriteUndoDataForBlock(blockundo, state, pindex, chainparams)) + return false; + if (!pindex->IsValid(BLOCK_VALID_SCRIPTS)) { pindex->RaiseValidity(BLOCK_VALID_SCRIPTS); setDirtyBlockIndex.insert(pindex); } - if (fTxIndex) - if (!pblocktree->WriteTxIndex(vPos)) - return AbortNode(state, "Failed to write transaction index"); + if (!WriteTxIndexDataForBlock(block, state, pindex)) + return false; assert(pindex->phashBlock); // add this block to the view's block chain @@ -2029,10 +2140,8 @@ static void DoWarning(const std::string& strWarning) } } -/** Update chainActive and related internal data structures. */ -void static UpdateTip(CBlockIndex *pindexNew, const CChainParams& chainParams) { - chainActive.SetTip(pindexNew); - +/** Check warning conditions and do some notifications on new chain tip set. */ +void static UpdateTip(const CBlockIndex *pindexNew, const CChainParams& chainParams) { // New best block mempool.AddTransactionsUpdated(1); @@ -2042,7 +2151,7 @@ void static UpdateTip(CBlockIndex *pindexNew, const CChainParams& chainParams) { if (!IsInitialBlockDownload()) { int nUpgraded = 0; - const CBlockIndex* pindex = chainActive.Tip(); + const CBlockIndex* pindex = pindexNew; for (int bit = 0; bit < VERSIONBITS_NUM_BITS; bit++) { WarningBitsConditionChecker checker(bit); ThresholdState state = checker.GetStateFor(pindex, chainParams.GetConsensus(), warningcache[bit]); @@ -2073,10 +2182,10 @@ void static UpdateTip(CBlockIndex *pindexNew, const CChainParams& chainParams) { } } LogPrintf("%s: new best=%s height=%d version=0x%08x log2_work=%.8g tx=%lu date='%s' progress=%f cache=%.1fMiB(%utxo)", __func__, - chainActive.Tip()->GetBlockHash().ToString(), chainActive.Height(), chainActive.Tip()->nVersion, - log(chainActive.Tip()->nChainWork.getdouble())/log(2.0), (unsigned long)chainActive.Tip()->nChainTx, - DateTimeStrFormat("%Y-%m-%d %H:%M:%S", chainActive.Tip()->GetBlockTime()), - GuessVerificationProgress(chainParams.TxData(), chainActive.Tip()), pcoinsTip->DynamicMemoryUsage() * (1.0 / (1<<20)), pcoinsTip->GetCacheSize()); + pindexNew->GetBlockHash().ToString(), pindexNew->nHeight, pindexNew->nVersion, + log(pindexNew->nChainWork.getdouble())/log(2.0), (unsigned long)pindexNew->nChainTx, + DateTimeStrFormat("%Y-%m-%d %H:%M:%S", pindexNew->GetBlockTime()), + GuessVerificationProgress(chainParams.TxData(), pindexNew), pcoinsTip->DynamicMemoryUsage() * (1.0 / (1<<20)), pcoinsTip->GetCacheSize()); if (!warningMessages.empty()) LogPrintf(" warning='%s'", boost::algorithm::join(warningMessages, ", ")); LogPrintf("\n"); @@ -2093,7 +2202,7 @@ void static UpdateTip(CBlockIndex *pindexNew, const CChainParams& chainParams) { * disconnectpool (note that the caller is responsible for mempool consistency * in any case). */ -bool static DisconnectTip(CValidationState& state, const CChainParams& chainparams, DisconnectedBlockTransactions *disconnectpool) +bool CChainState::DisconnectTip(CValidationState& state, const CChainParams& chainparams, DisconnectedBlockTransactions *disconnectpool) { CBlockIndex *pindexDelete = chainActive.Tip(); assert(pindexDelete); @@ -2130,7 +2239,8 @@ bool static DisconnectTip(CValidationState& state, const CChainParams& chainpara } } - // Update chainActive and related variables. + chainActive.SetTip(pindexDelete->pprev); + UpdateTip(pindexDelete->pprev, chainparams); // Let wallets know transactions went from 1-confirmed to // 0-confirmed or conflicted: @@ -2215,7 +2325,7 @@ public: * * The block is added to connectTrace if connection succeeds. */ -bool static ConnectTip(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexNew, const std::shared_ptr<const CBlock>& pblock, ConnectTrace& connectTrace, DisconnectedBlockTransactions &disconnectpool) +bool CChainState::ConnectTip(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexNew, const std::shared_ptr<const CBlock>& pblock, ConnectTrace& connectTrace, DisconnectedBlockTransactions &disconnectpool) { assert(pindexNew->pprev == chainActive.Tip()); // Read block from disk. @@ -2259,6 +2369,7 @@ bool static ConnectTip(CValidationState& state, const CChainParams& chainparams, mempool.removeForBlock(blockConnecting.vtx, pindexNew->nHeight); disconnectpool.removeForBlock(blockConnecting.vtx); // Update chainActive & related variables. + chainActive.SetTip(pindexNew); UpdateTip(pindexNew, chainparams); int64_t nTime6 = GetTimeMicros(); nTimePostConnect += nTime6 - nTime5; nTimeTotal += nTime6 - nTime1; @@ -2273,7 +2384,7 @@ bool static ConnectTip(CValidationState& state, const CChainParams& chainparams, * Return the tip of the chain with the most work in it, that isn't * known to be invalid (it's however far from certain to be valid). */ -static CBlockIndex* FindMostWorkChain() { +CBlockIndex* CChainState::FindMostWorkChain() { do { CBlockIndex *pindexNew = nullptr; @@ -2328,7 +2439,7 @@ static CBlockIndex* FindMostWorkChain() { } /** Delete all entries in setBlockIndexCandidates that are worse than the current tip. */ -static void PruneBlockIndexCandidates() { +void CChainState::PruneBlockIndexCandidates() { // Note that we can't delete the current block itself, as we may need to return to it later in case a // reorganization to a better block fails. std::set<CBlockIndex*, CBlockIndexWorkComparator>::iterator it = setBlockIndexCandidates.begin(); @@ -2343,7 +2454,7 @@ static void PruneBlockIndexCandidates() { * Try to make some progress towards making pindexMostWork the active block. * pblock is either nullptr or a pointer to a CBlock corresponding to pindexMostWork. */ -static bool ActivateBestChainStep(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexMostWork, const std::shared_ptr<const CBlock>& pblock, bool& fInvalidFound, ConnectTrace& connectTrace) +bool CChainState::ActivateBestChainStep(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexMostWork, const std::shared_ptr<const CBlock>& pblock, bool& fInvalidFound, ConnectTrace& connectTrace) { AssertLockHeld(cs_main); const CBlockIndex *pindexOldTip = chainActive.Tip(); @@ -2450,17 +2561,26 @@ static void NotifyHeaderTip() { * or an activated best chain. pblock is either nullptr or a pointer to a block * that is already loaded (to avoid loading it again from disk). */ -bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams, std::shared_ptr<const CBlock> pblock) { +bool CChainState::ActivateBestChain(CValidationState &state, const CChainParams& chainparams, std::shared_ptr<const CBlock> pblock) { // Note that while we're often called here from ProcessNewBlock, this is // far from a guarantee. Things in the P2P/RPC will often end up calling // us in the middle of ProcessNewBlock - do not assume pblock is set // sanely for performance or correctness! + AssertLockNotHeld(cs_main); CBlockIndex *pindexMostWork = nullptr; CBlockIndex *pindexNewTip = nullptr; int nStopAtHeight = gArgs.GetArg("-stopatheight", DEFAULT_STOPATHEIGHT); do { boost::this_thread::interruption_point(); + + if (GetMainSignals().CallbacksPending() > 10) { + // Block until the validation queue drains. This should largely + // never happen in normal operation, however may happen during + // reindex, causing memory blowup if we run too far ahead. + SyncWithValidationInterfaceQueue(); + } + if (ShutdownRequested()) break; @@ -2520,9 +2640,11 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams, return true; } +bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams, std::shared_ptr<const CBlock> pblock) { + return g_chainstate.ActivateBestChain(state, chainparams, std::move(pblock)); +} - -bool PreciousBlock(CValidationState& state, const CChainParams& params, CBlockIndex *pindex) +bool CChainState::PreciousBlock(CValidationState& state, const CChainParams& params, CBlockIndex *pindex) { { LOCK(cs_main); @@ -2548,10 +2670,13 @@ bool PreciousBlock(CValidationState& state, const CChainParams& params, CBlockIn } } - return ActivateBestChain(state, params); + return ActivateBestChain(state, params, std::shared_ptr<const CBlock>()); +} +bool PreciousBlock(CValidationState& state, const CChainParams& params, CBlockIndex *pindex) { + return g_chainstate.PreciousBlock(state, params, pindex); } -bool InvalidateBlock(CValidationState& state, const CChainParams& chainparams, CBlockIndex *pindex) +bool CChainState::InvalidateBlock(CValidationState& state, const CChainParams& chainparams, CBlockIndex *pindex) { AssertLockHeld(cs_main); @@ -2610,8 +2735,11 @@ bool InvalidateBlock(CValidationState& state, const CChainParams& chainparams, C uiInterface.NotifyBlockTip(IsInitialBlockDownload(), pindex->pprev); return true; } +bool InvalidateBlock(CValidationState& state, const CChainParams& chainparams, CBlockIndex *pindex) { + return g_chainstate.InvalidateBlock(state, chainparams, pindex); +} -bool ResetBlockFailureFlags(CBlockIndex *pindex) { +bool CChainState::ResetBlockFailureFlags(CBlockIndex *pindex) { AssertLockHeld(cs_main); int nHeight = pindex->nHeight; @@ -2644,8 +2772,11 @@ bool ResetBlockFailureFlags(CBlockIndex *pindex) { } return true; } +bool ResetBlockFailureFlags(CBlockIndex *pindex) { + return g_chainstate.ResetBlockFailureFlags(pindex); +} -static CBlockIndex* AddToBlockIndex(const CBlockHeader& block) +CBlockIndex* CChainState::AddToBlockIndex(const CBlockHeader& block) { // Check for duplicate uint256 hash = block.GetHash(); @@ -2680,7 +2811,7 @@ static CBlockIndex* AddToBlockIndex(const CBlockHeader& block) } /** Mark a block as having its data received and checked (up to BLOCK_VALID_TRANSACTIONS). */ -static bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBlockIndex *pindexNew, const CDiskBlockPos& pos, const Consensus::Params& consensusParams) +bool CChainState::ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBlockIndex *pindexNew, const CDiskBlockPos& pos, const Consensus::Params& consensusParams) { pindexNew->nTx = block.vtx.size(); pindexNew->nChainTx = 0; @@ -2728,7 +2859,7 @@ static bool ReceivedBlockTransactions(const CBlock &block, CValidationState& sta return true; } -static bool FindBlockPos(CValidationState &state, CDiskBlockPos &pos, unsigned int nAddSize, unsigned int nHeight, uint64_t nTime, bool fKnown = false) +static bool FindBlockPos(CDiskBlockPos &pos, unsigned int nAddSize, unsigned int nHeight, uint64_t nTime, bool fKnown = false) { LOCK(cs_LastBlockFile); @@ -2777,7 +2908,7 @@ static bool FindBlockPos(CValidationState &state, CDiskBlockPos &pos, unsigned i } } else - return state.Error("out of disk space"); + return error("out of disk space"); } } @@ -2952,7 +3083,13 @@ std::vector<unsigned char> GenerateCoinbaseCommitment(CBlock& block, const CBloc /** Context-dependent validity checks. * By "context", we mean only the previous block headers, but not the UTXO - * set; UTXO-related validity checks are done in ConnectBlock(). */ + * set; UTXO-related validity checks are done in ConnectBlock(). + * NOTE: This function is not currently invoked by ConnectBlock(), so we + * should consider upgrade issues if we change which consensus rules are + * enforced in this function (eg by adding a new consensus rule). See comment + * in ConnectBlock(). + * Note that -reindex-chainstate skips the validation that happens here! + */ static bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state, const CChainParams& params, const CBlockIndex* pindexPrev, int64_t nAdjustedTime) { assert(pindexPrev != nullptr); @@ -2992,6 +3129,12 @@ static bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationSta return true; } +/** NOTE: This function is not currently invoked by ConnectBlock(), so we + * should consider upgrade issues if we change which consensus rules are + * enforced in this function (eg by adding a new consensus rule). See comment + * in ConnectBlock(). + * Note that -reindex-chainstate skips the validation that happens here! + */ static bool ContextualCheckBlock(const CBlock& block, CValidationState& state, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev) { const int nHeight = pindexPrev == nullptr ? 0 : pindexPrev->nHeight + 1; @@ -3073,7 +3216,7 @@ static bool ContextualCheckBlock(const CBlock& block, CValidationState& state, c return true; } -static bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex) +bool CChainState::AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex) { AssertLockHeld(cs_main); // Check for duplicate @@ -3140,7 +3283,7 @@ bool ProcessNewBlockHeaders(const std::vector<CBlockHeader>& headers, CValidatio LOCK(cs_main); for (const CBlockHeader& header : headers) { CBlockIndex *pindex = nullptr; // Use a temp pindex instead of ppindex to avoid a const_cast - if (!AcceptBlockHeader(header, state, chainparams, &pindex)) { + if (!g_chainstate.AcceptBlockHeader(header, state, chainparams, &pindex)) { if (first_invalid) *first_invalid = header; return false; } @@ -3154,7 +3297,26 @@ bool ProcessNewBlockHeaders(const std::vector<CBlockHeader>& headers, CValidatio } /** Store block on disk. If dbp is non-nullptr, the file is known to already reside on disk */ -static bool AcceptBlock(const std::shared_ptr<const CBlock>& pblock, CValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex, bool fRequested, const CDiskBlockPos* dbp, bool* fNewBlock) +static CDiskBlockPos SaveBlockToDisk(const CBlock& block, int nHeight, const CChainParams& chainparams, const CDiskBlockPos* dbp) { + unsigned int nBlockSize = ::GetSerializeSize(block, SER_DISK, CLIENT_VERSION); + CDiskBlockPos blockPos; + if (dbp != nullptr) + blockPos = *dbp; + if (!FindBlockPos(blockPos, nBlockSize+8, nHeight, block.GetBlockTime(), dbp != nullptr)) { + error("%s: FindBlockPos failed", __func__); + return CDiskBlockPos(); + } + if (dbp == nullptr) { + if (!WriteBlockToDisk(block, blockPos, chainparams.MessageStart())) { + AbortNode("Failed to write block"); + return CDiskBlockPos(); + } + } + return blockPos; +} + +/** Store block on disk. If dbp is non-nullptr, the file is known to already reside on disk */ +bool CChainState::AcceptBlock(const std::shared_ptr<const CBlock>& pblock, CValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex, bool fRequested, const CDiskBlockPos* dbp, bool* fNewBlock) { const CBlock& block = *pblock; @@ -3214,19 +3376,13 @@ static bool AcceptBlock(const std::shared_ptr<const CBlock>& pblock, CValidation if (!IsInitialBlockDownload() && chainActive.Tip() == pindex->pprev) GetMainSignals().NewPoWValidBlock(pindex, pblock); - int nHeight = pindex->nHeight; - // Write block to history file try { - unsigned int nBlockSize = ::GetSerializeSize(block, SER_DISK, CLIENT_VERSION); - CDiskBlockPos blockPos; - if (dbp != nullptr) - blockPos = *dbp; - if (!FindBlockPos(state, blockPos, nBlockSize+8, nHeight, block.GetBlockTime(), dbp != nullptr)) - return error("AcceptBlock(): FindBlockPos failed"); - if (dbp == nullptr) - if (!WriteBlockToDisk(block, blockPos, chainparams.MessageStart())) - AbortNode(state, "Failed to write block"); + CDiskBlockPos blockPos = SaveBlockToDisk(block, pindex->nHeight, chainparams, dbp); + if (blockPos.IsNull()) { + state.Error(strprintf("%s: Failed to find position to write new block to disk", __func__)); + return false; + } if (!ReceivedBlockTransactions(block, state, pindex, blockPos, chainparams.GetConsensus())) return error("AcceptBlock(): ReceivedBlockTransactions failed"); } catch (const std::runtime_error& e) { @@ -3236,11 +3392,15 @@ static bool AcceptBlock(const std::shared_ptr<const CBlock>& pblock, CValidation if (fCheckForPruning) FlushStateToDisk(chainparams, state, FLUSH_STATE_NONE); // we just allocated more disk space for block files + CheckBlockIndex(chainparams.GetConsensus()); + return true; } bool ProcessNewBlock(const CChainParams& chainparams, const std::shared_ptr<const CBlock> pblock, bool fForceProcessing, bool *fNewBlock) { + AssertLockNotHeld(cs_main); + { CBlockIndex *pindex = nullptr; if (fNewBlock) *fNewBlock = false; @@ -3253,9 +3413,8 @@ bool ProcessNewBlock(const CChainParams& chainparams, const std::shared_ptr<cons if (ret) { // Store to disk - ret = AcceptBlock(pblock, state, chainparams, &pindex, fForceProcessing, nullptr, fNewBlock); + ret = g_chainstate.AcceptBlock(pblock, state, chainparams, &pindex, fForceProcessing, nullptr, fNewBlock); } - CheckBlockIndex(chainparams.GetConsensus()); if (!ret) { GetMainSignals().BlockChecked(*pblock, state); return error("%s: AcceptBlock FAILED (%s)", __func__, state.GetDebugMessage()); @@ -3265,7 +3424,7 @@ bool ProcessNewBlock(const CChainParams& chainparams, const std::shared_ptr<cons NotifyHeaderTip(); CValidationState state; // Only used to report errors, not invalidity - ignore it - if (!ActivateBestChain(state, chainparams, pblock)) + if (!g_chainstate.ActivateBestChain(state, chainparams, pblock)) return error("%s: ActivateBestChain failed", __func__); return true; @@ -3287,7 +3446,7 @@ bool TestBlockValidity(CValidationState& state, const CChainParams& chainparams, return error("%s: Consensus::CheckBlock: %s", __func__, FormatStateMessage(state)); if (!ContextualCheckBlock(block, state, chainparams.GetConsensus(), pindexPrev)) return error("%s: Consensus::ContextualCheckBlock: %s", __func__, FormatStateMessage(state)); - if (!ConnectBlock(block, state, &indexDummy, viewNew, chainparams, true)) + if (!g_chainstate.ConnectBlock(block, state, &indexDummy, viewNew, chainparams, true)) return false; assert(state.IsValid()); @@ -3315,8 +3474,8 @@ void PruneOneBlockFile(const int fileNumber) { LOCK(cs_LastBlockFile); - for (BlockMap::iterator it = mapBlockIndex.begin(); it != mapBlockIndex.end(); ++it) { - CBlockIndex* pindex = it->second; + for (const auto& entry : mapBlockIndex) { + CBlockIndex* pindex = entry.second; if (pindex->nFile == fileNumber) { pindex->nStatus &= ~BLOCK_HAVE_DATA; pindex->nStatus &= ~BLOCK_HAVE_UNDO; @@ -3464,7 +3623,7 @@ static FILE* OpenDiskFile(const CDiskBlockPos &pos, const char *prefix, bool fRe return nullptr; fs::path path = GetBlockPosFilename(pos, prefix); fs::create_directories(path.parent_path()); - FILE* file = fsbridge::fopen(path, "rb+"); + FILE* file = fsbridge::fopen(path, fReadOnly ? "rb": "rb+"); if (!file && !fReadOnly) file = fsbridge::fopen(path, "wb+"); if (!file) { @@ -3495,7 +3654,7 @@ fs::path GetBlockPosFilename(const CDiskBlockPos &pos, const char *prefix) return GetDataDir() / "blocks" / strprintf("%s%05u.dat", prefix, pos.nFile); } -CBlockIndex * InsertBlockIndex(uint256 hash) +CBlockIndex * CChainState::InsertBlockIndex(const uint256& hash) { if (hash.IsNull()) return nullptr; @@ -3513,9 +3672,9 @@ CBlockIndex * InsertBlockIndex(uint256 hash) return pindexNew; } -bool static LoadBlockIndexDB(const CChainParams& chainparams) +bool CChainState::LoadBlockIndex(const Consensus::Params& consensus_params, CBlockTreeDB& blocktree) { - if (!pblocktree->LoadBlockIndexGuts(chainparams.GetConsensus(), InsertBlockIndex)) + if (!blocktree.LoadBlockIndexGuts(consensus_params, [this](const uint256& hash){ return this->InsertBlockIndex(hash); })) return false; boost::this_thread::interruption_point(); @@ -3562,6 +3721,14 @@ bool static LoadBlockIndexDB(const CChainParams& chainparams) pindexBestHeader = pindex; } + return true; +} + +bool static LoadBlockIndexDB(const CChainParams& chainparams) +{ + if (!g_chainstate.LoadBlockIndex(chainparams.GetConsensus(), *pblocktree)) + return false; + // Load block file info pblocktree->ReadLastBlockFile(nLastBlockFile); vinfoBlockFile.resize(nLastBlockFile + 1); @@ -3634,7 +3801,7 @@ bool LoadChainTip(const CChainParams& chainparams) return false; chainActive.SetTip(it->second); - PruneBlockIndexCandidates(); + g_chainstate.PruneBlockIndexCandidates(); LogPrintf("Loaded best chain: hashBestChain=%s height=%d date=%s progress=%f\n", chainActive.Tip()->GetBlockHash().ToString(), chainActive.Height(), @@ -3699,16 +3866,16 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview, // check level 2: verify undo validity if (nCheckLevel >= 2 && pindex) { CBlockUndo undo; - CDiskBlockPos pos = pindex->GetUndoPos(); - if (!pos.IsNull()) { - if (!UndoReadFromDisk(undo, pos, pindex->pprev->GetBlockHash())) + if (!pindex->GetUndoPos().IsNull()) { + if (!UndoReadFromDisk(undo, pindex)) { return error("VerifyDB(): *** found bad undo data at %d, hash=%s\n", pindex->nHeight, pindex->GetBlockHash().ToString()); + } } } // check level 3: check for inconsistencies during memory-only disconnect of tip blocks if (nCheckLevel >= 3 && pindex == pindexState && (coins.DynamicMemoryUsage() + pcoinsTip->DynamicMemoryUsage()) <= nCoinCacheUsage) { assert(coins.GetBestBlock() == pindex->GetBlockHash()); - DisconnectResult res = DisconnectBlock(block, pindex, coins); + DisconnectResult res = g_chainstate.DisconnectBlock(block, pindex, coins); if (res == DISCONNECT_FAILED) { return error("VerifyDB(): *** irrecoverable inconsistency in block data at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString()); } @@ -3736,7 +3903,7 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview, CBlock block; if (!ReadBlockFromDisk(block, pindex, chainparams.GetConsensus())) return error("VerifyDB(): *** ReadBlockFromDisk failed at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString()); - if (!ConnectBlock(block, state, pindex, coins, chainparams)) + if (!g_chainstate.ConnectBlock(block, state, pindex, coins, chainparams)) return error("VerifyDB(): *** found unconnectable block at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString()); } } @@ -3748,7 +3915,7 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview, } /** Apply the effects of a block on the utxo cache, ignoring that it may already have been applied. */ -static bool RollforwardBlock(const CBlockIndex* pindex, CCoinsViewCache& inputs, const CChainParams& params) +bool CChainState::RollforwardBlock(const CBlockIndex* pindex, CCoinsViewCache& inputs, const CChainParams& params) { // TODO: merge with ConnectBlock CBlock block; @@ -3768,7 +3935,7 @@ static bool RollforwardBlock(const CBlockIndex* pindex, CCoinsViewCache& inputs, return true; } -bool ReplayBlocks(const CChainParams& params, CCoinsView* view) +bool CChainState::ReplayBlocks(const CChainParams& params, CCoinsView* view) { LOCK(cs_main); @@ -3833,7 +4000,11 @@ bool ReplayBlocks(const CChainParams& params, CCoinsView* view) return true; } -bool RewindBlockIndex(const CChainParams& params) +bool ReplayBlocks(const CChainParams& params, CCoinsView* view) { + return g_chainstate.ReplayBlocks(params, view); +} + +bool CChainState::RewindBlockIndex(const CChainParams& params) { LOCK(cs_main); @@ -3870,8 +4041,8 @@ bool RewindBlockIndex(const CChainParams& params) // Reduce validity flag and have-data flags. // We do this after actual disconnecting, otherwise we'll end up writing the lack of data // to disk before writing the chainstate, resulting in a failure to continue if interrupted. - for (BlockMap::iterator it = mapBlockIndex.begin(); it != mapBlockIndex.end(); it++) { - CBlockIndex* pindexIter = it->second; + for (const auto& entry : mapBlockIndex) { + CBlockIndex* pindexIter = entry.second; // Note: If we encounter an insufficiently validated block that // is on chainActive, it must be because we are a pruning node, and @@ -3914,10 +4085,21 @@ bool RewindBlockIndex(const CChainParams& params) PruneBlockIndexCandidates(); CheckBlockIndex(params.GetConsensus()); + } + return true; +} + +bool RewindBlockIndex(const CChainParams& params) { + if (!g_chainstate.RewindBlockIndex(params)) { + return false; + } + + if (chainActive.Tip() != nullptr) { // FlushStateToDisk can possibly read chainActive. Be conservative // and skip it here, we're about to -reindex-chainstate anyway, so // it'll get called a bunch real soon. + CValidationState state; if (!FlushStateToDisk(params, state, FLUSH_STATE_ALWAYS)) { return false; } @@ -3926,13 +4108,18 @@ bool RewindBlockIndex(const CChainParams& params) return true; } +void CChainState::UnloadBlockIndex() { + nBlockSequenceId = 1; + g_failed_blocks.clear(); + setBlockIndexCandidates.clear(); +} + // May NOT be used after any connections are up as much // of the peer-processing logic assumes a consistent // block index state void UnloadBlockIndex() { LOCK(cs_main); - setBlockIndexCandidates.clear(); chainActive.SetTip(nullptr); pindexBestInvalid = nullptr; pindexBestHeader = nullptr; @@ -3940,9 +4127,7 @@ void UnloadBlockIndex() mapBlocksUnlinked.clear(); vinfoBlockFile.clear(); nLastBlockFile = 0; - nBlockSequenceId = 1; setDirtyBlockIndex.clear(); - g_failed_blocks.clear(); setDirtyFileInfo.clear(); versionbitscache.Clear(); for (int b = 0; b < VERSIONBITS_NUM_BITS; b++) { @@ -3954,6 +4139,8 @@ void UnloadBlockIndex() } mapBlockIndex.clear(); fHavePruned = false; + + g_chainstate.UnloadBlockIndex(); } bool LoadBlockIndex(const CChainParams& chainparams) @@ -3981,7 +4168,7 @@ bool LoadBlockIndex(const CChainParams& chainparams) return true; } -bool LoadGenesisBlock(const CChainParams& chainparams) +bool CChainState::LoadGenesisBlock(const CChainParams& chainparams) { LOCK(cs_main); @@ -3994,15 +4181,11 @@ bool LoadGenesisBlock(const CChainParams& chainparams) try { CBlock &block = const_cast<CBlock&>(chainparams.GenesisBlock()); - // Start new block file - unsigned int nBlockSize = ::GetSerializeSize(block, SER_DISK, CLIENT_VERSION); - CDiskBlockPos blockPos; - CValidationState state; - if (!FindBlockPos(state, blockPos, nBlockSize+8, 0, block.GetBlockTime())) - return error("%s: FindBlockPos failed", __func__); - if (!WriteBlockToDisk(block, blockPos, chainparams.MessageStart())) + CDiskBlockPos blockPos = SaveBlockToDisk(block, 0, chainparams, nullptr); + if (blockPos.IsNull()) return error("%s: writing genesis block to disk failed", __func__); CBlockIndex *pindex = AddToBlockIndex(block); + CValidationState state; if (!ReceivedBlockTransactions(block, state, pindex, blockPos, chainparams.GetConsensus())) return error("%s: genesis block not accepted", __func__); } catch (const std::runtime_error& e) { @@ -4012,6 +4195,11 @@ bool LoadGenesisBlock(const CChainParams& chainparams) return true; } +bool LoadGenesisBlock(const CChainParams& chainparams) +{ + return g_chainstate.LoadGenesisBlock(chainparams); +} + bool LoadExternalBlockFile(const CChainParams& chainparams, FILE* fileIn, CDiskBlockPos *dbp) { // Map of disk positions for blocks with unknown parent (only used for reindex) @@ -4072,7 +4260,7 @@ bool LoadExternalBlockFile(const CChainParams& chainparams, FILE* fileIn, CDiskB if (mapBlockIndex.count(hash) == 0 || (mapBlockIndex[hash]->nStatus & BLOCK_HAVE_DATA) == 0) { LOCK(cs_main); CValidationState state; - if (AcceptBlock(pblock, state, chainparams, nullptr, true, dbp, nullptr)) + if (g_chainstate.AcceptBlock(pblock, state, chainparams, nullptr, true, dbp, nullptr)) nLoaded++; if (state.IsError()) break; @@ -4106,7 +4294,7 @@ bool LoadExternalBlockFile(const CChainParams& chainparams, FILE* fileIn, CDiskB head.ToString()); LOCK(cs_main); CValidationState dummy; - if (AcceptBlock(pblockrecursive, dummy, chainparams, nullptr, true, &it->second, nullptr)) + if (g_chainstate.AcceptBlock(pblockrecursive, dummy, chainparams, nullptr, true, &it->second, nullptr)) { nLoaded++; queue.push_back(pblockrecursive->GetHash()); @@ -4129,7 +4317,7 @@ bool LoadExternalBlockFile(const CChainParams& chainparams, FILE* fileIn, CDiskB return nLoaded > 0; } -void static CheckBlockIndex(const Consensus::Params& consensusParams) +void CChainState::CheckBlockIndex(const Consensus::Params& consensusParams) { if (!fCheckBlockIndex) { return; @@ -4147,8 +4335,8 @@ void static CheckBlockIndex(const Consensus::Params& consensusParams) // Build forward-pointing map of the entire block tree. std::multimap<CBlockIndex*,CBlockIndex*> forward; - for (BlockMap::iterator it = mapBlockIndex.begin(); it != mapBlockIndex.end(); it++) { - forward.insert(std::make_pair(it->second->pprev, it->second)); + for (auto& entry : mapBlockIndex) { + forward.insert(std::make_pair(entry.second->pprev, entry.second)); } assert(forward.size() == mapBlockIndex.size()); @@ -4471,7 +4659,7 @@ bool DumpMempool(void) } //! Guess how far we are in the verification process at the given block index -double GuessVerificationProgress(const ChainTxData& data, CBlockIndex *pindex) { +double GuessVerificationProgress(const ChainTxData& data, const CBlockIndex *pindex) { if (pindex == nullptr) return 0.0; diff --git a/src/validation.h b/src/validation.h index 254f3e0754..99cbfdf1ee 100644 --- a/src/validation.h +++ b/src/validation.h @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -159,7 +159,7 @@ extern CCriticalSection cs_main; extern CBlockPolicyEstimator feeEstimator; extern CTxMemPool mempool; typedef std::unordered_map<uint256, CBlockIndex*, BlockHasher> BlockMap; -extern BlockMap mapBlockIndex; +extern BlockMap& mapBlockIndex; extern uint64_t nLastBlockTx; extern uint64_t nLastBlockWeight; extern const std::string strMessageMagic; @@ -203,6 +203,8 @@ extern bool fPruneMode; extern uint64_t nPruneTarget; /** Block files containing a block-height within MIN_BLOCKS_TO_KEEP of chainActive.Tip() will not be pruned. */ static const unsigned int MIN_BLOCKS_TO_KEEP = 288; +/** Minimum blocks required to signal NODE_NETWORK_LIMITED */ +static const unsigned int NODE_NETWORK_LIMITED_MIN_BLOCKS = 288; static const signed int DEFAULT_CHECKBLOCKS = 6; static const unsigned int DEFAULT_CHECKLEVEL = 3; @@ -273,13 +275,13 @@ void ThreadScriptCheck(); /** Check whether we are doing an initial block download (synchronizing from disk or network) */ bool IsInitialBlockDownload(); /** Retrieve a transaction (from memory pool, or from disk, if possible) */ -bool GetTransaction(const uint256 &hash, CTransactionRef &tx, const Consensus::Params& params, uint256 &hashBlock, bool fAllowSlow = false); +bool GetTransaction(const uint256& hash, CTransactionRef& tx, const Consensus::Params& params, uint256& hashBlock, bool fAllowSlow = false, CBlockIndex* blockIndex = nullptr); /** Find the best known block, and make it the tip of the block chain */ bool ActivateBestChain(CValidationState& state, const CChainParams& chainparams, std::shared_ptr<const CBlock> pblock = std::shared_ptr<const CBlock>()); CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams); /** Guess verification progress (as a fraction between 0.0=genesis and 1.0=current tip). */ -double GuessVerificationProgress(const ChainTxData& data, CBlockIndex* pindex); +double GuessVerificationProgress(const ChainTxData& data, const CBlockIndex* pindex); /** Calculate the amount of disk space the block & undo files currently use */ uint64_t CalculateCurrentUsage(); @@ -294,8 +296,6 @@ void PruneOneBlockFile(const int fileNumber); */ void UnlinkPrunedFiles(const std::set<int>& setFilesToPrune); -/** Create a new block index entry for a given block hash */ -CBlockIndex * InsertBlockIndex(uint256 hash); /** Flush all state, indexes and buffers to disk. */ void FlushStateToDisk(); /** Prune block files and flush state to disk. */ @@ -441,7 +441,7 @@ bool InvalidateBlock(CValidationState& state, const CChainParams& chainparams, C bool ResetBlockFailureFlags(CBlockIndex *pindex); /** The currently-connected chain of blocks (protected by cs_main). */ -extern CChain chainActive; +extern CChain& chainActive; /** Global variable that points to the coins database (protected by cs_main) */ extern std::unique_ptr<CCoinsViewDB> pcoinsdbview; diff --git a/src/validationinterface.cpp b/src/validationinterface.cpp index 5ceba17e06..928df4fa65 100644 --- a/src/validationinterface.cpp +++ b/src/validationinterface.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -11,9 +11,11 @@ #include <sync.h> #include <txmempool.h> #include <util.h> +#include <validation.h> #include <list> #include <atomic> +#include <future> #include <boost/signals2/signal.hpp> @@ -49,7 +51,14 @@ void CMainSignals::UnregisterBackgroundSignalScheduler() { } void CMainSignals::FlushBackgroundCallbacks() { - m_internals->m_schedulerClient.EmptyQueue(); + if (m_internals) { + m_internals->m_schedulerClient.EmptyQueue(); + } +} + +size_t CMainSignals::CallbacksPending() { + if (!m_internals) return 0; + return m_internals->m_schedulerClient.CallbacksPending(); } void CMainSignals::RegisterWithMempoolSignals(CTxMemPool& pool) { @@ -92,6 +101,9 @@ void UnregisterValidationInterface(CValidationInterface* pwalletIn) { } void UnregisterAllValidationInterfaces() { + if (!g_signals.m_internals) { + return; + } g_signals.m_internals->BlockChecked.disconnect_all_slots(); g_signals.m_internals->Broadcast.disconnect_all_slots(); g_signals.m_internals->Inventory.disconnect_all_slots(); @@ -108,6 +120,16 @@ void CallFunctionInValidationInterfaceQueue(std::function<void ()> func) { g_signals.m_internals->m_schedulerClient.AddToProcessQueue(std::move(func)); } +void SyncWithValidationInterfaceQueue() { + AssertLockNotHeld(cs_main); + // Block until the validation queue drains + std::promise<void> promise; + CallFunctionInValidationInterfaceQueue([&promise] { + promise.set_value(); + }); + promise.get_future().wait(); +} + void CMainSignals::MempoolEntryRemoved(CTransactionRef ptx, MemPoolRemovalReason reason) { if (reason != MemPoolRemovalReason::BLOCK && reason != MemPoolRemovalReason::CONFLICT) { m_internals->m_schedulerClient.AddToProcessQueue([ptx, this] { diff --git a/src/validationinterface.h b/src/validationinterface.h index 7b5d138414..56ea698a2e 100644 --- a/src/validationinterface.h +++ b/src/validationinterface.h @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -42,6 +42,16 @@ void UnregisterAllValidationInterfaces(); * will result in a deadlock (that DEBUG_LOCKORDER will miss). */ void CallFunctionInValidationInterfaceQueue(std::function<void ()> func); +/** + * This is a synonym for the following, which asserts certain locks are not + * held: + * std::promise<void> promise; + * CallFunctionInValidationInterfaceQueue([&promise] { + * promise.set_value(); + * }); + * promise.get_future().wait(); + */ +void SyncWithValidationInterfaceQueue(); class CValidationInterface { protected: @@ -131,6 +141,8 @@ public: /** Call any remaining callbacks on the calling thread */ void FlushBackgroundCallbacks(); + size_t CallbacksPending(); + /** Register with mempool to call TransactionRemovedFromMempool callbacks */ void RegisterWithMempoolSignals(CTxMemPool& pool); /** Unregister with mempool */ diff --git a/src/version.h b/src/version.h index d528212490..4b38547f35 100644 --- a/src/version.h +++ b/src/version.h @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2016 The Bitcoin Core developers +// Copyright (c) 2012-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/versionbits.cpp b/src/versionbits.cpp index 3bd00ccb23..d2ee49db20 100644 --- a/src/versionbits.cpp +++ b/src/versionbits.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2016 The Bitcoin Core developers +// Copyright (c) 2016-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/versionbits.h b/src/versionbits.h index 0e111ed7a1..1600dc8c93 100644 --- a/src/versionbits.h +++ b/src/versionbits.h @@ -1,4 +1,4 @@ -// Copyright (c) 2016 The Bitcoin Core developers +// Copyright (c) 2016-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/wallet/coincontrol.h b/src/wallet/coincontrol.h index 15fd105779..458e770e03 100644 --- a/src/wallet/coincontrol.h +++ b/src/wallet/coincontrol.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -16,7 +16,10 @@ class CCoinControl { public: + //! Custom change destination, if not set an address is generated CTxDestination destChange; + //! Custom change type, ignored if destChange is set, defaults to g_change_type + OutputType change_type; //! If false, allows unselected inputs, but requires all selected inputs be used bool fAllowOtherInputs; //! Includes watch only addresses which match the ISMINE_WATCH_SOLVABLE criteria @@ -40,6 +43,7 @@ public: void SetNull() { destChange = CNoDestination(); + change_type = g_change_type; fAllowOtherInputs = false; fAllowWatchOnly = false; setSelected.clear(); diff --git a/src/wallet/crypter.cpp b/src/wallet/crypter.cpp index 4cd7db048b..6ad18721fd 100644 --- a/src/wallet/crypter.cpp +++ b/src/wallet/crypter.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -245,6 +245,7 @@ bool CCryptoKeyStore::AddCryptedKey(const CPubKey &vchPubKey, const std::vector< } mapCryptedKeys[vchPubKey.GetID()] = make_pair(vchPubKey, vchCryptedSecret); + ImplicitlyLearnRelatedKeyScripts(vchPubKey); return true; } diff --git a/src/wallet/crypter.h b/src/wallet/crypter.h index 7b0936ba0d..f3ae7144b4 100644 --- a/src/wallet/crypter.h +++ b/src/wallet/crypter.h @@ -1,4 +1,4 @@ -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/wallet/db.cpp b/src/wallet/db.cpp index c6fd95f250..23c6279128 100644 --- a/src/wallet/db.cpp +++ b/src/wallet/db.cpp @@ -1,16 +1,16 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 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 <wallet/db.h> #include <addrman.h> -#include <fs.h> #include <hash.h> #include <protocol.h> #include <util.h> #include <utilstrencodings.h> +#include <wallet/walletutil.h> #include <stdint.h> @@ -95,7 +95,7 @@ void CDBEnv::Close() EnvShutdown(); } -bool CDBEnv::Open(const fs::path& pathIn) +bool CDBEnv::Open(const fs::path& pathIn, bool retry) { if (fDbEnvInit) return true; @@ -103,6 +103,11 @@ bool CDBEnv::Open(const fs::path& pathIn) boost::this_thread::interruption_point(); strPath = pathIn.string(); + if (!LockDirectory(pathIn, ".walletlock")) { + LogPrintf("Cannot obtain a lock on wallet directory %s. Another instance of bitcoin may be using it.\n", strPath); + return false; + } + fs::path pathLogDir = pathIn / "database"; TryCreateDirectories(pathLogDir); fs::path pathErrorFile = pathIn / "db.log"; @@ -134,7 +139,24 @@ bool CDBEnv::Open(const fs::path& pathIn) S_IRUSR | S_IWUSR); if (ret != 0) { dbenv->close(0); - return error("CDBEnv::Open: Error %d opening database environment: %s\n", ret, DbEnv::strerror(ret)); + LogPrintf("CDBEnv::Open: Error %d opening database environment: %s\n", ret, DbEnv::strerror(ret)); + if (retry) { + // try moving the database env out of the way + fs::path pathDatabaseBak = pathIn / strprintf("database.%d.bak", GetTime()); + try { + fs::rename(pathLogDir, pathDatabaseBak); + LogPrintf("Moved old %s to %s. Retrying.\n", pathLogDir.string(), pathDatabaseBak.string()); + } catch (const fs::filesystem_error&) { + // failure is ok (well, not really, but it's not worse than what we started with) + } + // try opening it again one more time + if (!Open(pathIn, false)) { + // if it still fails, it probably means we can't even create the database env + return false; + } + } else { + return false; + } } fDbEnvInit = true; @@ -257,7 +279,7 @@ bool CDB::Recover(const std::string& filename, void *callbackDataIn, bool (*reco return fSuccess; } -bool CDB::VerifyEnvironment(const std::string& walletFile, const fs::path& dataDir, std::string& errorStr) +bool CDB::VerifyEnvironment(const std::string& walletFile, const fs::path& walletDir, std::string& errorStr) { LogPrintf("Using BerkeleyDB version %s\n", DbEnv::version(0, 0, 0)); LogPrintf("Using wallet %s\n", walletFile); @@ -265,35 +287,21 @@ bool CDB::VerifyEnvironment(const std::string& walletFile, const fs::path& dataD // Wallet file must be a plain filename without a directory if (walletFile != fs::basename(walletFile) + fs::extension(walletFile)) { - errorStr = strprintf(_("Wallet %s resides outside data directory %s"), walletFile, dataDir.string()); + errorStr = strprintf(_("Wallet %s resides outside wallet directory %s"), walletFile, walletDir.string()); return false; } - if (!bitdb.Open(dataDir)) - { - // try moving the database env out of the way - fs::path pathDatabase = dataDir / "database"; - fs::path pathDatabaseBak = dataDir / strprintf("database.%d.bak", GetTime()); - try { - fs::rename(pathDatabase, pathDatabaseBak); - LogPrintf("Moved old %s to %s. Retrying.\n", pathDatabase.string(), pathDatabaseBak.string()); - } catch (const fs::filesystem_error&) { - // failure is ok (well, not really, but it's not worse than what we started with) - } - - // try again - if (!bitdb.Open(dataDir)) { - // if it still fails, it probably means we can't even create the database env - errorStr = strprintf(_("Error initializing wallet database environment %s!"), GetDataDir()); - return false; - } + if (!bitdb.Open(walletDir, true)) { + errorStr = strprintf(_("Error initializing wallet database environment %s!"), walletDir); + return false; } + return true; } -bool CDB::VerifyDatabaseFile(const std::string& walletFile, const fs::path& dataDir, std::string& warningStr, std::string& errorStr, CDBEnv::recoverFunc_type recoverFunc) +bool CDB::VerifyDatabaseFile(const std::string& walletFile, const fs::path& walletDir, std::string& warningStr, std::string& errorStr, CDBEnv::recoverFunc_type recoverFunc) { - if (fs::exists(dataDir / walletFile)) + if (fs::exists(walletDir / walletFile)) { std::string backup_filename; CDBEnv::VerifyResult r = bitdb.Verify(walletFile, recoverFunc, backup_filename); @@ -303,7 +311,7 @@ bool CDB::VerifyDatabaseFile(const std::string& walletFile, const fs::path& data " Original %s saved as %s in %s; if" " your balance or transactions are incorrect you should" " restore from a backup."), - walletFile, backup_filename, dataDir); + walletFile, backup_filename, walletDir); } if (r == CDBEnv::RECOVER_FAIL) { @@ -407,7 +415,7 @@ CDB::CDB(CWalletDBWrapper& dbw, const char* pszMode, bool fFlushOnCloseIn) : pdb { LOCK(env->cs_db); - if (!env->Open(GetDataDir())) + if (!env->Open(GetWalletDir())) throw std::runtime_error("CDB: Failed to open database environment."); pdb = env->mapDb[strFilename]; @@ -695,7 +703,7 @@ bool CWalletDBWrapper::Backup(const std::string& strDest) env->mapFileUseCount.erase(strFile); // Copy wallet file - fs::path pathSrc = GetDataDir() / strFile; + fs::path pathSrc = GetWalletDir() / strFile; fs::path pathDest(strDest); if (fs::is_directory(pathDest)) pathDest /= strFile; diff --git a/src/wallet/db.h b/src/wallet/db.h index 5c5948aa29..787135e400 100644 --- a/src/wallet/db.h +++ b/src/wallet/db.h @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -68,7 +68,7 @@ public: typedef std::pair<std::vector<unsigned char>, std::vector<unsigned char> > KeyValPair; bool Salvage(const std::string& strFile, bool fAggressive, std::vector<KeyValPair>& vResult); - bool Open(const fs::path& path); + bool Open(const fs::path& path, bool retry = 0); void Close(); void Flush(bool fShutdown); void CheckpointLSN(const std::string& strFile); @@ -167,9 +167,9 @@ public: ideal to be called periodically */ static bool PeriodicFlush(CWalletDBWrapper& dbw); /* verifies the database environment */ - static bool VerifyEnvironment(const std::string& walletFile, const fs::path& dataDir, std::string& errorStr); + static bool VerifyEnvironment(const std::string& walletFile, const fs::path& walletDir, std::string& errorStr); /* verifies the database file */ - static bool VerifyDatabaseFile(const std::string& walletFile, const fs::path& dataDir, std::string& warningStr, std::string& errorStr, CDBEnv::recoverFunc_type recoverFunc); + static bool VerifyDatabaseFile(const std::string& walletFile, const fs::path& walletDir, std::string& warningStr, std::string& errorStr, CDBEnv::recoverFunc_type recoverFunc); public: template <typename K, typename T> diff --git a/src/wallet/init.cpp b/src/wallet/init.cpp index ca6dcccf78..ace95204b8 100644 --- a/src/wallet/init.cpp +++ b/src/wallet/init.cpp @@ -9,12 +9,15 @@ #include <util.h> #include <utilmoneystr.h> #include <validation.h> -#include <wallet/wallet.h> #include <wallet/rpcwallet.h> +#include <wallet/wallet.h> +#include <wallet/walletutil.h> std::string GetWalletHelpString(bool showDebug) { std::string strUsage = HelpMessageGroup(_("Wallet options:")); + strUsage += HelpMessageOpt("-addresstype", strprintf("What type of addresses to use (\"legacy\", \"p2sh-segwit\", or \"bech32\", default: \"%s\")", FormatOutputType(OUTPUT_TYPE_DEFAULT))); + strUsage += HelpMessageOpt("-changetype", "What type of change to use (\"legacy\", \"p2sh-segwit\", or \"bech32\"). Default is same as -addresstype, except when -addresstype=p2sh-segwit a native segwit output is used when sending to a native segwit address)"); strUsage += HelpMessageOpt("-disablewallet", _("Do not load the wallet and disable wallet RPC calls")); strUsage += HelpMessageOpt("-keypool=<n>", strprintf(_("Set key pool size to <n> (default: %u)"), DEFAULT_KEYPOOL_SIZE)); strUsage += HelpMessageOpt("-fallbackfee=<amt>", strprintf(_("A fee rate (in %s/kB) that will be used when fee estimation has insufficient data (default: %s)"), @@ -30,10 +33,11 @@ std::string GetWalletHelpString(bool showDebug) strUsage += HelpMessageOpt("-salvagewallet", _("Attempt to recover private keys from a corrupt wallet on startup")); 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("-walletrbf", strprintf(_("Send transactions with full-RBF opt-in enabled (default: %u)"), DEFAULT_WALLET_RBF)); + strUsage += HelpMessageOpt("-walletrbf", strprintf(_("Send transactions with full-RBF opt-in enabled (RPC only, 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)); + strUsage += HelpMessageOpt("-walletdir=<dir>", _("Specify directory to hold wallets (default: <datadir>/wallets if it exists, otherwise <datadir>)")); strUsage += HelpMessageOpt("-walletnotify=<cmd>", _("Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)")); strUsage += HelpMessageOpt("-zapwallettxes=<mode>", _("Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup") + " " + _("(1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data)")); @@ -173,6 +177,18 @@ bool WalletParameterInteraction() bSpendZeroConfChange = gArgs.GetBoolArg("-spendzeroconfchange", DEFAULT_SPEND_ZEROCONF_CHANGE); fWalletRbf = gArgs.GetBoolArg("-walletrbf", DEFAULT_WALLET_RBF); + g_address_type = ParseOutputType(gArgs.GetArg("-addresstype", "")); + if (g_address_type == OUTPUT_TYPE_NONE) { + return InitError(strprintf("Unknown address type '%s'", gArgs.GetArg("-addresstype", ""))); + } + + // If changetype is set in config file or parameter, check that it's valid. + // Default to OUTPUT_TYPE_NONE if not set. + g_change_type = ParseOutputType(gArgs.GetArg("-changetype", ""), OUTPUT_TYPE_NONE); + if (g_change_type == OUTPUT_TYPE_NONE && !gArgs.GetArg("-changetype", "").empty()) { + return InitError(strprintf("Unknown change type '%s'", gArgs.GetArg("-changetype", ""))); + } + return true; } @@ -191,6 +207,19 @@ bool VerifyWallets() return true; } + if (gArgs.IsArgSet("-walletdir")) { + fs::path wallet_dir = gArgs.GetArg("-walletdir", ""); + if (!fs::exists(wallet_dir)) { + return InitError(strprintf(_("Specified -walletdir \"%s\" does not exist"), wallet_dir.string())); + } else if (!fs::is_directory(wallet_dir)) { + return InitError(strprintf(_("Specified -walletdir \"%s\" is not a directory"), wallet_dir.string())); + } else if (!wallet_dir.is_absolute()) { + return InitError(strprintf(_("Specified -walletdir \"%s\" is a relative path"), wallet_dir.string())); + } + } + + LogPrintf("Using wallet directory %s\n", GetWalletDir().string()); + uiInterface.InitMessage(_("Verifying wallet(s)...")); // Keep track of each wallet absolute path to detect duplicates. @@ -205,7 +234,7 @@ bool VerifyWallets() return InitError(strprintf(_("Error loading wallet %s. Invalid characters in -wallet filename."), walletFile)); } - fs::path wallet_path = fs::absolute(walletFile, GetDataDir()); + fs::path wallet_path = fs::absolute(walletFile, GetWalletDir()); if (fs::exists(wallet_path) && (!fs::is_regular_file(wallet_path) || fs::is_symlink(wallet_path))) { return InitError(strprintf(_("Error loading wallet %s. -wallet filename must be a regular file."), walletFile)); @@ -216,7 +245,7 @@ bool VerifyWallets() } std::string strError; - if (!CWalletDB::VerifyEnvironment(walletFile, GetDataDir().string(), strError)) { + if (!CWalletDB::VerifyEnvironment(walletFile, GetWalletDir().string(), strError)) { return InitError(strError); } @@ -230,7 +259,7 @@ bool VerifyWallets() } std::string strWarning; - bool dbV = CWalletDB::VerifyDatabaseFile(walletFile, GetDataDir().string(), strWarning, strError); + bool dbV = CWalletDB::VerifyDatabaseFile(walletFile, GetWalletDir().string(), strWarning, strError); if (!strWarning.empty()) { InitWarning(strWarning); } diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index fcc4c43872..0b021f9fe0 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -86,7 +86,8 @@ UniValue importprivkey(const JSONRPCRequest& request) "1. \"privkey\" (string, required) The private key (see dumpprivkey)\n" "2. \"label\" (string, optional, default=\"\") An optional label\n" "3. rescan (boolean, optional, default=true) Rescan the wallet for transactions\n" - "\nNote: This call can take minutes to complete if rescan is true.\n" + "\nNote: This call can take minutes to complete if rescan is true, during that time, other rpc calls\n" + "may report that the imported key exists but related transactions are still missing, leading to temporarily incorrect/bogus balances and unspent outputs until rescan completes.\n" "\nExamples:\n" "\nDump a private key\n" + HelpExampleCli("dumpprivkey", "\"myaddress\"") + @@ -101,56 +102,65 @@ UniValue importprivkey(const JSONRPCRequest& request) ); - LOCK2(cs_main, pwallet->cs_wallet); + WalletRescanReserver reserver(pwallet); + bool fRescan = true; + { + LOCK2(cs_main, pwallet->cs_wallet); - EnsureWalletIsUnlocked(pwallet); + EnsureWalletIsUnlocked(pwallet); - std::string strSecret = request.params[0].get_str(); - std::string strLabel = ""; - if (!request.params[1].isNull()) - strLabel = request.params[1].get_str(); - - // Whether to perform rescan after import - bool fRescan = true; - if (!request.params[2].isNull()) - fRescan = request.params[2].get_bool(); + std::string strSecret = request.params[0].get_str(); + std::string strLabel = ""; + if (!request.params[1].isNull()) + strLabel = request.params[1].get_str(); - if (fRescan && fPruneMode) - throw JSONRPCError(RPC_WALLET_ERROR, "Rescan is disabled in pruned mode"); + // Whether to perform rescan after import + if (!request.params[2].isNull()) + fRescan = request.params[2].get_bool(); - CBitcoinSecret vchSecret; - bool fGood = vchSecret.SetString(strSecret); + if (fRescan && fPruneMode) + throw JSONRPCError(RPC_WALLET_ERROR, "Rescan is disabled in pruned mode"); - if (!fGood) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key encoding"); + if (fRescan && !reserver.reserve()) { + throw JSONRPCError(RPC_WALLET_ERROR, "Wallet is currently rescanning. Abort existing rescan or wait."); + } - CKey key = vchSecret.GetKey(); - if (!key.IsValid()) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Private key outside allowed range"); + CBitcoinSecret vchSecret; + bool fGood = vchSecret.SetString(strSecret); - CPubKey pubkey = key.GetPubKey(); - assert(key.VerifyPubKey(pubkey)); - CKeyID vchAddress = pubkey.GetID(); - { - pwallet->MarkDirty(); - pwallet->SetAddressBook(vchAddress, strLabel, "receive"); + if (!fGood) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key encoding"); - // Don't throw error in case a key is already there - if (pwallet->HaveKey(vchAddress)) { - return NullUniValue; - } + CKey key = vchSecret.GetKey(); + if (!key.IsValid()) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Private key outside allowed range"); - pwallet->mapKeyMetadata[vchAddress].nCreateTime = 1; + CPubKey pubkey = key.GetPubKey(); + assert(key.VerifyPubKey(pubkey)); + CKeyID vchAddress = pubkey.GetID(); + { + pwallet->MarkDirty(); + // We don't know which corresponding address will be used; label them all + for (const auto& dest : GetAllDestinationsForKey(pubkey)) { + pwallet->SetAddressBook(dest, strLabel, "receive"); + } - if (!pwallet->AddKeyPubKey(key, pubkey)) { - throw JSONRPCError(RPC_WALLET_ERROR, "Error adding key to wallet"); - } + // Don't throw error in case a key is already there + if (pwallet->HaveKey(vchAddress)) { + return NullUniValue; + } - // whenever a key is imported, we need to scan the whole chain - pwallet->UpdateTimeFirstKey(1); + // whenever a key is imported, we need to scan the whole chain + pwallet->UpdateTimeFirstKey(1); + pwallet->mapKeyMetadata[vchAddress].nCreateTime = 1; - if (fRescan) { - pwallet->RescanFromTime(TIMESTAMP_MIN, true /* update */); + if (!pwallet->AddKeyPubKey(key, pubkey)) { + throw JSONRPCError(RPC_WALLET_ERROR, "Error adding key to wallet"); + } + pwallet->LearnAllRelatedScripts(pubkey); } } + if (fRescan) { + pwallet->RescanFromTime(TIMESTAMP_MIN, reserver, true /* update */); + } return NullUniValue; } @@ -165,7 +175,7 @@ UniValue abortrescan(const JSONRPCRequest& request) if (request.fHelp || request.params.size() > 0) throw std::runtime_error( "abortrescan\n" - "\nStops current wallet rescan triggered e.g. by an importprivkey call.\n" + "\nStops current wallet rescan triggered by an RPC call, e.g. by an importprivkey call.\n" "\nExamples:\n" "\nImport a private key\n" + HelpExampleCli("importprivkey", "\"mykey\"") + @@ -232,7 +242,8 @@ UniValue importaddress(const JSONRPCRequest& request) "2. \"label\" (string, optional, default=\"\") An optional label\n" "3. rescan (boolean, optional, default=true) Rescan the wallet for transactions\n" "4. p2sh (boolean, optional, default=false) Add the P2SH version of the script as well\n" - "\nNote: This call can take minutes to complete if rescan is true.\n" + "\nNote: This call can take minutes to complete if rescan is true, during that time, other rpc calls\n" + "may report that the imported address exists but related transactions are still missing, leading to temporarily incorrect/bogus balances and unspent outputs until rescan completes.\n" "If you have the full public key, you should call importpubkey instead of this.\n" "\nNote: If you import a non-standard raw script in hex form, outputs sending to it will be treated\n" "as change, and not show up in many RPCs.\n" @@ -258,29 +269,35 @@ UniValue importaddress(const JSONRPCRequest& request) if (fRescan && fPruneMode) throw JSONRPCError(RPC_WALLET_ERROR, "Rescan is disabled in pruned mode"); + WalletRescanReserver reserver(pwallet); + if (fRescan && !reserver.reserve()) { + throw JSONRPCError(RPC_WALLET_ERROR, "Wallet is currently rescanning. Abort existing rescan or wait."); + } + // Whether to import a p2sh version, too bool fP2SH = false; if (!request.params[3].isNull()) fP2SH = request.params[3].get_bool(); - LOCK2(cs_main, pwallet->cs_wallet); + { + LOCK2(cs_main, pwallet->cs_wallet); - CTxDestination dest = DecodeDestination(request.params[0].get_str()); - if (IsValidDestination(dest)) { - if (fP2SH) { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Cannot use the p2sh flag with an address - use a script instead"); + CTxDestination dest = DecodeDestination(request.params[0].get_str()); + if (IsValidDestination(dest)) { + if (fP2SH) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Cannot use the p2sh flag with an address - use a script instead"); + } + ImportAddress(pwallet, dest, strLabel); + } else if (IsHex(request.params[0].get_str())) { + std::vector<unsigned char> data(ParseHex(request.params[0].get_str())); + ImportScript(pwallet, CScript(data.begin(), data.end()), strLabel, fP2SH); + } else { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address or script"); } - ImportAddress(pwallet, dest, strLabel); - } else if (IsHex(request.params[0].get_str())) { - std::vector<unsigned char> data(ParseHex(request.params[0].get_str())); - ImportScript(pwallet, CScript(data.begin(), data.end()), strLabel, fP2SH); - } else { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address or script"); } - if (fRescan) { - pwallet->RescanFromTime(TIMESTAMP_MIN, true /* update */); + pwallet->RescanFromTime(TIMESTAMP_MIN, reserver, true /* update */); pwallet->ReacceptWalletTransactions(); } @@ -401,7 +418,8 @@ UniValue importpubkey(const JSONRPCRequest& request) "1. \"pubkey\" (string, required) The hex-encoded public key\n" "2. \"label\" (string, optional, default=\"\") An optional label\n" "3. rescan (boolean, optional, default=true) Rescan the wallet for transactions\n" - "\nNote: This call can take minutes to complete if rescan is true.\n" + "\nNote: This call can take minutes to complete if rescan is true, during that time, other rpc calls\n" + "may report that the imported pubkey exists but related transactions are still missing, leading to temporarily incorrect/bogus balances and unspent outputs until rescan completes.\n" "\nExamples:\n" "\nImport a public key with rescan\n" + HelpExampleCli("importpubkey", "\"mypubkey\"") + @@ -424,6 +442,11 @@ UniValue importpubkey(const JSONRPCRequest& request) if (fRescan && fPruneMode) throw JSONRPCError(RPC_WALLET_ERROR, "Rescan is disabled in pruned mode"); + WalletRescanReserver reserver(pwallet); + if (fRescan && !reserver.reserve()) { + throw JSONRPCError(RPC_WALLET_ERROR, "Wallet is currently rescanning. Abort existing rescan or wait."); + } + if (!IsHex(request.params[0].get_str())) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Pubkey must be a hex string"); std::vector<unsigned char> data(ParseHex(request.params[0].get_str())); @@ -431,14 +454,18 @@ UniValue importpubkey(const JSONRPCRequest& request) if (!pubKey.IsFullyValid()) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Pubkey is not a valid public key"); - LOCK2(cs_main, pwallet->cs_wallet); - - ImportAddress(pwallet, pubKey.GetID(), strLabel); - ImportScript(pwallet, GetScriptForRawPubKey(pubKey), strLabel, false); + { + LOCK2(cs_main, pwallet->cs_wallet); + for (const auto& dest : GetAllDestinationsForKey(pubKey)) { + ImportAddress(pwallet, dest, strLabel); + } + ImportScript(pwallet, GetScriptForRawPubKey(pubKey), strLabel, false); + pwallet->LearnAllRelatedScripts(pubKey); + } if (fRescan) { - pwallet->RescanFromTime(TIMESTAMP_MIN, true /* update */); + pwallet->RescanFromTime(TIMESTAMP_MIN, reserver, true /* update */); pwallet->ReacceptWalletTransactions(); } @@ -471,78 +498,102 @@ UniValue importwallet(const JSONRPCRequest& request) if (fPruneMode) throw JSONRPCError(RPC_WALLET_ERROR, "Importing wallets is disabled in pruned mode"); - LOCK2(cs_main, pwallet->cs_wallet); - - EnsureWalletIsUnlocked(pwallet); - - std::ifstream file; - file.open(request.params[0].get_str().c_str(), std::ios::in | std::ios::ate); - if (!file.is_open()) - throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot open wallet dump file"); - - int64_t nTimeBegin = chainActive.Tip()->GetBlockTime(); + WalletRescanReserver reserver(pwallet); + if (!reserver.reserve()) { + throw JSONRPCError(RPC_WALLET_ERROR, "Wallet is currently rescanning. Abort existing rescan or wait."); + } + int64_t nTimeBegin = 0; bool fGood = true; + { + LOCK2(cs_main, pwallet->cs_wallet); - int64_t nFilesize = std::max((int64_t)1, (int64_t)file.tellg()); - file.seekg(0, file.beg); - - pwallet->ShowProgress(_("Importing..."), 0); // show progress dialog in GUI - while (file.good()) { - pwallet->ShowProgress("", std::max(1, std::min(99, (int)(((double)file.tellg() / (double)nFilesize) * 100)))); - std::string line; - std::getline(file, line); - if (line.empty() || line[0] == '#') - continue; - - std::vector<std::string> vstr; - boost::split(vstr, line, boost::is_any_of(" ")); - if (vstr.size() < 2) - continue; - CBitcoinSecret vchSecret; - if (!vchSecret.SetString(vstr[0])) - continue; - CKey key = vchSecret.GetKey(); - CPubKey pubkey = key.GetPubKey(); - assert(key.VerifyPubKey(pubkey)); - CKeyID keyid = pubkey.GetID(); - if (pwallet->HaveKey(keyid)) { - LogPrintf("Skipping import of %s (key already present)\n", EncodeDestination(keyid)); - continue; + EnsureWalletIsUnlocked(pwallet); + + std::ifstream file; + file.open(request.params[0].get_str().c_str(), std::ios::in | std::ios::ate); + if (!file.is_open()) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot open wallet dump file"); } - int64_t nTime = DecodeDumpTime(vstr[1]); - std::string strLabel; - bool fLabel = true; - for (unsigned int nStr = 2; nStr < vstr.size(); nStr++) { - if (boost::algorithm::starts_with(vstr[nStr], "#")) - break; - if (vstr[nStr] == "change=1") - fLabel = false; - if (vstr[nStr] == "reserve=1") - fLabel = false; - if (boost::algorithm::starts_with(vstr[nStr], "label=")) { - strLabel = DecodeDumpString(vstr[nStr].substr(6)); - fLabel = true; + nTimeBegin = chainActive.Tip()->GetBlockTime(); + + int64_t nFilesize = std::max((int64_t)1, (int64_t)file.tellg()); + file.seekg(0, file.beg); + + pwallet->ShowProgress(_("Importing..."), 0); // show progress dialog in GUI + while (file.good()) { + pwallet->ShowProgress("", std::max(1, std::min(99, (int)(((double)file.tellg() / (double)nFilesize) * 100)))); + std::string line; + std::getline(file, line); + if (line.empty() || line[0] == '#') + continue; + + std::vector<std::string> vstr; + boost::split(vstr, line, boost::is_any_of(" ")); + if (vstr.size() < 2) + continue; + CBitcoinSecret vchSecret; + if (vchSecret.SetString(vstr[0])) { + CKey key = vchSecret.GetKey(); + CPubKey pubkey = key.GetPubKey(); + assert(key.VerifyPubKey(pubkey)); + CKeyID keyid = pubkey.GetID(); + if (pwallet->HaveKey(keyid)) { + LogPrintf("Skipping import of %s (key already present)\n", EncodeDestination(keyid)); + continue; + } + int64_t nTime = DecodeDumpTime(vstr[1]); + std::string strLabel; + bool fLabel = true; + for (unsigned int nStr = 2; nStr < vstr.size(); nStr++) { + if (boost::algorithm::starts_with(vstr[nStr], "#")) + break; + if (vstr[nStr] == "change=1") + fLabel = false; + if (vstr[nStr] == "reserve=1") + fLabel = false; + if (boost::algorithm::starts_with(vstr[nStr], "label=")) { + strLabel = DecodeDumpString(vstr[nStr].substr(6)); + fLabel = true; + } + } + LogPrintf("Importing %s...\n", EncodeDestination(keyid)); + if (!pwallet->AddKeyPubKey(key, pubkey)) { + fGood = false; + continue; + } + pwallet->mapKeyMetadata[keyid].nCreateTime = nTime; + if (fLabel) + pwallet->SetAddressBook(keyid, strLabel, "receive"); + nTimeBegin = std::min(nTimeBegin, nTime); + } else if(IsHex(vstr[0])) { + std::vector<unsigned char> vData(ParseHex(vstr[0])); + CScript script = CScript(vData.begin(), vData.end()); + if (pwallet->HaveCScript(script)) { + LogPrintf("Skipping import of %s (script already present)\n", vstr[0]); + continue; + } + if(!pwallet->AddCScript(script)) { + LogPrintf("Error importing script %s\n", vstr[0]); + fGood = false; + continue; + } + int64_t birth_time = DecodeDumpTime(vstr[1]); + if (birth_time > 0) { + pwallet->m_script_metadata[CScriptID(script)].nCreateTime = birth_time; + nTimeBegin = std::min(nTimeBegin, birth_time); + } } } - LogPrintf("Importing %s...\n", EncodeDestination(keyid)); - if (!pwallet->AddKeyPubKey(key, pubkey)) { - fGood = false; - continue; - } - pwallet->mapKeyMetadata[keyid].nCreateTime = nTime; - if (fLabel) - pwallet->SetAddressBook(keyid, strLabel, "receive"); - nTimeBegin = std::min(nTimeBegin, nTime); + file.close(); + pwallet->ShowProgress("", 100); // hide progress dialog in GUI + pwallet->UpdateTimeFirstKey(nTimeBegin); } - file.close(); - pwallet->ShowProgress("", 100); // hide progress dialog in GUI - pwallet->UpdateTimeFirstKey(nTimeBegin); - pwallet->RescanFromTime(nTimeBegin, false /* update */); + pwallet->RescanFromTime(nTimeBegin, reserver, false /* update */); pwallet->MarkDirty(); if (!fGood) - throw JSONRPCError(RPC_WALLET_ERROR, "Error adding some keys to wallet"); + throw JSONRPCError(RPC_WALLET_ERROR, "Error adding some keys/scripts to wallet"); return NullUniValue; } @@ -578,12 +629,12 @@ UniValue dumpprivkey(const JSONRPCRequest& request) if (!IsValidDestination(dest)) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address"); } - const CKeyID *keyID = boost::get<CKeyID>(&dest); - if (!keyID) { + auto keyid = GetKeyForDestination(*pwallet, dest); + if (keyid.IsNull()) { throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to a key"); } CKey vchSecret; - if (!pwallet->GetKey(*keyID, vchSecret)) { + if (!pwallet->GetKey(keyid, vchSecret)) { throw JSONRPCError(RPC_WALLET_ERROR, "Private key for address " + strAddress + " is not known"); } return CBitcoinSecret(vchSecret).ToString(); @@ -601,7 +652,7 @@ UniValue dumpwallet(const JSONRPCRequest& request) throw std::runtime_error( "dumpwallet \"filename\"\n" "\nDumps all wallet keys in a human-readable format to a server-side file. This does not allow overwriting existing files.\n" - "Imported scripts are not currently included in wallet dumps, these must be backed up separately.\n" + "Imported scripts are included in the dumpfile, but corresponding BIP173 addresses, etc. may not be added automatically by importwallet.\n" "Note that if your wallet contains keys which are not derived from your HD seed (e.g. imported keys), these are not covered by\n" "only backing up the seed itself, and must be backed up too (e.g. ensure you back up the whole dumpfile).\n" "\nArguments:\n" @@ -640,6 +691,9 @@ UniValue dumpwallet(const JSONRPCRequest& request) const std::map<CKeyID, int64_t>& mapKeyPool = pwallet->GetAllReserveKeys(); pwallet->GetKeyBirthTimes(mapKeyBirth); + std::set<CScriptID> scripts = pwallet->GetCScripts(); + // TODO: include scripts in GetKeyBirthTimes() output instead of separate + // sort time/key pairs std::vector<std::pair<int64_t, CKeyID> > vKeyBirth; for (const auto& entry : mapKeyBirth) { @@ -657,7 +711,7 @@ UniValue dumpwallet(const JSONRPCRequest& request) file << strprintf("# mined on %s\n", EncodeDumpTime(chainActive.Tip()->GetBlockTime())); file << "\n"; - // add the base58check encoded extended master if the wallet uses HD + // add the base58check encoded extended master if the wallet uses HD CKeyID masterKeyID = pwallet->GetHDChain().masterKeyID; if (!masterKeyID.IsNull()) { @@ -694,6 +748,21 @@ UniValue dumpwallet(const JSONRPCRequest& request) } } file << "\n"; + for (const CScriptID &scriptid : scripts) { + CScript script; + std::string create_time = "0"; + std::string address = EncodeDestination(scriptid); + // get birth times for scripts with metadata + auto it = pwallet->m_script_metadata.find(scriptid); + if (it != pwallet->m_script_metadata.end()) { + create_time = EncodeDumpTime(it->second.nCreateTime); + } + if(pwallet->GetCScript(scriptid, script)) { + file << strprintf("%s %s script=1", HexStr(script.begin(), script.end()), create_time); + file << strprintf(" # addr=%s\n", address); + } + } + file << "\n"; file << "# End of dump\n"; file.close(); @@ -721,8 +790,8 @@ UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, const int6 const std::string& strRedeemScript = data.exists("redeemscript") ? data["redeemscript"].get_str() : ""; const UniValue& pubKeys = data.exists("pubkeys") ? data["pubkeys"].get_array() : UniValue(); const UniValue& keys = data.exists("keys") ? data["keys"].get_array() : UniValue(); - const bool& internal = data.exists("internal") ? data["internal"].get_bool() : false; - const bool& watchOnly = data.exists("watchonly") ? data["watchonly"].get_bool() : false; + const bool internal = data.exists("internal") ? data["internal"].get_bool() : false; + const bool watchOnly = data.exists("watchonly") ? data["watchonly"].get_bool() : false; const std::string& label = data.exists("label") && !internal ? data["label"].get_str() : ""; bool isScript = scriptPubKey.getType() == UniValue::VSTR; @@ -1067,6 +1136,8 @@ UniValue importmulti(const JSONRPCRequest& mainRequest) " {\n" " \"rescan\": <false>, (boolean, optional, default: true) Stating if should rescan the blockchain after all imports\n" " }\n" + "\nNote: This call can take minutes to complete if rescan is true, during that time, other rpc calls\n" + "may report that the imported keys, addresses or scripts exists but related transactions are still missing.\n" "\nExamples:\n" + HelpExampleCli("importmulti", "'[{ \"scriptPubKey\": { \"address\": \"<my address>\" }, \"timestamp\":1455191478 }, " "{ \"scriptPubKey\": { \"address\": \"<my 2nd address>\" }, \"label\": \"example 2\", \"timestamp\": 1455191480 }]'") + @@ -1092,49 +1163,55 @@ UniValue importmulti(const JSONRPCRequest& mainRequest) } } - LOCK2(cs_main, pwallet->cs_wallet); - EnsureWalletIsUnlocked(pwallet); - - // Verify all timestamps are present before importing any keys. - const int64_t now = chainActive.Tip() ? chainActive.Tip()->GetMedianTimePast() : 0; - for (const UniValue& data : requests.getValues()) { - GetImportTimestamp(data, now); + WalletRescanReserver reserver(pwallet); + if (fRescan && !reserver.reserve()) { + throw JSONRPCError(RPC_WALLET_ERROR, "Wallet is currently rescanning. Abort existing rescan or wait."); } + int64_t now = 0; bool fRunScan = false; - const int64_t minimumTimestamp = 1; int64_t nLowestTimestamp = 0; - - if (fRescan && chainActive.Tip()) { - nLowestTimestamp = chainActive.Tip()->GetBlockTime(); - } else { - fRescan = false; - } - UniValue response(UniValue::VARR); + { + LOCK2(cs_main, pwallet->cs_wallet); + EnsureWalletIsUnlocked(pwallet); - for (const UniValue& data : requests.getValues()) { - const int64_t timestamp = std::max(GetImportTimestamp(data, now), minimumTimestamp); - const UniValue result = ProcessImport(pwallet, data, timestamp); - response.push_back(result); - - if (!fRescan) { - continue; + // Verify all timestamps are present before importing any keys. + now = chainActive.Tip() ? chainActive.Tip()->GetMedianTimePast() : 0; + for (const UniValue& data : requests.getValues()) { + GetImportTimestamp(data, now); } - // If at least one request was successful then allow rescan. - if (result["success"].get_bool()) { - fRunScan = true; + const int64_t minimumTimestamp = 1; + + if (fRescan && chainActive.Tip()) { + nLowestTimestamp = chainActive.Tip()->GetBlockTime(); + } else { + fRescan = false; } - // Get the lowest timestamp. - if (timestamp < nLowestTimestamp) { - nLowestTimestamp = timestamp; + for (const UniValue& data : requests.getValues()) { + const int64_t timestamp = std::max(GetImportTimestamp(data, now), minimumTimestamp); + const UniValue result = ProcessImport(pwallet, data, timestamp); + response.push_back(result); + + if (!fRescan) { + continue; + } + + // If at least one request was successful then allow rescan. + if (result["success"].get_bool()) { + fRunScan = true; + } + + // Get the lowest timestamp. + if (timestamp < nLowestTimestamp) { + nLowestTimestamp = timestamp; + } } } - if (fRescan && fRunScan && requests.size()) { - int64_t scannedTime = pwallet->RescanFromTime(nLowestTimestamp, true /* update */); + int64_t scannedTime = pwallet->RescanFromTime(nLowestTimestamp, reserver, true /* update */); pwallet->ReacceptWalletTransactions(); if (scannedTime > nLowestTimestamp) { diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 23559eb350..fcee22a14a 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -18,6 +18,7 @@ #include <rpc/mining.h> #include <rpc/safemode.h> #include <rpc/server.h> +#include <rpc/util.h> #include <script/sign.h> #include <timedata.h> #include <util.h> @@ -26,6 +27,7 @@ #include <wallet/feebumper.h> #include <wallet/wallet.h> #include <wallet/walletdb.h> +#include <wallet/walletutil.h> #include <init.h> // For StartShutdown @@ -135,14 +137,15 @@ UniValue getnewaddress(const JSONRPCRequest& request) return NullUniValue; } - if (request.fHelp || request.params.size() > 1) + if (request.fHelp || request.params.size() > 2) throw std::runtime_error( - "getnewaddress ( \"account\" )\n" + "getnewaddress ( \"account\" \"address_type\" )\n" "\nReturns a new Bitcoin address for receiving payments.\n" "If 'account' is specified (DEPRECATED), it is added to the address book \n" "so payments received with the address will be credited to 'account'.\n" "\nArguments:\n" "1. \"account\" (string, optional) DEPRECATED. The account name for the address to be linked to. If not provided, the default account \"\" is used. It can also be set to the empty string \"\" to represent the default account. The account does not need to exist, it will be created if there is no account by the given name.\n" + "2. \"address_type\" (string, optional) The address type to use. Options are \"legacy\", \"p2sh-segwit\", and \"bech32\". Default is set by -addresstype.\n" "\nResult:\n" "\"address\" (string) The new bitcoin address\n" "\nExamples:\n" @@ -157,6 +160,14 @@ UniValue getnewaddress(const JSONRPCRequest& request) if (!request.params[0].isNull()) strAccount = AccountFromValue(request.params[0]); + OutputType output_type = g_address_type; + if (!request.params[1].isNull()) { + output_type = ParseOutputType(request.params[1].get_str(), g_address_type); + if (output_type == OUTPUT_TYPE_NONE) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Unknown address type '%s'", request.params[1].get_str())); + } + } + if (!pwallet->IsLocked()) { pwallet->TopUpKeyPool(); } @@ -166,22 +177,23 @@ UniValue getnewaddress(const JSONRPCRequest& request) if (!pwallet->GetKeyFromPool(newKey)) { throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first"); } - CKeyID keyID = newKey.GetID(); + pwallet->LearnRelatedScripts(newKey, output_type); + CTxDestination dest = GetDestinationForKey(newKey, output_type); - pwallet->SetAddressBook(keyID, strAccount, "receive"); + pwallet->SetAddressBook(dest, strAccount, "receive"); - return EncodeDestination(keyID); + return EncodeDestination(dest); } -CTxDestination GetAccountAddress(CWallet* const pwallet, std::string strAccount, bool bForceNew=false) +CTxDestination GetAccountDestination(CWallet* const pwallet, std::string strAccount, bool bForceNew=false) { - CPubKey pubKey; - if (!pwallet->GetAccountPubkey(pubKey, strAccount, bForceNew)) { + CTxDestination dest; + if (!pwallet->GetAccountDestination(dest, strAccount, bForceNew)) { throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first"); } - return pubKey.GetID(); + return dest; } UniValue getaccountaddress(const JSONRPCRequest& request) @@ -213,7 +225,7 @@ UniValue getaccountaddress(const JSONRPCRequest& request) UniValue ret(UniValue::VSTR); - ret = EncodeDestination(GetAccountAddress(pwallet, strAccount)); + ret = EncodeDestination(GetAccountDestination(pwallet, strAccount)); return ret; } @@ -225,11 +237,13 @@ UniValue getrawchangeaddress(const JSONRPCRequest& request) return NullUniValue; } - if (request.fHelp || request.params.size() > 0) + if (request.fHelp || request.params.size() > 1) throw std::runtime_error( - "getrawchangeaddress\n" + "getrawchangeaddress ( \"address_type\" )\n" "\nReturns a new Bitcoin address, for receiving change.\n" "This is for use with raw transactions, NOT normal use.\n" + "\nArguments:\n" + "1. \"address_type\" (string, optional) The address type to use. Options are \"legacy\", \"p2sh-segwit\", and \"bech32\". Default is set by -changetype.\n" "\nResult:\n" "\"address\" (string) The address\n" "\nExamples:\n" @@ -243,6 +257,14 @@ UniValue getrawchangeaddress(const JSONRPCRequest& request) pwallet->TopUpKeyPool(); } + OutputType output_type = g_change_type != OUTPUT_TYPE_NONE ? g_change_type : g_address_type; + if (!request.params[0].isNull()) { + output_type = ParseOutputType(request.params[0].get_str(), output_type); + if (output_type == OUTPUT_TYPE_NONE) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Unknown address type '%s'", request.params[0].get_str())); + } + } + CReserveKey reservekey(pwallet); CPubKey vchPubKey; if (!reservekey.GetReservedKey(vchPubKey, true)) @@ -250,9 +272,10 @@ UniValue getrawchangeaddress(const JSONRPCRequest& request) reservekey.KeepKey(); - CKeyID keyID = vchPubKey.GetID(); + pwallet->LearnRelatedScripts(vchPubKey, output_type); + CTxDestination dest = GetDestinationForKey(vchPubKey, output_type); - return EncodeDestination(keyID); + return EncodeDestination(dest); } @@ -291,8 +314,8 @@ UniValue setaccount(const JSONRPCRequest& request) // Detect when changing the account of an address that is the 'unused current key' of another account: if (pwallet->mapAddressBook.count(dest)) { std::string strOldAccount = pwallet->mapAddressBook[dest].name; - if (dest == GetAccountAddress(pwallet, strOldAccount)) { - GetAccountAddress(pwallet, strOldAccount, true); + if (dest == GetAccountDestination(pwallet, strOldAccount)) { + GetAccountDestination(pwallet, strOldAccount, true); } } pwallet->SetAddressBook(dest, strAccount, "receive"); @@ -770,6 +793,8 @@ UniValue getbalance(const JSONRPCRequest& request) throw std::runtime_error( "getbalance ( \"account\" minconf include_watchonly )\n" "\nIf account is not specified, returns the server's total available balance.\n" + "The available balance is what the wallet considers currently spendable, and is\n" + "thus affected by options which limit spendability such as -spendzeroconfchange.\n" "If account is specified (DEPRECATED), returns the balance in the account.\n" "Note that the account \"\" is not the same as leaving the parameter out.\n" "The server total may be different to the balance in the default \"\" account.\n" @@ -1035,7 +1060,7 @@ UniValue sendmany(const JSONRPCRequest& request) "\nSend two amounts to two different addresses, subtract fee from amount:\n" + HelpExampleCli("sendmany", "\"\" \"{\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\\\":0.01,\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\" 1 \"\" \"[\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\\\",\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\"]\"") + "\nAs a json rpc call\n" - + HelpExampleRpc("sendmany", "\"\", \"{\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\\\":0.01,\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\", 6, \"testing\"") + + HelpExampleRpc("sendmany", "\"\", {\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\":0.01,\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\":0.02}, 6, \"testing\"") ); ObserveSafeMode(); @@ -1137,9 +1162,6 @@ UniValue sendmany(const JSONRPCRequest& request) return wtx.GetHash().GetHex(); } -// Defined in rpc/misc.cpp -extern CScript _createmultisig_redeemScript(CWallet * const pwallet, const UniValue& params); - UniValue addmultisigaddress(const JSONRPCRequest& request) { CWallet * const pwallet = GetWalletForJSONRPCRequest(request); @@ -1147,24 +1169,32 @@ UniValue addmultisigaddress(const JSONRPCRequest& request) return NullUniValue; } - if (request.fHelp || request.params.size() < 2 || request.params.size() > 3) - { - std::string msg = "addmultisigaddress nrequired [\"key\",...] ( \"account\" )\n" + if (request.fHelp || request.params.size() < 2 || request.params.size() > 4) { + std::string msg = "addmultisigaddress nrequired [\"key\",...] ( \"account\" \"address_type\" )\n" "\nAdd a nrequired-to-sign multisignature address to the wallet. Requires a new wallet backup.\n" "Each key is a Bitcoin address or hex-encoded public key.\n" + "This functionality is only intended for use with non-watchonly addresses.\n" + "See `importaddress` for watchonly p2sh address support.\n" "If 'account' is specified (DEPRECATED), assign address to that account.\n" "\nArguments:\n" - "1. nrequired (numeric, required) The number of required signatures out of the n keys or addresses.\n" - "2. \"keys\" (string, required) A json array of bitcoin addresses or hex-encoded public keys\n" + "1. nrequired (numeric, required) The number of required signatures out of the n keys or addresses.\n" + "2. \"keys\" (string, required) A json array of bitcoin addresses or hex-encoded public keys\n" " [\n" - " \"address\" (string) bitcoin address or hex-encoded public key\n" + " \"address\" (string) bitcoin address or hex-encoded public key\n" " ...,\n" " ]\n" - "3. \"account\" (string, optional) DEPRECATED. An account to assign the addresses to.\n" + "3. \"account\" (string, optional) DEPRECATED. An account to assign the addresses to.\n" + "4. \"address_type\" (string, optional) The address type to use. Options are \"legacy\", \"p2sh-segwit\", and \"bech32\". Default is set by -addresstype.\n" "\nResult:\n" - "\"address\" (string) A bitcoin address associated with the keys.\n" + "{\n" + " \"address\":\"multisigaddress\", (string) The value of the new multisig address.\n" + " \"redeemScript\":\"script\" (string) The string value of the hex-encoded redemption script.\n" + "}\n" + "\nResult (DEPRECATED. To see this result in v0.16 instead, please start bitcoind with -deprecatedrpc=addmultisigaddress).\n" + " clients should transition to the new output api before upgrading to v0.17.\n" + "\"address\" (string) A bitcoin address associated with the keys.\n" "\nExamples:\n" "\nAdd a multisig address from 2 addresses\n" @@ -1181,13 +1211,42 @@ UniValue addmultisigaddress(const JSONRPCRequest& request) if (!request.params[2].isNull()) strAccount = AccountFromValue(request.params[2]); + int required = request.params[0].get_int(); + + // Get the public keys + const UniValue& keys_or_addrs = request.params[1].get_array(); + std::vector<CPubKey> pubkeys; + for (unsigned int i = 0; i < keys_or_addrs.size(); ++i) { + if (IsHex(keys_or_addrs[i].get_str()) && (keys_or_addrs[i].get_str().length() == 66 || keys_or_addrs[i].get_str().length() == 130)) { + pubkeys.push_back(HexToPubKey(keys_or_addrs[i].get_str())); + } else { + pubkeys.push_back(AddrToPubKey(pwallet, keys_or_addrs[i].get_str())); + } + } + + OutputType output_type = g_address_type; + if (!request.params[3].isNull()) { + output_type = ParseOutputType(request.params[3].get_str(), output_type); + if (output_type == OUTPUT_TYPE_NONE) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Unknown address type '%s'", request.params[3].get_str())); + } + } + // Construct using pay-to-script-hash: - CScript inner = _createmultisig_redeemScript(pwallet, request.params); - CScriptID innerID(inner); + CScript inner = CreateMultisigRedeemscript(required, pubkeys); pwallet->AddCScript(inner); + CTxDestination dest = pwallet->AddAndGetDestinationForScript(inner, output_type); + pwallet->SetAddressBook(dest, strAccount, "send"); - pwallet->SetAddressBook(innerID, strAccount, "send"); - return EncodeDestination(innerID); + // Return old style interface + if (IsDeprecatedRPCEnabled("addmultisigaddress")) { + return EncodeDestination(dest); + } + + UniValue result(UniValue::VOBJ); + result.pushKV("address", EncodeDestination(dest)); + result.pushKV("redeemScript", HexStr(inner.begin(), inner.end())); + return result; } class Witnessifier : public boost::static_visitor<bool> @@ -1203,12 +1262,7 @@ public: if (pwallet) { CScript basescript = GetScriptForDestination(keyID); CScript witscript = GetScriptForWitness(basescript); - SignatureData sigs; - // This check is to make sure that the script we created can actually be solved for and signed by us - // if we were to have the private keys. This is just to make sure that the script is valid and that, - // if found in a transaction, we would still accept and relay that transaction. - if (!ProduceSignature(DummySignatureCreator(pwallet), witscript, sigs) || - !VerifyScript(sigs.scriptSig, witscript, &sigs.scriptWitness, MANDATORY_SCRIPT_VERIFY_FLAGS | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, DummySignatureCreator(pwallet).Checker())) { + if (!IsSolvable(*pwallet, witscript)) { return false; } return ExtractDestination(witscript, result); @@ -1227,12 +1281,7 @@ public: return true; } CScript witscript = GetScriptForWitness(subscript); - SignatureData sigs; - // This check is to make sure that the script we created can actually be solved for and signed by us - // if we were to have the private keys. This is just to make sure that the script is valid and that, - // if found in a transaction, we would still accept and relay that transaction. - if (!ProduceSignature(DummySignatureCreator(pwallet), witscript, sigs) || - !VerifyScript(sigs.scriptSig, witscript, &sigs.scriptWitness, MANDATORY_SCRIPT_VERIFY_FLAGS | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, DummySignatureCreator(pwallet).Checker())) { + if (!IsSolvable(*pwallet, witscript)) { return false; } return ExtractDestination(witscript, result); @@ -1268,7 +1317,8 @@ UniValue addwitnessaddress(const JSONRPCRequest& request) if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) { std::string msg = "addwitnessaddress \"address\" ( p2sh )\n" - "\nAdd a witness address for a script (with pubkey or redeemscript known). Requires a new wallet backup.\n" + "\nDEPRECATED: set the address_type argument of getnewaddress, or option -addresstype=[bech32|p2sh-segwit] instead.\n" + "Add a witness address for a script (with pubkey or redeemscript known). Requires a new wallet backup.\n" "It returns the witness script.\n" "\nArguments:\n" @@ -1282,6 +1332,12 @@ UniValue addwitnessaddress(const JSONRPCRequest& request) throw std::runtime_error(msg); } + if (!IsDeprecatedRPCEnabled("addwitnessaddress")) { + throw JSONRPCError(RPC_METHOD_DEPRECATED, "addwitnessaddress is deprecated and will be fully removed in v0.17. " + "To use addwitnessaddress in v0.16, restart bitcoind with -deprecatedrpc=addwitnessaddress.\n" + "Projects should transition to using the address_type argument of getnewaddress, or option -addresstype=[bech32|p2sh-segwit] instead.\n"); + } + { LOCK(cs_main); if (!IsWitnessEnabled(chainActive.Tip(), Params().GetConsensus()) && !gArgs.GetBoolArg("-walletprematurewitness", false)) { @@ -1316,7 +1372,7 @@ UniValue addwitnessaddress(const JSONRPCRequest& request) throw JSONRPCError(RPC_WALLET_ERROR, "Cannot convert between witness address types"); } } else { - pwallet->AddCScript(witprogram); + pwallet->AddCScript(witprogram); // Implicit for single-key now, but necessary for multisig and for compatibility with older software pwallet->SetAddressBook(w.result, "", "receive"); } @@ -1438,14 +1494,14 @@ UniValue ListReceived(CWallet * const pwallet, const UniValue& params, bool fByA if (fByAccounts) { - for (std::map<std::string, tallyitem>::iterator it = mapAccountTally.begin(); it != mapAccountTally.end(); ++it) + for (const auto& entry : mapAccountTally) { - CAmount nAmount = (*it).second.nAmount; - int nConf = (*it).second.nConf; + CAmount nAmount = entry.second.nAmount; + int nConf = entry.second.nConf; UniValue obj(UniValue::VOBJ); - if((*it).second.fIsWatchonly) + if (entry.second.fIsWatchonly) obj.push_back(Pair("involvesWatchonly", true)); - obj.push_back(Pair("account", (*it).first)); + obj.push_back(Pair("account", entry.first)); obj.push_back(Pair("amount", ValueFromAmount(nAmount))); obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf))); ret.push_back(obj); @@ -2266,7 +2322,8 @@ UniValue walletpassphrase(const JSONRPCRequest& request) "This is needed prior to performing transactions related to private keys such as sending bitcoins\n" "\nArguments:\n" "1. \"passphrase\" (string, required) The wallet passphrase\n" - "2. timeout (numeric, required) The time to keep the decryption key in seconds.\n" + "2. timeout (numeric, required) The time to keep the decryption key in seconds. Limited to at most 1073741824 (2^30) seconds.\n" + " Any value greater than 1073741824 seconds will be set to 1073741824 seconds.\n" "\nNote:\n" "Issuing the walletpassphrase command while the wallet is already unlocked will set a new unlock\n" "time that overrides the old one.\n" @@ -2295,6 +2352,17 @@ UniValue walletpassphrase(const JSONRPCRequest& request) // Alternately, find a way to make request.params[0] mlock()'d to begin with. strWalletPass = request.params[0].get_str().c_str(); + // Get the timeout + int64_t nSleepTime = request.params[1].get_int64(); + // Timeout cannot be negative, otherwise it will relock immediately + if (nSleepTime < 0) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "Timeout cannot be negative."); + } + // Clamp timeout to 2^30 seconds + if (nSleepTime > (int64_t)1 << 30) { + nSleepTime = (int64_t)1 << 30; + } + if (strWalletPass.length() > 0) { if (!pwallet->Unlock(strWalletPass)) { @@ -2308,7 +2376,6 @@ UniValue walletpassphrase(const JSONRPCRequest& request) pwallet->TopUpKeyPool(); - int64_t nSleepTime = request.params[1].get_int64(); pwallet->nRelockTime = GetTime() + nSleepTime; RPCRunLater(strprintf("lockwallet(%s)", pwallet->GetName()), boost::bind(LockWallet, pwallet), nSleepTime); @@ -2979,9 +3046,9 @@ UniValue fundrawtransaction(const JSONRPCRequest& request) return NullUniValue; } - if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) + if (request.fHelp || request.params.size() < 1 || request.params.size() > 3) throw std::runtime_error( - "fundrawtransaction \"hexstring\" ( options )\n" + "fundrawtransaction \"hexstring\" ( options iswitness )\n" "\nAdd inputs to a transaction until it has enough in value to meet its out value.\n" "This will not modify existing inputs, and will add at most one change output to the outputs.\n" "No existing outputs will be modified unless \"subtractFeeFromOutputs\" is specified.\n" @@ -2998,6 +3065,7 @@ UniValue fundrawtransaction(const JSONRPCRequest& request) " {\n" " \"changeAddress\" (string, optional, default pool address) The bitcoin address to receive the change\n" " \"changePosition\" (numeric, optional, default random) The index of the change output\n" + " \"change_type\" (string, optional) The output type to use. Only valid if changeAddress is not specified. Options are \"legacy\", \"p2sh-segwit\", and \"bech32\". Default is set by -changetype.\n" " \"includeWatching\" (boolean, optional, default false) Also select inputs which are watch only\n" " \"lockUnspents\" (boolean, optional, default false) Lock selected unspent outputs\n" " \"feeRate\" (numeric, optional, default not set: makes wallet determine the fee) Set a specific fee rate in " + CURRENCY_UNIT + "/kB\n" @@ -3016,6 +3084,9 @@ UniValue fundrawtransaction(const JSONRPCRequest& request) " \"CONSERVATIVE\"\n" " }\n" " for backward compatibility: passing in a true instead of an object will result in {\"includeWatching\":true}\n" + "3. iswitness (boolean, optional) Whether the transaction hex is a serialized witness transaction \n" + " If iswitness is not present, heuristic tests will be used in decoding\n" + "\nResult:\n" "{\n" " \"hex\": \"value\", (string) The resulting raw transaction (hex-encoded string)\n" @@ -3052,7 +3123,7 @@ UniValue fundrawtransaction(const JSONRPCRequest& request) coinControl.fAllowWatchOnly = request.params[1].get_bool(); } else { - RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VOBJ}); + RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VOBJ, UniValue::VBOOL}); UniValue options = request.params[1]; @@ -3060,6 +3131,7 @@ UniValue fundrawtransaction(const JSONRPCRequest& request) { {"changeAddress", UniValueType(UniValue::VSTR)}, {"changePosition", UniValueType(UniValue::VNUM)}, + {"change_type", UniValueType(UniValue::VSTR)}, {"includeWatching", UniValueType(UniValue::VBOOL)}, {"lockUnspents", UniValueType(UniValue::VBOOL)}, {"reserveChangeKey", UniValueType(UniValue::VBOOL)}, // DEPRECATED (and ignored), should be removed in 0.16 or so. @@ -3084,6 +3156,16 @@ UniValue fundrawtransaction(const JSONRPCRequest& request) if (options.exists("changePosition")) changePosition = options["changePosition"].get_int(); + if (options.exists("change_type")) { + if (options.exists("changeAddress")) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot specify both changeAddress and address_type options"); + } + coinControl.change_type = ParseOutputType(options["change_type"].get_str(), coinControl.change_type); + if (coinControl.change_type == OUTPUT_TYPE_NONE) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Unknown change type '%s'", options["change_type"].get_str())); + } + } + if (options.exists("includeWatching")) coinControl.fAllowWatchOnly = options["includeWatching"].get_bool(); @@ -3121,8 +3203,11 @@ UniValue fundrawtransaction(const JSONRPCRequest& request) // parse hex string from parameter CMutableTransaction tx; - if (!DecodeHexTx(tx, request.params[0].get_str(), true)) + bool try_witness = request.params[2].isNull() ? true : request.params[2].get_bool(); + bool try_no_witness = request.params[2].isNull() ? true : !request.params[2].get_bool(); + if (!DecodeHexTx(tx, request.params[0].get_str(), try_no_witness, try_witness)) { throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed"); + } if (tx.vout.size() == 0) throw JSONRPCError(RPC_INVALID_PARAMETER, "TX must have at least one output"); @@ -3375,30 +3460,41 @@ UniValue rescanblockchain(const JSONRPCRequest& request) ); } - LOCK2(cs_main, pwallet->cs_wallet); + WalletRescanReserver reserver(pwallet); + if (!reserver.reserve()) { + throw JSONRPCError(RPC_WALLET_ERROR, "Wallet is currently rescanning. Abort existing rescan or wait."); + } - CBlockIndex *pindexStart = chainActive.Genesis(); + CBlockIndex *pindexStart = nullptr; CBlockIndex *pindexStop = nullptr; - if (!request.params[0].isNull()) { - pindexStart = chainActive[request.params[0].get_int()]; - if (!pindexStart) { - throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid start_height"); - } - } + CBlockIndex *pChainTip = nullptr; + { + LOCK(cs_main); + pindexStart = chainActive.Genesis(); + pChainTip = chainActive.Tip(); - if (!request.params[1].isNull()) { - pindexStop = chainActive[request.params[1].get_int()]; - if (!pindexStop) { - throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid stop_height"); + if (!request.params[0].isNull()) { + pindexStart = chainActive[request.params[0].get_int()]; + if (!pindexStart) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid start_height"); + } } - else if (pindexStop->nHeight < pindexStart->nHeight) { - throw JSONRPCError(RPC_INVALID_PARAMETER, "stop_height must be greater then start_height"); + + if (!request.params[1].isNull()) { + pindexStop = chainActive[request.params[1].get_int()]; + if (!pindexStop) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid stop_height"); + } + else if (pindexStop->nHeight < pindexStart->nHeight) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "stop_height must be greater then start_height"); + } } } // We can't rescan beyond non-pruned blocks, stop and throw an error if (fPruneMode) { - CBlockIndex *block = pindexStop ? pindexStop : chainActive.Tip(); + LOCK(cs_main); + CBlockIndex *block = pindexStop ? pindexStop : pChainTip; while (block && block->nHeight >= pindexStart->nHeight) { if (!(block->nStatus & BLOCK_HAVE_DATA)) { throw JSONRPCError(RPC_MISC_ERROR, "Can't rescan beyond pruned data. Use RPC call getblockchaininfo to determine your pruned height."); @@ -3407,18 +3503,17 @@ UniValue rescanblockchain(const JSONRPCRequest& request) } } - CBlockIndex *stopBlock = pwallet->ScanForWalletTransactions(pindexStart, pindexStop, true); + CBlockIndex *stopBlock = pwallet->ScanForWalletTransactions(pindexStart, pindexStop, reserver, true); if (!stopBlock) { if (pwallet->IsAbortingRescan()) { throw JSONRPCError(RPC_MISC_ERROR, "Rescan aborted."); } // if we got a nullptr returned, ScanForWalletTransactions did rescan up to the requested stopindex - stopBlock = pindexStop ? pindexStop : chainActive.Tip(); + stopBlock = pindexStop ? pindexStop : pChainTip; } else { throw JSONRPCError(RPC_MISC_ERROR, "Rescan failed. Potentially corrupted data files."); } - UniValue response(UniValue::VOBJ); response.pushKV("start_height", pindexStart->nHeight); response.pushKV("stop_height", stopBlock->nHeight); @@ -3440,12 +3535,12 @@ extern UniValue rescanblockchain(const JSONRPCRequest& request); static const CRPCCommand commands[] = { // category name actor (function) argNames // --------------------- ------------------------ ----------------------- ---------- - { "rawtransactions", "fundrawtransaction", &fundrawtransaction, {"hexstring","options"} }, + { "rawtransactions", "fundrawtransaction", &fundrawtransaction, {"hexstring","options","iswitness"} }, { "hidden", "resendwallettransactions", &resendwallettransactions, {} }, { "wallet", "abandontransaction", &abandontransaction, {"txid"} }, { "wallet", "abortrescan", &abortrescan, {} }, - { "wallet", "addmultisigaddress", &addmultisigaddress, {"nrequired","keys","account"} }, - { "wallet", "addwitnessaddress", &addwitnessaddress, {"address","p2sh"} }, + { "wallet", "addmultisigaddress", &addmultisigaddress, {"nrequired","keys","account","address_type"} }, + { "hidden", "addwitnessaddress", &addwitnessaddress, {"address","p2sh"} }, { "wallet", "backupwallet", &backupwallet, {"destination"} }, { "wallet", "bumpfee", &bumpfee, {"txid", "options"} }, { "wallet", "dumpprivkey", &dumpprivkey, {"address"} }, @@ -3455,8 +3550,8 @@ static const CRPCCommand commands[] = { "wallet", "getaccount", &getaccount, {"address"} }, { "wallet", "getaddressesbyaccount", &getaddressesbyaccount, {"account"} }, { "wallet", "getbalance", &getbalance, {"account","minconf","include_watchonly"} }, - { "wallet", "getnewaddress", &getnewaddress, {"account"} }, - { "wallet", "getrawchangeaddress", &getrawchangeaddress, {} }, + { "wallet", "getnewaddress", &getnewaddress, {"account","address_type"} }, + { "wallet", "getrawchangeaddress", &getrawchangeaddress, {"address_type"} }, { "wallet", "getreceivedbyaccount", &getreceivedbyaccount, {"account","minconf"} }, { "wallet", "getreceivedbyaddress", &getreceivedbyaddress, {"address","minconf"} }, { "wallet", "gettransaction", &gettransaction, {"txid","include_watchonly"} }, diff --git a/src/wallet/rpcwallet.h b/src/wallet/rpcwallet.h index 14e51610d9..77f7b42b23 100644 --- a/src/wallet/rpcwallet.h +++ b/src/wallet/rpcwallet.h @@ -1,4 +1,4 @@ -// Copyright (c) 2016 The Bitcoin Core developers +// Copyright (c) 2016-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/wallet/test/accounting_tests.cpp b/src/wallet/test/accounting_tests.cpp index a9cdc89e6f..cafd69d075 100644 --- a/src/wallet/test/accounting_tests.cpp +++ b/src/wallet/test/accounting_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2016 The Bitcoin Core developers +// Copyright (c) 2012-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -10,18 +10,16 @@ #include <boost/test/unit_test.hpp> -extern CWallet* pwalletMain; - BOOST_FIXTURE_TEST_SUITE(accounting_tests, WalletTestingSetup) static void -GetResults(std::map<CAmount, CAccountingEntry>& results) +GetResults(CWallet *wallet, std::map<CAmount, CAccountingEntry>& results) { std::list<CAccountingEntry> aes; results.clear(); - BOOST_CHECK(pwalletMain->ReorderTransactions() == DB_LOAD_OK); - pwalletMain->ListAccountCreditDebit("", aes); + BOOST_CHECK(wallet->ReorderTransactions() == DB_LOAD_OK); + wallet->ListAccountCreditDebit("", aes); for (CAccountingEntry& ae : aes) { results[ae.nOrderPos] = ae; @@ -54,7 +52,7 @@ BOOST_AUTO_TEST_CASE(acc_orderupgrade) ae.strOtherAccount = "c"; pwalletMain->AddAccountingEntry(ae); - GetResults(results); + GetResults(pwalletMain.get(), results); BOOST_CHECK(pwalletMain->nOrderPosNext == 3); BOOST_CHECK(2 == results.size()); @@ -70,7 +68,7 @@ BOOST_AUTO_TEST_CASE(acc_orderupgrade) ae.nOrderPos = pwalletMain->IncOrderPosNext(); pwalletMain->AddAccountingEntry(ae); - GetResults(results); + GetResults(pwalletMain.get(), results); BOOST_CHECK(results.size() == 3); BOOST_CHECK(pwalletMain->nOrderPosNext == 4); @@ -102,7 +100,7 @@ BOOST_AUTO_TEST_CASE(acc_orderupgrade) vpwtx[2]->nTimeReceived = (unsigned int)1333333329; vpwtx[2]->nOrderPos = -1; - GetResults(results); + GetResults(pwalletMain.get(), results); BOOST_CHECK(results.size() == 3); BOOST_CHECK(pwalletMain->nOrderPosNext == 6); @@ -120,7 +118,7 @@ BOOST_AUTO_TEST_CASE(acc_orderupgrade) ae.nOrderPos = -1; pwalletMain->AddAccountingEntry(ae); - GetResults(results); + GetResults(pwalletMain.get(), results); BOOST_CHECK(results.size() == 4); BOOST_CHECK(pwalletMain->nOrderPosNext == 7); diff --git a/src/wallet/test/crypto_tests.cpp b/src/wallet/test/crypto_tests.cpp index 3ff8c6d224..89b2c4e796 100644 --- a/src/wallet/test/crypto_tests.cpp +++ b/src/wallet/test/crypto_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2016 The Bitcoin Core developers +// Copyright (c) 2014-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/wallet/test/wallet_test_fixture.cpp b/src/wallet/test/wallet_test_fixture.cpp index 995ec640b1..7797f85f07 100644 --- a/src/wallet/test/wallet_test_fixture.cpp +++ b/src/wallet/test/wallet_test_fixture.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2016 The Bitcoin Core developers +// Copyright (c) 2016-2017 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,9 +6,6 @@ #include <rpc/server.h> #include <wallet/db.h> -#include <wallet/wallet.h> - -std::unique_ptr<CWallet> pwalletMain; WalletTestingSetup::WalletTestingSetup(const std::string& chainName): TestingSetup(chainName) @@ -16,6 +13,8 @@ WalletTestingSetup::WalletTestingSetup(const std::string& chainName): bitdb.MakeMock(); bool fFirstRun; + g_address_type = OUTPUT_TYPE_DEFAULT; + g_change_type = OUTPUT_TYPE_DEFAULT; std::unique_ptr<CWalletDBWrapper> dbw(new CWalletDBWrapper(&bitdb, "wallet_test.dat")); pwalletMain = MakeUnique<CWallet>(std::move(dbw)); pwalletMain->LoadWallet(fFirstRun); @@ -27,7 +26,6 @@ WalletTestingSetup::WalletTestingSetup(const std::string& chainName): WalletTestingSetup::~WalletTestingSetup() { UnregisterValidationInterface(pwalletMain.get()); - pwalletMain.reset(); bitdb.Flush(true); bitdb.Reset(); diff --git a/src/wallet/test/wallet_test_fixture.h b/src/wallet/test/wallet_test_fixture.h index a341bc698a..c03aec7f87 100644 --- a/src/wallet/test/wallet_test_fixture.h +++ b/src/wallet/test/wallet_test_fixture.h @@ -1,4 +1,4 @@ -// Copyright (c) 2016 The Bitcoin Core developers +// Copyright (c) 2016-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -7,11 +7,15 @@ #include <test/test_bitcoin.h> +#include <wallet/wallet.h> + /** Testing setup and teardown for wallet. */ struct WalletTestingSetup: public TestingSetup { explicit WalletTestingSetup(const std::string& chainName = CBaseChainParams::MAIN); ~WalletTestingSetup(); + + std::unique_ptr<CWallet> pwalletMain; }; #endif diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp index 7ae1e74dbe..7e0881afd7 100644 --- a/src/wallet/test/wallet_tests.cpp +++ b/src/wallet/test/wallet_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2016 The Bitcoin Core developers +// Copyright (c) 2012-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -19,8 +19,6 @@ #include <boost/test/unit_test.hpp> #include <univalue.h> -extern CWallet* pwalletMain; - extern UniValue importmulti(const JSONRPCRequest& request); extern UniValue dumpwallet(const JSONRPCRequest& request); extern UniValue importwallet(const JSONRPCRequest& request); @@ -372,8 +370,6 @@ static void AddKey(CWallet& wallet, const CKey& key) BOOST_FIXTURE_TEST_CASE(rescan, TestChain100Setup) { - LOCK(cs_main); - // Cap last block file size, and mine new block in a new block file. CBlockIndex* const nullBlock = nullptr; CBlockIndex* oldTip = chainActive.Tip(); @@ -381,12 +377,16 @@ BOOST_FIXTURE_TEST_CASE(rescan, TestChain100Setup) CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey())); CBlockIndex* newTip = chainActive.Tip(); + LOCK(cs_main); + // Verify ScanForWalletTransactions picks up transactions in both the old // and new block files. { CWallet wallet; AddKey(wallet, coinbaseKey); - BOOST_CHECK_EQUAL(nullBlock, wallet.ScanForWalletTransactions(oldTip, nullptr)); + WalletRescanReserver reserver(&wallet); + reserver.reserve(); + BOOST_CHECK_EQUAL(nullBlock, wallet.ScanForWalletTransactions(oldTip, nullptr, reserver)); BOOST_CHECK_EQUAL(wallet.GetImmatureBalance(), 100 * COIN); } @@ -399,7 +399,9 @@ BOOST_FIXTURE_TEST_CASE(rescan, TestChain100Setup) { CWallet wallet; AddKey(wallet, coinbaseKey); - BOOST_CHECK_EQUAL(oldTip, wallet.ScanForWalletTransactions(oldTip, nullptr)); + WalletRescanReserver reserver(&wallet); + reserver.reserve(); + BOOST_CHECK_EQUAL(oldTip, wallet.ScanForWalletTransactions(oldTip, nullptr, reserver)); BOOST_CHECK_EQUAL(wallet.GetImmatureBalance(), 50 * COIN); } @@ -449,8 +451,6 @@ BOOST_FIXTURE_TEST_CASE(rescan, TestChain100Setup) // than or equal to key birthday. BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup) { - LOCK(cs_main); - // Create two blocks with same timestamp to verify that importwallet rescan // will pick up both blocks, not just the first. const int64_t BLOCK_TIME = chainActive.Tip()->GetBlockTimeMax() + 5; @@ -464,6 +464,8 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup) SetMockTime(KEY_TIME); coinbaseTxns.emplace_back(*CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey())).vtx[0]); + LOCK(cs_main); + // Import key into wallet and call dumpwallet to create backup file. { CWallet wallet; @@ -604,11 +606,15 @@ public: { CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey())); ::bitdb.MakeMock(); + g_address_type = OUTPUT_TYPE_DEFAULT; + g_change_type = OUTPUT_TYPE_DEFAULT; wallet.reset(new CWallet(std::unique_ptr<CWalletDBWrapper>(new CWalletDBWrapper(&bitdb, "wallet_test.dat")))); bool firstRun; wallet->LoadWallet(firstRun); AddKey(*wallet, coinbaseKey); - wallet->ScanForWalletTransactions(chainActive.Genesis(), nullptr); + WalletRescanReserver reserver(wallet.get()); + reserver.reserve(); + wallet->ScanForWalletTransactions(chainActive.Genesis(), nullptr, reserver); } ~ListCoinsTestingSetup() @@ -629,10 +635,15 @@ public: BOOST_CHECK(wallet->CreateTransaction({recipient}, wtx, reservekey, fee, changePos, error, dummy)); CValidationState state; BOOST_CHECK(wallet->CommitTransaction(wtx, reservekey, nullptr, state)); + CMutableTransaction blocktx; + { + LOCK(wallet->cs_wallet); + blocktx = CMutableTransaction(*wallet->mapWallet.at(wtx.GetHash()).tx); + } + CreateAndProcessBlock({CMutableTransaction(blocktx)}, GetScriptForRawPubKey(coinbaseKey.GetPubKey())); LOCK(wallet->cs_wallet); auto it = wallet->mapWallet.find(wtx.GetHash()); BOOST_CHECK(it != wallet->mapWallet.end()); - CreateAndProcessBlock({CMutableTransaction(*it->second.tx)}, GetScriptForRawPubKey(coinbaseKey.GetPubKey())); it->second.SetMerkleBranch(chainActive.Tip(), 1); return it->second; } @@ -643,7 +654,6 @@ public: BOOST_FIXTURE_TEST_CASE(ListCoins, ListCoinsTestingSetup) { std::string coinbaseAddress = coinbaseKey.GetPubKey().GetID().ToString(); - LOCK2(cs_main, wallet->cs_wallet); // Confirm ListCoins initially returns 1 coin grouped under coinbaseKey // address. @@ -671,6 +681,7 @@ BOOST_FIXTURE_TEST_CASE(ListCoins, ListCoinsTestingSetup) BOOST_CHECK_EQUAL(available.size(), 2); for (const auto& group : list) { for (const auto& coin : group.second) { + LOCK(wallet->cs_wallet); wallet->LockCoin(COutPoint(coin.tx->GetHash(), coin.i)); } } diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index edc1ca6ef8..07a23ce249 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -23,12 +23,10 @@ #include <primitives/block.h> #include <primitives/transaction.h> #include <script/script.h> -#include <script/sign.h> #include <scheduler.h> #include <timedata.h> #include <txmempool.h> #include <util.h> -#include <ui_interface.h> #include <utilmoneystr.h> #include <wallet/fees.h> @@ -44,6 +42,8 @@ CFeeRate payTxFee(DEFAULT_TRANSACTION_FEE); unsigned int nTxConfirmTarget = DEFAULT_TX_CONFIRM_TARGET; bool bSpendZeroConfChange = DEFAULT_SPEND_ZEROCONF_CHANGE; bool fWalletRbf = DEFAULT_WALLET_RBF; +OutputType g_address_type = OUTPUT_TYPE_NONE; +OutputType g_change_type = OUTPUT_TYPE_NONE; const char * DEFAULT_WALLET_DAT = "wallet.dat"; const uint32_t BIP32_HARDENED_KEY_LIMIT = 0x80000000; @@ -284,7 +284,7 @@ bool CWallet::AddCryptedKey(const CPubKey &vchPubKey, } } -bool CWallet::LoadKeyMetadata(const CTxDestination& keyID, const CKeyMetadata &meta) +bool CWallet::LoadKeyMetadata(const CKeyID& keyID, const CKeyMetadata &meta) { AssertLockHeld(cs_wallet); // mapKeyMetadata UpdateTimeFirstKey(meta.nCreateTime); @@ -292,6 +292,14 @@ bool CWallet::LoadKeyMetadata(const CTxDestination& keyID, const CKeyMetadata &m return true; } +bool CWallet::LoadScriptMetadata(const CScriptID& script_id, const CKeyMetadata &meta) +{ + AssertLockHeld(cs_wallet); // m_script_metadata + UpdateTimeFirstKey(meta.nCreateTime); + m_script_metadata[script_id] = meta; + return true; +} + bool CWallet::LoadCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret) { return CCryptoKeyStore::AddCryptedKey(vchPubKey, vchCryptedSecret); @@ -340,7 +348,7 @@ bool CWallet::AddWatchOnly(const CScript& dest) { if (!CCryptoKeyStore::AddWatchOnly(dest)) return false; - const CKeyMetadata& meta = mapKeyMetadata[CScriptID(dest)]; + const CKeyMetadata& meta = m_script_metadata[CScriptID(dest)]; UpdateTimeFirstKey(meta.nCreateTime); NotifyWatchonlyChanged(true); return CWalletDB(*dbw).WriteWatchOnly(dest, meta); @@ -348,7 +356,7 @@ bool CWallet::AddWatchOnly(const CScript& dest) bool CWallet::AddWatchOnly(const CScript& dest, int64_t nCreateTime) { - mapKeyMetadata[CScriptID(dest)].nCreateTime = nCreateTime; + m_script_metadata[CScriptID(dest)].nCreateTime = nCreateTime; return AddWatchOnly(dest); } @@ -705,9 +713,9 @@ DBErrors CWallet::ReorderTransactions() typedef std::multimap<int64_t, TxPair > TxItems; TxItems txByTime; - for (std::map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) + for (auto& entry : mapWallet) { - CWalletTx* wtx = &((*it).second); + CWalletTx* wtx = &entry.second; txByTime.insert(std::make_pair(wtx->nTimeReceived, TxPair(wtx, nullptr))); } std::list<CAccountingEntry> acentries; @@ -815,7 +823,7 @@ bool CWallet::AccountMove(std::string strFrom, std::string strTo, CAmount nAmoun return true; } -bool CWallet::GetAccountPubkey(CPubKey &pubKey, std::string strAccount, bool bForceNew) +bool CWallet::GetAccountDestination(CTxDestination &dest, std::string strAccount, bool bForceNew) { CWalletDB walletdb(*dbw); @@ -826,8 +834,8 @@ bool CWallet::GetAccountPubkey(CPubKey &pubKey, std::string strAccount, bool bFo if (!account.vchPubKey.IsValid()) bForceNew = true; else { - // Check if the current key has been used - CScript scriptPubKey = GetScriptForDestination(account.vchPubKey.GetID()); + // Check if the current key has been used (TODO: check other addresses with the same key) + CScript scriptPubKey = GetScriptForDestination(GetDestinationForKey(account.vchPubKey, g_address_type)); for (std::map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end() && account.vchPubKey.IsValid(); ++it) @@ -844,12 +852,14 @@ bool CWallet::GetAccountPubkey(CPubKey &pubKey, std::string strAccount, bool bFo if (!GetKeyFromPool(account.vchPubKey, false)) return false; - SetAddressBook(account.vchPubKey.GetID(), strAccount, "receive"); + LearnRelatedScripts(account.vchPubKey, g_address_type); + dest = GetDestinationForKey(account.vchPubKey, g_address_type); + SetAddressBook(dest, strAccount, "receive"); walletdb.WriteAccount(strAccount, account); + } else { + dest = GetDestinationForKey(account.vchPubKey, g_address_type); } - pubKey = account.vchPubKey; - return true; } @@ -1286,12 +1296,7 @@ void CWallet::BlockUntilSyncedToCurrentChain() { // ...otherwise put a callback in the validation interface queue and wait // for the queue to drain enough to execute it (indicating we are caught up // at least with the time we entered this function). - - std::promise<void> promise; - CallFunctionInValidationInterfaceQueue([&promise] { - promise.set_value(); - }); - promise.get_future().wait(); + SyncWithValidationInterfaceQueue(); } @@ -1607,19 +1612,20 @@ void CWalletTx::GetAmounts(std::list<COutputEntry>& listReceived, * @return Earliest timestamp that could be successfully scanned from. Timestamp * returned will be higher than startTime if relevant blocks could not be read. */ -int64_t CWallet::RescanFromTime(int64_t startTime, bool update) +int64_t CWallet::RescanFromTime(int64_t startTime, const WalletRescanReserver& reserver, bool update) { - AssertLockHeld(cs_main); - AssertLockHeld(cs_wallet); - // Find starting block. May be null if nCreateTime is greater than the // highest blockchain timestamp, in which case there is nothing that needs // to be scanned. - CBlockIndex* const startBlock = chainActive.FindEarliestAtLeast(startTime - TIMESTAMP_WINDOW); - LogPrintf("%s: Rescanning last %i blocks\n", __func__, startBlock ? chainActive.Height() - startBlock->nHeight + 1 : 0); + CBlockIndex* startBlock = nullptr; + { + LOCK(cs_main); + startBlock = chainActive.FindEarliestAtLeast(startTime - TIMESTAMP_WINDOW); + LogPrintf("%s: Rescanning last %i blocks\n", __func__, startBlock ? chainActive.Height() - startBlock->nHeight + 1 : 0); + } if (startBlock) { - const CBlockIndex* const failedBlock = ScanForWalletTransactions(startBlock, nullptr, update); + const CBlockIndex* const failedBlock = ScanForWalletTransactions(startBlock, nullptr, reserver, update); if (failedBlock) { return failedBlock->GetBlockTimeMax() + TIMESTAMP_WINDOW + 1; } @@ -1638,12 +1644,17 @@ int64_t CWallet::RescanFromTime(int64_t startTime, bool update) * * If pindexStop is not a nullptr, the scan will stop at the block-index * defined by pindexStop + * + * Caller needs to make sure pindexStop (and the optional pindexStart) are on + * the main chain after to the addition of any new keys you want to detect + * transactions for. */ -CBlockIndex* CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, CBlockIndex* pindexStop, bool fUpdate) +CBlockIndex* CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, CBlockIndex* pindexStop, const WalletRescanReserver &reserver, bool fUpdate) { int64_t nNow = GetTime(); const CChainParams& chainParams = Params(); + assert(reserver.isReserved()); if (pindexStop) { assert(pindexStop->nHeight >= pindexStart->nHeight); } @@ -1651,24 +1662,42 @@ CBlockIndex* CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, CBlock CBlockIndex* pindex = pindexStart; CBlockIndex* ret = nullptr; { - LOCK2(cs_main, cs_wallet); fAbortRescan = false; - fScanningWallet = true; - ShowProgress(_("Rescanning..."), 0); // show rescan progress in GUI as dialog or on splashscreen, if -rescan on startup - double dProgressStart = GuessVerificationProgress(chainParams.TxData(), pindex); - double dProgressTip = GuessVerificationProgress(chainParams.TxData(), chainActive.Tip()); + CBlockIndex* tip = nullptr; + double dProgressStart; + double dProgressTip; + { + LOCK(cs_main); + tip = chainActive.Tip(); + dProgressStart = GuessVerificationProgress(chainParams.TxData(), pindex); + dProgressTip = GuessVerificationProgress(chainParams.TxData(), tip); + } while (pindex && !fAbortRescan) { - if (pindex->nHeight % 100 == 0 && dProgressTip - dProgressStart > 0.0) - ShowProgress(_("Rescanning..."), std::max(1, std::min(99, (int)((GuessVerificationProgress(chainParams.TxData(), pindex) - dProgressStart) / (dProgressTip - dProgressStart) * 100)))); + if (pindex->nHeight % 100 == 0 && dProgressTip - dProgressStart > 0.0) { + double gvp = 0; + { + LOCK(cs_main); + gvp = GuessVerificationProgress(chainParams.TxData(), pindex); + } + ShowProgress(_("Rescanning..."), std::max(1, std::min(99, (int)((gvp - dProgressStart) / (dProgressTip - dProgressStart) * 100)))); + } if (GetTime() >= nNow + 60) { nNow = GetTime(); + LOCK(cs_main); LogPrintf("Still rescanning. At block %d. Progress=%f\n", pindex->nHeight, GuessVerificationProgress(chainParams.TxData(), pindex)); } CBlock block; if (ReadBlockFromDisk(block, pindex, Params().GetConsensus())) { + LOCK2(cs_main, cs_wallet); + if (pindex && !chainActive.Contains(pindex)) { + // Abort scan if current block is no longer active, to prevent + // marking transactions as coming from the wrong block. + ret = pindex; + break; + } for (size_t posInBlock = 0; posInBlock < block.vtx.size(); ++posInBlock) { AddToWalletIfInvolvingMe(block.vtx[posInBlock], pindex, posInBlock, fUpdate); } @@ -1678,14 +1707,20 @@ CBlockIndex* CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, CBlock if (pindex == pindexStop) { break; } - pindex = chainActive.Next(pindex); + { + LOCK(cs_main); + pindex = chainActive.Next(pindex); + if (tip != chainActive.Tip()) { + tip = chainActive.Tip(); + // in case the tip has changed, update progress max + dProgressTip = GuessVerificationProgress(chainParams.TxData(), tip); + } + } } if (pindex && fAbortRescan) { LogPrintf("Rescan aborted at block %d. Progress=%f\n", pindex->nHeight, GuessVerificationProgress(chainParams.TxData(), pindex)); } ShowProgress(_("Rescanning..."), 100); // hide progress dialog in GUI - - fScanningWallet = false; } return ret; } @@ -1713,11 +1748,8 @@ void CWallet::ReacceptWalletTransactions() } // Try to add wallet transactions to memory pool - for (std::pair<const int64_t, CWalletTx*>& item : mapSorted) - { + for (std::pair<const int64_t, CWalletTx*>& item : mapSorted) { CWalletTx& wtx = *(item.second); - - LOCK(mempool.cs); CValidationState state; wtx.AcceptToMemoryPool(maxTxFee, state); } @@ -1865,7 +1897,7 @@ CAmount CWalletTx::GetAvailableCredit(bool fUseCache) const return nCredit; } -CAmount CWalletTx::GetImmatureWatchOnlyCredit(const bool& fUseCache) const +CAmount CWalletTx::GetImmatureWatchOnlyCredit(const bool fUseCache) const { if (IsCoinBase() && GetBlocksToMaturity() > 0 && IsInMainChain()) { @@ -1879,7 +1911,7 @@ CAmount CWalletTx::GetImmatureWatchOnlyCredit(const bool& fUseCache) const return 0; } -CAmount CWalletTx::GetAvailableWatchOnlyCredit(const bool& fUseCache) const +CAmount CWalletTx::GetAvailableWatchOnlyCredit(const bool fUseCache) const { if (pwallet == nullptr) return 0; @@ -2026,9 +2058,9 @@ CAmount CWallet::GetBalance() const CAmount nTotal = 0; { LOCK2(cs_main, cs_wallet); - for (std::map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) + for (const auto& entry : mapWallet) { - const CWalletTx* pcoin = &(*it).second; + const CWalletTx* pcoin = &entry.second; if (pcoin->IsTrusted()) nTotal += pcoin->GetAvailableCredit(); } @@ -2042,9 +2074,9 @@ CAmount CWallet::GetUnconfirmedBalance() const CAmount nTotal = 0; { LOCK2(cs_main, cs_wallet); - for (std::map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) + for (const auto& entry : mapWallet) { - const CWalletTx* pcoin = &(*it).second; + const CWalletTx* pcoin = &entry.second; if (!pcoin->IsTrusted() && pcoin->GetDepthInMainChain() == 0 && pcoin->InMempool()) nTotal += pcoin->GetAvailableCredit(); } @@ -2057,9 +2089,9 @@ CAmount CWallet::GetImmatureBalance() const CAmount nTotal = 0; { LOCK2(cs_main, cs_wallet); - for (std::map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) + for (const auto& entry : mapWallet) { - const CWalletTx* pcoin = &(*it).second; + const CWalletTx* pcoin = &entry.second; nTotal += pcoin->GetImmatureCredit(); } } @@ -2071,9 +2103,9 @@ CAmount CWallet::GetWatchOnlyBalance() const CAmount nTotal = 0; { LOCK2(cs_main, cs_wallet); - for (std::map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) + for (const auto& entry : mapWallet) { - const CWalletTx* pcoin = &(*it).second; + const CWalletTx* pcoin = &entry.second; if (pcoin->IsTrusted()) nTotal += pcoin->GetAvailableWatchOnlyCredit(); } @@ -2087,9 +2119,9 @@ CAmount CWallet::GetUnconfirmedWatchOnlyBalance() const CAmount nTotal = 0; { LOCK2(cs_main, cs_wallet); - for (std::map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) + for (const auto& entry : mapWallet) { - const CWalletTx* pcoin = &(*it).second; + const CWalletTx* pcoin = &entry.second; if (!pcoin->IsTrusted() && pcoin->GetDepthInMainChain() == 0 && pcoin->InMempool()) nTotal += pcoin->GetAvailableWatchOnlyCredit(); } @@ -2102,9 +2134,9 @@ CAmount CWallet::GetImmatureWatchOnlyBalance() const CAmount nTotal = 0; { LOCK2(cs_main, cs_wallet); - for (std::map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) + for (const auto& entry : mapWallet) { - const CWalletTx* pcoin = &(*it).second; + const CWalletTx* pcoin = &entry.second; nTotal += pcoin->GetImmatureWatchOnlyCredit(); } } @@ -2169,7 +2201,7 @@ CAmount CWallet::GetAvailableBalance(const CCoinControl* coinControl) const return balance; } -void CWallet::AvailableCoins(std::vector<COutput> &vCoins, bool fOnlySafe, const CCoinControl *coinControl, const CAmount &nMinimumAmount, const CAmount &nMaximumAmount, const CAmount &nMinimumSumAmount, const uint64_t &nMaximumCount, const int &nMinDepth, const int &nMaxDepth) const +void CWallet::AvailableCoins(std::vector<COutput> &vCoins, bool fOnlySafe, const CCoinControl *coinControl, const CAmount &nMinimumAmount, const CAmount &nMaximumAmount, const CAmount &nMinimumSumAmount, const uint64_t nMaximumCount, const int nMinDepth, const int nMaxDepth) const { vCoins.clear(); @@ -2178,10 +2210,10 @@ void CWallet::AvailableCoins(std::vector<COutput> &vCoins, bool fOnlySafe, const CAmount nTotal = 0; - for (std::map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) + for (const auto& entry : mapWallet) { - const uint256& wtxid = it->first; - const CWalletTx* pcoin = &(*it).second; + const uint256& wtxid = entry.first; + const CWalletTx* pcoin = &entry.second; if (!CheckFinalTx(*pcoin->tx)) continue; @@ -2242,10 +2274,10 @@ void CWallet::AvailableCoins(std::vector<COutput> &vCoins, bool fOnlySafe, const if (pcoin->tx->vout[i].nValue < nMinimumAmount || pcoin->tx->vout[i].nValue > nMaximumAmount) continue; - if (coinControl && coinControl->HasSelected() && !coinControl->fAllowOtherInputs && !coinControl->IsSelected(COutPoint((*it).first, i))) + if (coinControl && coinControl->HasSelected() && !coinControl->fAllowOtherInputs && !coinControl->IsSelected(COutPoint(entry.first, i))) continue; - if (IsLockedCoin((*it).first, i)) + if (IsLockedCoin(entry.first, i)) continue; if (IsSpent(wtxid, i)) @@ -2592,9 +2624,8 @@ bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nC { std::vector<CRecipient> vecSend; - // Turn the txout set into a CRecipient vector - for (size_t idx = 0; idx < tx.vout.size(); idx++) - { + // Turn the txout set into a CRecipient vector. + for (size_t idx = 0; idx < tx.vout.size(); idx++) { const CTxOut& txOut = tx.vout[idx]; CRecipient recipient = {txOut.scriptPubKey, txOut.nValue, setSubtractFeeFromOutputs.count(idx) == 1}; vecSend.push_back(recipient); @@ -2602,8 +2633,13 @@ bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nC coinControl.fAllowOtherInputs = true; - for (const CTxIn& txin : tx.vin) + for (const CTxIn& txin : tx.vin) { coinControl.Select(txin.prevout); + } + + // Acquire the locks to prevent races to the new locked unspents between the + // CreateTransaction call and LockCoin calls (when lockUnspents is true). + LOCK2(cs_main, cs_wallet); CReserveKey reservekey(this); CWalletTx wtx; @@ -2613,34 +2649,59 @@ bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nC if (nChangePosInOut != -1) { tx.vout.insert(tx.vout.begin() + nChangePosInOut, wtx.tx->vout[nChangePosInOut]); - // we don't have the normal Create/Commit cycle, and don't want to risk reusing change, - // so just remove the key from the keypool here. + // We don't have the normal Create/Commit cycle, and don't want to risk + // reusing change, so just remove the key from the keypool here. reservekey.KeepKey(); } - // Copy output sizes from new transaction; they may have had the fee subtracted from them - for (unsigned int idx = 0; idx < tx.vout.size(); idx++) + // Copy output sizes from new transaction; they may have had the fee + // subtracted from them. + for (unsigned int idx = 0; idx < tx.vout.size(); idx++) { tx.vout[idx].nValue = wtx.tx->vout[idx].nValue; + } - // Add new txins (keeping original txin scriptSig/order) - for (const CTxIn& txin : wtx.tx->vin) - { - if (!coinControl.IsSelected(txin.prevout)) - { + // Add new txins while keeping original txin scriptSig/order. + for (const CTxIn& txin : wtx.tx->vin) { + if (!coinControl.IsSelected(txin.prevout)) { tx.vin.push_back(txin); - if (lockUnspents) - { - LOCK2(cs_main, cs_wallet); - LockCoin(txin.prevout); + if (lockUnspents) { + LockCoin(txin.prevout); } } } - return true; } +OutputType CWallet::TransactionChangeType(OutputType change_type, const std::vector<CRecipient>& vecSend) +{ + // If -changetype is specified, always use that change type. + if (change_type != OUTPUT_TYPE_NONE) { + return change_type; + } + + // if g_address_type is legacy, use legacy address as change (even + // if some of the outputs are P2WPKH or P2WSH). + if (g_address_type == OUTPUT_TYPE_LEGACY) { + return OUTPUT_TYPE_LEGACY; + } + + // if any destination is P2WPKH or P2WSH, use P2WPKH for the change + // output. + for (const auto& recipient : vecSend) { + // Check if any destination contains a witness program: + int witnessversion = 0; + std::vector<unsigned char> witnessprogram; + if (recipient.scriptPubKey.IsWitnessProgram(witnessversion, witnessprogram)) { + return OUTPUT_TYPE_BECH32; + } + } + + // else use g_address_type for change + return g_address_type; +} + bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet, int& nChangePosInOut, std::string& strFailReason, const CCoinControl& coin_control, bool sign) { @@ -2736,7 +2797,10 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CWalletT return false; } - scriptChange = GetScriptForDestination(vchPubKey.GetID()); + const OutputType change_type = TransactionChangeType(coin_control.change_type, vecSend); + + LearnRelatedScripts(vchPubKey, change_type); + scriptChange = GetScriptForDestination(GetDestinationForKey(vchPubKey, change_type)); } CTxOut change_prototype_txout(0, scriptChange); size_t change_prototype_size = GetSerializeSize(change_prototype_txout, SER_DISK, 0); @@ -3625,6 +3689,7 @@ void CWallet::MarkReserveKeysAsUsed(int64_t keypool_id) if (walletdb.ReadPool(index, keypool)) { //TODO: This should be unnecessary m_pool_key_to_index.erase(keypool.vchPubKey.GetID()); } + LearnAllRelatedScripts(keypool.vchPubKey); walletdb.ErasePool(index); LogPrintf("keypool index %d removed\n", index); it = setKeyPool->erase(it); @@ -3705,9 +3770,9 @@ void CWallet::GetKeyBirthTimes(std::map<CTxDestination, int64_t> &mapKeyBirth) c // find first block that affects those keys, if there are any left std::vector<CKeyID> vAffected; - for (std::map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); it++) { + for (const auto& entry : mapWallet) { // iterate over all wallet transactions... - const CWalletTx &wtx = (*it).second; + const CWalletTx &wtx = entry.second; BlockMap::const_iterator blit = mapBlockIndex.find(wtx.hashBlock); if (blit != mapBlockIndex.end() && chainActive.Contains(blit->second)) { // ... which are already in a block @@ -3727,8 +3792,8 @@ void CWallet::GetKeyBirthTimes(std::map<CTxDestination, int64_t> &mapKeyBirth) c } // Extract block timestamps for those keys - for (std::map<CKeyID, CBlockIndex*>::const_iterator it = mapKeyFirstBlock.begin(); it != mapKeyFirstBlock.end(); it++) - mapKeyBirth[it->first] = it->second->GetBlockTime() - TIMESTAMP_WINDOW; // block times can be 2h off + for (const auto& entry : mapKeyFirstBlock) + mapKeyBirth[entry.first] = entry.second->GetBlockTime() - TIMESTAMP_WINDOW; // block times can be 2h off } /** @@ -3996,7 +4061,14 @@ CWallet* CWallet::CreateWalletFromFile(const std::string walletFile) } nStart = GetTimeMillis(); - walletInstance->ScanForWalletTransactions(pindexRescan, nullptr, true); + { + WalletRescanReserver reserver(walletInstance); + if (!reserver.reserve()) { + InitError(_("Failed to rescan the wallet during initialization")); + return nullptr; + } + walletInstance->ScanForWalletTransactions(pindexRescan, nullptr, reserver, true); + } LogPrintf(" rescan %15dms\n", GetTimeMillis() - nStart); walletInstance->SetBestChain(chainActive.GetLocator()); walletInstance->dbw->IncrementUpdateCounter(); @@ -4114,6 +4186,11 @@ int CMerkleTx::GetBlocksToMaturity() const bool CWalletTx::AcceptToMemoryPool(const CAmount& nAbsurdFee, CValidationState& state) { + // Quick check to avoid re-setting fInMempool to false + if (mempool.exists(tx->GetHash())) { + return false; + } + // We must set fInMempool here - while it will be re-set to true by the // entered-mempool callback, if we did not there would be a race where a // user could call sendmoney in a loop and hit spurious out of funds errors @@ -4124,3 +4201,106 @@ bool CWalletTx::AcceptToMemoryPool(const CAmount& nAbsurdFee, CValidationState& fInMempool = ret; return ret; } + +static const std::string OUTPUT_TYPE_STRING_LEGACY = "legacy"; +static const std::string OUTPUT_TYPE_STRING_P2SH_SEGWIT = "p2sh-segwit"; +static const std::string OUTPUT_TYPE_STRING_BECH32 = "bech32"; + +OutputType ParseOutputType(const std::string& type, OutputType default_type) +{ + if (type.empty()) { + return default_type; + } else if (type == OUTPUT_TYPE_STRING_LEGACY) { + return OUTPUT_TYPE_LEGACY; + } else if (type == OUTPUT_TYPE_STRING_P2SH_SEGWIT) { + return OUTPUT_TYPE_P2SH_SEGWIT; + } else if (type == OUTPUT_TYPE_STRING_BECH32) { + return OUTPUT_TYPE_BECH32; + } else { + return OUTPUT_TYPE_NONE; + } +} + +const std::string& FormatOutputType(OutputType type) +{ + switch (type) { + case OUTPUT_TYPE_LEGACY: return OUTPUT_TYPE_STRING_LEGACY; + case OUTPUT_TYPE_P2SH_SEGWIT: return OUTPUT_TYPE_STRING_P2SH_SEGWIT; + case OUTPUT_TYPE_BECH32: return OUTPUT_TYPE_STRING_BECH32; + default: assert(false); + } +} + +void CWallet::LearnRelatedScripts(const CPubKey& key, OutputType type) +{ + if (key.IsCompressed() && (type == OUTPUT_TYPE_P2SH_SEGWIT || type == OUTPUT_TYPE_BECH32)) { + CTxDestination witdest = WitnessV0KeyHash(key.GetID()); + CScript witprog = GetScriptForDestination(witdest); + // Make sure the resulting program is solvable. + assert(IsSolvable(*this, witprog)); + AddCScript(witprog); + } +} + +void CWallet::LearnAllRelatedScripts(const CPubKey& key) +{ + // OUTPUT_TYPE_P2SH_SEGWIT always adds all necessary scripts for all types. + LearnRelatedScripts(key, OUTPUT_TYPE_P2SH_SEGWIT); +} + +CTxDestination GetDestinationForKey(const CPubKey& key, OutputType type) +{ + switch (type) { + case OUTPUT_TYPE_LEGACY: return key.GetID(); + case OUTPUT_TYPE_P2SH_SEGWIT: + case OUTPUT_TYPE_BECH32: { + if (!key.IsCompressed()) return key.GetID(); + CTxDestination witdest = WitnessV0KeyHash(key.GetID()); + CScript witprog = GetScriptForDestination(witdest); + if (type == OUTPUT_TYPE_P2SH_SEGWIT) { + return CScriptID(witprog); + } else { + return witdest; + } + } + default: assert(false); + } +} + +std::vector<CTxDestination> GetAllDestinationsForKey(const CPubKey& key) +{ + CKeyID keyid = key.GetID(); + if (key.IsCompressed()) { + CTxDestination segwit = WitnessV0KeyHash(keyid); + CTxDestination p2sh = CScriptID(GetScriptForDestination(segwit)); + return std::vector<CTxDestination>{std::move(keyid), std::move(p2sh), std::move(segwit)}; + } else { + return std::vector<CTxDestination>{std::move(keyid)}; + } +} + +CTxDestination CWallet::AddAndGetDestinationForScript(const CScript& script, OutputType type) +{ + // Note that scripts over 520 bytes are not yet supported. + switch (type) { + case OUTPUT_TYPE_LEGACY: + return CScriptID(script); + case OUTPUT_TYPE_P2SH_SEGWIT: + case OUTPUT_TYPE_BECH32: { + WitnessV0ScriptHash hash; + CSHA256().Write(script.data(), script.size()).Finalize(hash.begin()); + CTxDestination witdest = hash; + CScript witprog = GetScriptForDestination(witdest); + // Check if the resulting program is solvable (i.e. doesn't use an uncompressed key) + if (!IsSolvable(*this, witprog)) return CScriptID(script); + // Add the redeemscript, so that P2WSH and P2SH-P2WSH outputs are recognized as ours. + AddCScript(witprog); + if (type == OUTPUT_TYPE_BECH32) { + return witdest; + } else { + return CScriptID(witprog); + } + } + default: assert(false); + } +} diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 1bd0be7bd0..a4684c2935 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -99,6 +99,19 @@ enum WalletFeature FEATURE_LATEST = FEATURE_COMPRPUBKEY // HD is optional, use FEATURE_COMPRPUBKEY as latest version }; +enum OutputType : int +{ + OUTPUT_TYPE_NONE, + OUTPUT_TYPE_LEGACY, + OUTPUT_TYPE_P2SH_SEGWIT, + OUTPUT_TYPE_BECH32, + + OUTPUT_TYPE_DEFAULT = OUTPUT_TYPE_P2SH_SEGWIT +}; + +extern OutputType g_address_type; +extern OutputType g_change_type; + /** A key pool entry */ class CKeyPool @@ -445,8 +458,8 @@ public: CAmount GetCredit(const isminefilter& filter) const; CAmount GetImmatureCredit(bool fUseCache=true) const; CAmount GetAvailableCredit(bool fUseCache=true) const; - CAmount GetImmatureWatchOnlyCredit(const bool& fUseCache=true) const; - CAmount GetAvailableWatchOnlyCredit(const bool& fUseCache=true) const; + CAmount GetImmatureWatchOnlyCredit(const bool fUseCache=true) const; + CAmount GetAvailableWatchOnlyCredit(const bool fUseCache=true) const; CAmount GetChange() const; void GetAmounts(std::list<COutputEntry>& listReceived, @@ -646,6 +659,7 @@ private: }; +class WalletRescanReserver; //forward declarations for ScanForWalletTransactions/RescanFromTime /** * A CWallet is an extension of a keystore, which also maintains a set of transactions and balances, * and provides the ability to create new transactions. @@ -655,7 +669,10 @@ class CWallet final : public CCryptoKeyStore, public CValidationInterface private: static std::atomic<bool> fFlushScheduled; std::atomic<bool> fAbortRescan; - std::atomic<bool> fScanningWallet; + std::atomic<bool> fScanningWallet; //controlled by WalletRescanReserver + std::mutex mutexScanning; + friend class WalletRescanReserver; + /** * Select a set of coins such that nValueRet >= nTargetValue and at least @@ -761,9 +778,11 @@ public: void LoadKeyPool(int64_t nIndex, const CKeyPool &keypool); - // Map from Key ID (for regular keys) or Script ID (for watch-only keys) to - // key metadata. - std::map<CTxDestination, CKeyMetadata> mapKeyMetadata; + // Map from Key ID to key metadata. + std::map<CKeyID, CKeyMetadata> mapKeyMetadata; + + // Map from Script ID to key metadata (for watch-only keys). + std::map<CScriptID, CKeyMetadata> m_script_metadata; typedef std::map<unsigned int, CMasterKey> MasterKeyMap; MasterKeyMap mapMasterKeys; @@ -828,7 +847,7 @@ public: /** * populate vCoins with vector of available COutputs. */ - void AvailableCoins(std::vector<COutput>& vCoins, bool fOnlySafe=true, const CCoinControl *coinControl = nullptr, const CAmount& nMinimumAmount = 1, const CAmount& nMaximumAmount = MAX_MONEY, const CAmount& nMinimumSumAmount = MAX_MONEY, const uint64_t& nMaximumCount = 0, const int& nMinDepth = 0, const int& nMaxDepth = 9999999) const; + void AvailableCoins(std::vector<COutput>& vCoins, bool fOnlySafe=true, const CCoinControl *coinControl = nullptr, const CAmount& nMinimumAmount = 1, const CAmount& nMaximumAmount = MAX_MONEY, const CAmount& nMinimumSumAmount = MAX_MONEY, const uint64_t nMaximumCount = 0, const int nMinDepth = 0, const int nMaxDepth = 9999999) const; /** * Return list of available coins and locked coins grouped by non-change output address. @@ -874,7 +893,8 @@ public: //! Adds a key to the store, without saving it to disk (used by LoadWallet) bool LoadKey(const CKey& key, const CPubKey &pubkey) { return CCryptoKeyStore::AddKeyPubKey(key, pubkey); } //! Load metadata (used by LoadWallet) - bool LoadKeyMetadata(const CTxDestination& pubKey, const CKeyMetadata &metadata); + bool LoadKeyMetadata(const CKeyID& keyID, const CKeyMetadata &metadata); + bool LoadScriptMetadata(const CScriptID& script_id, const CKeyMetadata &metadata); bool LoadMinVersion(int nVersion) { AssertLockHeld(cs_wallet); nWalletVersion = nVersion; nWalletMaxVersion = std::max(nWalletMaxVersion, nVersion); return true; } void UpdateTimeFirstKey(int64_t nCreateTime); @@ -920,7 +940,7 @@ public: int64_t IncOrderPosNext(CWalletDB *pwalletdb = nullptr); 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); + bool GetAccountDestination(CTxDestination &dest, std::string strAccount, bool bForceNew = false); void MarkDirty(); bool AddToWallet(const CWalletTx& wtxIn, bool fFlushOnClose=true); @@ -929,8 +949,8 @@ public: void BlockConnected(const std::shared_ptr<const CBlock>& pblock, const CBlockIndex *pindex, const std::vector<CTransactionRef>& vtxConflicted) override; void BlockDisconnected(const std::shared_ptr<const CBlock>& pblock) override; bool AddToWalletIfInvolvingMe(const CTransactionRef& tx, const CBlockIndex* pIndex, int posInBlock, bool fUpdate); - int64_t RescanFromTime(int64_t startTime, bool update); - CBlockIndex* ScanForWalletTransactions(CBlockIndex* pindexStart, CBlockIndex* pindexStop, bool fUpdate = false); + int64_t RescanFromTime(int64_t startTime, const WalletRescanReserver& reserver, bool update); + CBlockIndex* ScanForWalletTransactions(CBlockIndex* pindexStart, CBlockIndex* pindexStop, const WalletRescanReserver& reserver, bool fUpdate = false); void TransactionRemovedFromMempool(const CTransactionRef &ptx) override; void ReacceptWalletTransactions(); void ResendWalletTransactions(int64_t nBestBlockTime, CConnman* connman) override; @@ -945,6 +965,8 @@ public: CAmount GetLegacyBalance(const isminefilter& filter, int minDepth, const std::string* account) const; CAmount GetAvailableBalance(const CCoinControl* coinControl = nullptr) const; + OutputType TransactionChangeType(OutputType change_type, const std::vector<CRecipient>& vecSend); + /** * Insert additional inputs into the transaction by * calling CreateTransaction(); @@ -1126,6 +1148,26 @@ public: * deadlock */ void BlockUntilSyncedToCurrentChain(); + + /** + * Explicitly make the wallet learn the related scripts for outputs to the + * given key. This is purely to make the wallet file compatible with older + * software, as CBasicKeyStore automatically does this implicitly for all + * keys now. + */ + void LearnRelatedScripts(const CPubKey& key, OutputType); + + /** + * Same as LearnRelatedScripts, but when the OutputType is not known (and could + * be anything). + */ + void LearnAllRelatedScripts(const CPubKey& key); + + /** + * Get a destination of the requested type (if possible) to the specified script. + * This function will automatically add the necessary scripts to the wallet. + */ + CTxDestination AddAndGetDestinationForScript(const CScript& script, OutputType); }; /** A key allocated from the key pool. */ @@ -1215,4 +1257,51 @@ bool CWallet::DummySignTx(CMutableTransaction &txNew, const ContainerType &coins return true; } +OutputType ParseOutputType(const std::string& str, OutputType default_type = OUTPUT_TYPE_DEFAULT); +const std::string& FormatOutputType(OutputType type); + +/** + * Get a destination of the requested type (if possible) to the specified key. + * The caller must make sure LearnRelatedScripts has been called beforehand. + */ +CTxDestination GetDestinationForKey(const CPubKey& key, OutputType); + +/** Get all destinations (potentially) supported by the wallet for the given key. */ +std::vector<CTxDestination> GetAllDestinationsForKey(const CPubKey& key); + +/** RAII object to check and reserve a wallet rescan */ +class WalletRescanReserver +{ +private: + CWalletRef m_wallet; + bool m_could_reserve; +public: + explicit WalletRescanReserver(CWalletRef w) : m_wallet(w), m_could_reserve(false) {} + + bool reserve() + { + assert(!m_could_reserve); + std::lock_guard<std::mutex> lock(m_wallet->mutexScanning); + if (m_wallet->fScanningWallet) { + return false; + } + m_wallet->fScanningWallet = true; + m_could_reserve = true; + return true; + } + + bool isReserved() const + { + return (m_could_reserve && m_wallet->fScanningWallet); + } + + ~WalletRescanReserver() + { + std::lock_guard<std::mutex> lock(m_wallet->mutexScanning); + if (m_could_reserve) { + m_wallet->fScanningWallet = false; + } + } +}; + #endif // BITCOIN_WALLET_WALLET_H diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index 66b8dea4ad..dd6835a06f 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -423,27 +423,23 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, } wss.fIsEncrypted = true; } - else if (strType == "keymeta" || strType == "watchmeta") + else if (strType == "keymeta") { - CTxDestination keyID; - if (strType == "keymeta") - { - CPubKey vchPubKey; - ssKey >> vchPubKey; - keyID = vchPubKey.GetID(); - } - else if (strType == "watchmeta") - { - CScript script; - ssKey >> script; - keyID = CScriptID(script); - } - + CPubKey vchPubKey; + ssKey >> vchPubKey; CKeyMetadata keyMeta; ssValue >> keyMeta; wss.nKeyMeta++; - - pwallet->LoadKeyMetadata(keyID, keyMeta); + pwallet->LoadKeyMetadata(vchPubKey.GetID(), keyMeta); + } + else if (strType == "watchmeta") + { + CScript script; + ssKey >> script; + CKeyMetadata keyMeta; + ssValue >> keyMeta; + wss.nKeyMeta++; + pwallet->LoadScriptMetadata(CScriptID(script), keyMeta); } else if (strType == "defaultkey") { @@ -630,7 +626,6 @@ DBErrors CWalletDB::LoadWallet(CWallet* pwallet) DBErrors CWalletDB::FindWalletTx(std::vector<uint256>& vTxHash, std::vector<CWalletTx>& vWtx) { - bool fNoncriticalErrors = false; DBErrors result = DB_LOAD_OK; try { @@ -685,9 +680,6 @@ DBErrors CWalletDB::FindWalletTx(std::vector<uint256>& vTxHash, std::vector<CWal result = DB_CORRUPT; } - if (fNoncriticalErrors && result == DB_LOAD_OK) - result = DB_NONCRITICAL_ERROR; - return result; } @@ -814,14 +806,14 @@ bool CWalletDB::RecoverKeysOnlyFilter(void *callbackData, CDataStream ssKey, CDa return true; } -bool CWalletDB::VerifyEnvironment(const std::string& walletFile, const fs::path& dataDir, std::string& errorStr) +bool CWalletDB::VerifyEnvironment(const std::string& walletFile, const fs::path& walletDir, std::string& errorStr) { - return CDB::VerifyEnvironment(walletFile, dataDir, errorStr); + return CDB::VerifyEnvironment(walletFile, walletDir, errorStr); } -bool CWalletDB::VerifyDatabaseFile(const std::string& walletFile, const fs::path& dataDir, std::string& warningStr, std::string& errorStr) +bool CWalletDB::VerifyDatabaseFile(const std::string& walletFile, const fs::path& walletDir, std::string& warningStr, std::string& errorStr) { - return CDB::VerifyDatabaseFile(walletFile, dataDir, warningStr, errorStr, CWalletDB::Recover); + return CDB::VerifyDatabaseFile(walletFile, walletDir, warningStr, errorStr, CWalletDB::Recover); } bool CWalletDB::WriteDestData(const std::string &address, const std::string &key, const std::string &value) diff --git a/src/wallet/walletdb.h b/src/wallet/walletdb.h index 0a85fc3bc0..3691cfcb57 100644 --- a/src/wallet/walletdb.h +++ b/src/wallet/walletdb.h @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -226,9 +226,9 @@ public: /* Function to determine if a certain KV/key-type is a key (cryptographical key) type */ static bool IsKeyType(const std::string& strType); /* verifies the database environment */ - static bool VerifyEnvironment(const std::string& walletFile, const fs::path& dataDir, std::string& errorStr); + static bool VerifyEnvironment(const std::string& walletFile, const fs::path& walletDir, std::string& errorStr); /* verifies the database file */ - static bool VerifyDatabaseFile(const std::string& walletFile, const fs::path& dataDir, std::string& warningStr, std::string& errorStr); + static bool VerifyDatabaseFile(const std::string& walletFile, const fs::path& walletDir, std::string& warningStr, std::string& errorStr); //! write the hdchain model (external chain child index counter) bool WriteHDChain(const CHDChain& chain); diff --git a/src/wallet/walletutil.cpp b/src/wallet/walletutil.cpp new file mode 100644 index 0000000000..7c97b668ae --- /dev/null +++ b/src/wallet/walletutil.cpp @@ -0,0 +1,27 @@ +// Copyright (c) 2017 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 <wallet/walletutil.h> + +fs::path GetWalletDir() +{ + fs::path path; + + if (gArgs.IsArgSet("-walletdir")) { + path = gArgs.GetArg("-walletdir", ""); + if (!fs::is_directory(path)) { + // If the path specified doesn't exist, we return the deliberately + // invalid empty string. + path = ""; + } + } else { + path = GetDataDir(); + // If a wallets directory exists, use that, otherwise default to GetDataDir + if (fs::is_directory(path / "wallets")) { + path /= "wallets"; + } + } + + return path; +} diff --git a/src/wallet/walletutil.h b/src/wallet/walletutil.h new file mode 100644 index 0000000000..50ff736402 --- /dev/null +++ b/src/wallet/walletutil.h @@ -0,0 +1,14 @@ +// Copyright (c) 2017 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_WALLET_UTIL_H +#define BITCOIN_WALLET_UTIL_H + +#include <chainparamsbase.h> +#include <util.h> + +//! Get the path of the wallet directory. +fs::path GetWalletDir(); + +#endif // BITCOIN_WALLET_UTIL_H diff --git a/src/warnings.cpp b/src/warnings.cpp index c52a1fdb47..572c766600 100644 --- a/src/warnings.cpp +++ b/src/warnings.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/warnings.h b/src/warnings.h index e8e982c0e3..3d7ac5aab4 100644 --- a/src/warnings.h +++ b/src/warnings.h @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/zmq/zmqabstractnotifier.cpp b/src/zmq/zmqabstractnotifier.cpp index ce5c753eb4..fc1ff6d031 100644 --- a/src/zmq/zmqabstractnotifier.cpp +++ b/src/zmq/zmqabstractnotifier.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2015 The Bitcoin Core developers +// Copyright (c) 2015-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/zmq/zmqabstractnotifier.h b/src/zmq/zmqabstractnotifier.h index 6fbaba2036..7270ae203b 100644 --- a/src/zmq/zmqabstractnotifier.h +++ b/src/zmq/zmqabstractnotifier.h @@ -1,4 +1,4 @@ -// Copyright (c) 2015 The Bitcoin Core developers +// Copyright (c) 2015-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/zmq/zmqconfig.h b/src/zmq/zmqconfig.h index ce8f3e13db..1ba1262a83 100644 --- a/src/zmq/zmqconfig.h +++ b/src/zmq/zmqconfig.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014 The Bitcoin Core developers +// Copyright (c) 2014-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/zmq/zmqnotificationinterface.cpp b/src/zmq/zmqnotificationinterface.cpp index 26587d38a3..68b425fa08 100644 --- a/src/zmq/zmqnotificationinterface.cpp +++ b/src/zmq/zmqnotificationinterface.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2016 The Bitcoin Core developers +// Copyright (c) 2015-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -40,15 +40,15 @@ CZMQNotificationInterface* CZMQNotificationInterface::Create() factories["pubrawblock"] = CZMQAbstractNotifier::Create<CZMQPublishRawBlockNotifier>; factories["pubrawtx"] = CZMQAbstractNotifier::Create<CZMQPublishRawTransactionNotifier>; - for (std::map<std::string, CZMQNotifierFactory>::const_iterator i=factories.begin(); i!=factories.end(); ++i) + for (const auto& entry : factories) { - std::string arg("-zmq" + i->first); + std::string arg("-zmq" + entry.first); if (gArgs.IsArgSet(arg)) { - CZMQNotifierFactory factory = i->second; + CZMQNotifierFactory factory = entry.second; std::string address = gArgs.GetArg(arg, ""); CZMQAbstractNotifier *notifier = factory(); - notifier->SetType(i->first); + notifier->SetType(entry.first); notifier->SetAddress(address); notifiers.push_back(notifier); } diff --git a/src/zmq/zmqnotificationinterface.h b/src/zmq/zmqnotificationinterface.h index 222d31e2ad..dee926ea5e 100644 --- a/src/zmq/zmqnotificationinterface.h +++ b/src/zmq/zmqnotificationinterface.h @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2016 The Bitcoin Core developers +// Copyright (c) 2015-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/zmq/zmqpublishnotifier.cpp b/src/zmq/zmqpublishnotifier.cpp index acccb896c0..8c9acef257 100644 --- a/src/zmq/zmqpublishnotifier.cpp +++ b/src/zmq/zmqpublishnotifier.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2016 The Bitcoin Core developers +// Copyright (c) 2015-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/zmq/zmqpublishnotifier.h b/src/zmq/zmqpublishnotifier.h index 0e9bb23e5b..d53bba9971 100644 --- a/src/zmq/zmqpublishnotifier.h +++ b/src/zmq/zmqpublishnotifier.h @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2016 The Bitcoin Core developers +// Copyright (c) 2015-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/test/README.md b/test/README.md index 868eb667ae..b59c8db4e5 100644 --- a/test/README.md +++ b/test/README.md @@ -8,7 +8,7 @@ There are currently two sets of tests in this directory: - [functional](/test/functional) which test the functionality of bitcoind and bitcoin-qt by interacting with them through the RPC and P2P interfaces. -- [util](test/util) which tests the bitcoin utilities, currently only +- [util](/test/util) which tests the bitcoin utilities, currently only bitcoin-tx. The util tests are run as part of `make check` target. The functional diff --git a/test/functional/README.md b/test/functional/README.md index 2558bd017d..662b4b44d5 100644 --- a/test/functional/README.md +++ b/test/functional/README.md @@ -17,7 +17,7 @@ don't have test cases for. #### Style guidelines -- Where possible, try to adhere to [PEP-8 guidelines]([https://www.python.org/dev/peps/pep-0008/) +- Where possible, try to adhere to [PEP-8 guidelines](https://www.python.org/dev/peps/pep-0008/) - Use a python linter like flake8 before submitting PRs to catch common style nits (eg trailing whitespace, unused imports, etc) - Avoid wildcard imports where possible @@ -27,6 +27,20 @@ don't have test cases for. `set_test_params()`, `add_options()` and `setup_xxxx()` methods at the top of the subclass, then locally-defined helper methods, then the `run_test()` method. +#### Naming guidelines + +- Name the test `<area>_test.py`, where area can be one of the following: + - `feature` for tests for full features that aren't wallet/mining/mempool, eg `feature_rbf.py` + - `interface` for tests for other interfaces (REST, ZMQ, etc), eg `interface_rest.py` + - `mempool` for tests for mempool behaviour, eg `mempool_reorg.py` + - `mining` for tests for mining features, eg `mining_prioritisetransaction.py` + - `p2p` for tests that explicitly test the p2p interface, eg `p2p_disconnect_ban.py` + - `rpc` for tests for individual RPC methods or features, eg `rpc_listtransactions.py` + - `wallet` for tests for wallet features, eg `wallet_keypool.py` +- use an underscore to separate words + - exception: for tests for specific RPCs or command line options which don't include underscores, name the test after the exact RPC or argument name, eg `rpc_decodescript.py`, not `rpc_decode_script.py` +- Don't use the redundant word `test` in the name, eg `interface_zmq.py`, not `interface_zmq_test.py` + #### General test-writing advice - Set `self.num_nodes` to the minimum number of nodes necessary for the test. @@ -63,17 +77,17 @@ wrappers for them, `msg_block`, `msg_tx`, etc). with the bitcoind(s) being tested (using python's asyncore package); the other implements the test logic. -- `NodeConn` is the class used to connect to a bitcoind. If you implement -a callback class that derives from `NodeConnCB` and pass that to the -`NodeConn` object, your code will receive the appropriate callbacks when -events of interest arrive. +- `P2PConnection` is the class used to connect to a bitcoind. `P2PInterface` +contains the higher level logic for processing P2P payloads and connecting to +the Bitcoin Core node application logic. For custom behaviour, subclass the +P2PInterface object and override the callback methods. -- Call `NetworkThread.start()` after all `NodeConn` objects are created to +- Call `network_thread_start()` after all `P2PInterface` objects are created to start the networking thread. (Continue with the test logic in your existing thread.) - Can be used to write tests where specific P2P protocol behavior is tested. -Examples tests are `p2p-accept-block.py`, `p2p-compactblocks.py`. +Examples tests are `p2p_unrequested_blocks.py`, `p2p_compactblocks.py`. #### Comptool @@ -119,7 +133,7 @@ Each `TestInstance` consists of: acceptance is tested against the given outcome. - For examples of tests written in this framework, see - `invalidblockrequest.py` and `p2p-fullblocktest.py`. + `p2p_invalid_block.py` and `feature_block.py`. ### test-framework modules diff --git a/test/functional/create_cache.py b/test/functional/create_cache.py index 7d4d1a529b..9665c50a92 100755 --- a/test/functional/create_cache.py +++ b/test/functional/create_cache.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2016 The Bitcoin Core developers +# Copyright (c) 2016-2017 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Create a blockchain cache. @@ -16,6 +16,7 @@ class CreateCache(BitcoinTestFramework): def set_test_params(self): self.num_nodes = 0 + self.supports_cli = True def setup_network(self): pass diff --git a/test/functional/example_test.py b/test/functional/example_test.py index ba40f33016..12be685ecf 100755 --- a/test/functional/example_test.py +++ b/test/functional/example_test.py @@ -17,11 +17,12 @@ from collections import defaultdict from test_framework.blocktools import (create_block, create_coinbase) from test_framework.mininode import ( CInv, - NetworkThread, - NodeConnCB, + P2PInterface, mininode_lock, msg_block, msg_getdata, + network_thread_join, + network_thread_start, ) from test_framework.test_framework import BitcoinTestFramework from test_framework.util import ( @@ -30,15 +31,15 @@ from test_framework.util import ( wait_until, ) -# NodeConnCB is a class containing callbacks to be executed when a P2P -# message is received from the node-under-test. Subclass NodeConnCB and +# P2PInterface is a class containing callbacks to be executed when a P2P +# message is received from the node-under-test. Subclass P2PInterface and # override the on_*() methods if you need custom behaviour. -class BaseNode(NodeConnCB): +class BaseNode(P2PInterface): def __init__(self): - """Initialize the NodeConnCB + """Initialize the P2PInterface Used to inialize custom properties for the Node that aren't - included by default in the base class. Be aware that the NodeConnCB + included by default in the base class. Be aware that the P2PInterface base class already stores a counter for each P2P message type and the last received message of each type, which should be sufficient for the needs of most tests. @@ -49,14 +50,14 @@ class BaseNode(NodeConnCB): # Stores a dictionary of all blocks received self.block_receive_map = defaultdict(int) - def on_block(self, conn, message): + def on_block(self, message): """Override the standard on_block callback Store the hash of a received block in the dictionary.""" message.block.calc_sha256() self.block_receive_map[message.block.sha256] += 1 - def on_inv(self, conn, message): + def on_inv(self, message): """Override the standard on_inv callback""" pass @@ -131,12 +132,12 @@ class ExampleTest(BitcoinTestFramework): def run_test(self): """Main test logic""" - # Create a P2P connection to one of the nodes + # Create P2P connections to two of the nodes self.nodes[0].add_p2p_connection(BaseNode()) # Start up network handling in another thread. This needs to be called # after the P2P connections have been created. - NetworkThread().start() + network_thread_start() # wait_for_verack ensures that the P2P connection is fully up. self.nodes[0].p2p.wait_for_verack() @@ -174,7 +175,7 @@ class ExampleTest(BitcoinTestFramework): block = create_block(self.tip, create_coinbase(height), self.block_time) block.solve() block_message = msg_block(block) - # Send message is used to send a P2P message to the node over our NodeConn connection + # Send message is used to send a P2P message to the node over our P2PInterface self.nodes[0].p2p.send_message(block_message) self.tip = block.sha256 blocks.append(self.tip) @@ -188,7 +189,14 @@ class ExampleTest(BitcoinTestFramework): connect_nodes(self.nodes[1], 2) self.log.info("Add P2P connection to node2") + # We can't add additional P2P connections once the network thread has started. Disconnect the connection + # to node0, wait for the network thread to terminate, then connect to node2. This is specific to + # the current implementation of the network thread and may be improved in future. + self.nodes[0].disconnect_p2ps() + network_thread_join() + self.nodes[2].add_p2p_connection(BaseNode()) + network_thread_start() self.nodes[2].p2p.wait_for_verack() self.log.info("Wait for node2 reach current tip. Test that it has propagated all the blocks to us") @@ -199,12 +207,12 @@ class ExampleTest(BitcoinTestFramework): self.nodes[2].p2p.send_message(getdata_request) # wait_until() will loop until a predicate condition is met. Use it to test properties of the - # NodeConnCB objects. + # P2PInterface objects. wait_until(lambda: sorted(blocks) == sorted(list(self.nodes[2].p2p.block_receive_map.keys())), timeout=5, lock=mininode_lock) self.log.info("Check that each block was received only once") - # The network thread uses a global lock on data access to the NodeConn objects when sending and receiving - # messages. The test thread should acquire the global lock before accessing any NodeConn data to avoid locking + # The network thread uses a global lock on data access to the P2PConnection objects when sending and receiving + # messages. The test thread should acquire the global lock before accessing any P2PConnection data to avoid locking # and synchronization issues. Note wait_until() acquires this global lock when testing the predicate. with mininode_lock: for block in self.nodes[2].p2p.block_receive_map.values(): diff --git a/test/functional/assumevalid.py b/test/functional/feature_assumevalid.py index 36761d359e..5a09142412 100755 --- a/test/functional/assumevalid.py +++ b/test/functional/feature_assumevalid.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2014-2016 The Bitcoin Core developers +# Copyright (c) 2014-2017 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 logic for skipping signature validation on old blocks. @@ -38,15 +38,16 @@ from test_framework.mininode import (CBlockHeader, CTransaction, CTxIn, CTxOut, - NetworkThread, - NodeConnCB, + network_thread_join, + network_thread_start, + P2PInterface, msg_block, msg_headers) from test_framework.script import (CScript, OP_TRUE) from test_framework.test_framework import BitcoinTestFramework from test_framework.util import assert_equal -class BaseNode(NodeConnCB): +class BaseNode(P2PInterface): def send_header_for_blocks(self, new_blocks): headers_message = msg_headers() headers_message.headers = [CBlockHeader(b) for b in new_blocks] @@ -67,7 +68,7 @@ class AssumeValidTest(BitcoinTestFramework): def send_blocks_until_disconnected(self, p2p_conn): """Keep sending blocks to the node until we're disconnected.""" for i in range(len(self.blocks)): - if not p2p_conn.connection: + if p2p_conn.state != "connected": break try: p2p_conn.send_message(msg_block(self.blocks[i])) @@ -98,7 +99,7 @@ class AssumeValidTest(BitcoinTestFramework): # Connect to node0 p2p0 = self.nodes[0].add_p2p_connection(BaseNode()) - NetworkThread().start() # Start up network handling in another thread + network_thread_start() self.nodes[0].p2p.wait_for_verack() # Build the blockchain @@ -159,13 +160,22 @@ class AssumeValidTest(BitcoinTestFramework): self.block_time += 1 height += 1 + # We're adding new connections so terminate the network thread + self.nodes[0].disconnect_p2ps() + network_thread_join() + # Start node1 and node2 with assumevalid so they accept a block with a bad signature. self.start_node(1, extra_args=["-assumevalid=" + hex(block102.sha256)]) - p2p1 = self.nodes[1].add_p2p_connection(BaseNode()) - p2p1.wait_for_verack() - self.start_node(2, extra_args=["-assumevalid=" + hex(block102.sha256)]) + + p2p0 = self.nodes[0].add_p2p_connection(BaseNode()) + p2p1 = self.nodes[1].add_p2p_connection(BaseNode()) p2p2 = self.nodes[2].add_p2p_connection(BaseNode()) + + network_thread_start() + + p2p0.wait_for_verack() + p2p1.wait_for_verack() p2p2.wait_for_verack() # send header lists to all three nodes diff --git a/test/functional/bip68-sequence.py b/test/functional/feature_bip68_sequence.py index 5f8f21701f..94b13653b9 100755 --- a/test/functional/bip68-sequence.py +++ b/test/functional/feature_bip68_sequence.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2014-2016 The Bitcoin Core developers +# Copyright (c) 2014-2017 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 BIP68 implementation.""" @@ -362,9 +362,10 @@ class BIP68Test(BitcoinTestFramework): block.vtx.extend([tx1, tx2, tx3]) block.hashMerkleRoot = block.calc_merkle_root() block.rehash() + add_witness_commitment(block) block.solve() - self.nodes[0].submitblock(ToHex(block)) + self.nodes[0].submitblock(bytes_to_hex_str(block.serialize(True))) assert_equal(self.nodes[0].getbestblockhash(), block.hash) def activateCSV(self): diff --git a/test/functional/bip9-softforks.py b/test/functional/feature_bip9_softforks.py index 904789301a..ae92e9f07c 100755 --- a/test/functional/bip9-softforks.py +++ b/test/functional/feature_bip9_softforks.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2015-2016 The Bitcoin Core developers +# Copyright (c) 2015-2017 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 BIP 9 soft forks. @@ -22,7 +22,7 @@ import itertools from test_framework.test_framework import ComparisonTestFramework from test_framework.util import * -from test_framework.mininode import CTransaction, NetworkThread +from test_framework.mininode import CTransaction, network_thread_start from test_framework.blocktools import create_coinbase, create_block from test_framework.comptool import TestInstance, TestManager from test_framework.script import CScript, OP_1NEGATE, OP_CHECKSEQUENCEVERIFY, OP_DROP @@ -36,7 +36,7 @@ class BIP9SoftForksTest(ComparisonTestFramework): def run_test(self): self.test = TestManager(self, self.options.tmpdir) self.test.add_all_connections(self.nodes) - NetworkThread().start() # Start up network handling in another thread + network_thread_start() self.test.run() def create_transaction(self, node, coinbase, to_address, amount): @@ -245,8 +245,8 @@ class BIP9SoftForksTest(ComparisonTestFramework): self.setup_chain() self.setup_network() self.test.add_all_connections(self.nodes) - NetworkThread().start() - self.test.test_nodes[0].wait_for_verack() + network_thread_start() + self.test.p2p_connections[0].wait_for_verack() def get_tests(self): for test in itertools.chain( diff --git a/test/functional/p2p-fullblocktest.py b/test/functional/feature_block.py index f19b845a32..fe9bbda14b 100755 --- a/test/functional/p2p-fullblocktest.py +++ b/test/functional/feature_block.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2015-2016 The Bitcoin Core developers +# Copyright (c) 2015-2017 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 block processing. @@ -18,6 +18,7 @@ from test_framework.blocktools import * import time from test_framework.key import CECKey from test_framework.script import * +from test_framework.mininode import network_thread_start import struct class PreviousSpendableOutput(): @@ -35,12 +36,15 @@ class CBrokenBlock(CBlock): self.vtx = copy.deepcopy(base_block.vtx) self.hashMerkleRoot = self.calc_merkle_root() - def serialize(self): + def serialize(self, with_witness=False): r = b"" r += super(CBlock, self).serialize() r += struct.pack("<BQ", 255, len(self.vtx)) for tx in self.vtx: - r += tx.serialize() + if with_witness: + r += tx.serialize_with_witness() + else: + r += tx.serialize_without_witness() return r def normal_serialize(self): @@ -68,7 +72,7 @@ class FullBlockTest(ComparisonTestFramework): def run_test(self): self.test = TestManager(self, self.options.tmpdir) self.test.add_all_connections(self.nodes) - NetworkThread().start() # Start up network handling in another thread + network_thread_start() self.test.run() def add_transactions_to_block(self, block, tx_list): diff --git a/test/functional/bip65-cltv-p2p.py b/test/functional/feature_cltv.py index 3073324798..f62ae31654 100755 --- a/test/functional/bip65-cltv-p2p.py +++ b/test/functional/feature_cltv.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2015-2016 The Bitcoin Core developers +# Copyright (c) 2015-2017 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 BIP65 (CHECKLOCKTIMEVERIFY). @@ -66,9 +66,9 @@ class BIP65Test(BitcoinTestFramework): self.setup_clean_chain = True def run_test(self): - self.nodes[0].add_p2p_connection(NodeConnCB()) + self.nodes[0].add_p2p_connection(P2PInterface()) - NetworkThread().start() # Start up network handling in another thread + network_thread_start() # wait_for_verack ensures that the P2P connection is fully up. self.nodes[0].p2p.wait_for_verack() diff --git a/test/functional/feature_config_args.py b/test/functional/feature_config_args.py new file mode 100755 index 0000000000..61abba8082 --- /dev/null +++ b/test/functional/feature_config_args.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python3 +# Copyright (c) 2017 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 various command line arguments and configuration file parameters.""" + +import os + +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import get_datadir_path + +class ConfArgsTest(BitcoinTestFramework): + def set_test_params(self): + self.setup_clean_chain = True + self.num_nodes = 1 + + def run_test(self): + self.stop_node(0) + # Remove the -datadir argument so it doesn't override the config file + self.nodes[0].args = [arg for arg in self.nodes[0].args if not arg.startswith("-datadir")] + + default_data_dir = get_datadir_path(self.options.tmpdir, 0) + new_data_dir = os.path.join(default_data_dir, 'newdatadir') + new_data_dir_2 = os.path.join(default_data_dir, 'newdatadir2') + + # Check that using -datadir argument on non-existent directory fails + self.nodes[0].datadir = new_data_dir + self.assert_start_raises_init_error(0, ['-datadir='+new_data_dir], 'Error: Specified data directory "' + new_data_dir + '" does not exist.') + + # Check that using non-existent datadir in conf file fails + conf_file = os.path.join(default_data_dir, "bitcoin.conf") + with open(conf_file, 'a', encoding='utf8') as f: + f.write("datadir=" + new_data_dir + "\n") + self.assert_start_raises_init_error(0, ['-conf='+conf_file], 'Error reading configuration file: specified data directory "' + new_data_dir + '" does not exist.') + + # Create the directory and ensure the config file now works + os.mkdir(new_data_dir) + self.start_node(0, ['-conf='+conf_file, '-wallet=w1']) + self.stop_node(0) + assert os.path.isfile(os.path.join(new_data_dir, 'regtest', 'wallets', 'w1')) + + # Ensure command line argument overrides datadir in conf + os.mkdir(new_data_dir_2) + self.nodes[0].datadir = new_data_dir_2 + self.start_node(0, ['-datadir='+new_data_dir_2, '-conf='+conf_file, '-wallet=w2']) + assert os.path.isfile(os.path.join(new_data_dir_2, 'regtest', 'wallets', 'w2')) + +if __name__ == '__main__': + ConfArgsTest().main() diff --git a/test/functional/bip68-112-113-p2p.py b/test/functional/feature_csv_activation.py index 7e6a4f4408..82aa0ff891 100755 --- a/test/functional/bip68-112-113-p2p.py +++ b/test/functional/feature_csv_activation.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2015-2016 The Bitcoin Core developers +# Copyright (c) 2015-2017 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 activation of the first version bits soft fork. @@ -45,7 +45,7 @@ bip112tx_special - test negative argument to OP_CSV from test_framework.test_framework import ComparisonTestFramework from test_framework.util import * -from test_framework.mininode import ToHex, CTransaction, NetworkThread +from test_framework.mininode import ToHex, CTransaction, network_thread_start from test_framework.blocktools import create_coinbase, create_block from test_framework.comptool import TestInstance, TestManager from test_framework.script import * @@ -95,12 +95,12 @@ class BIP68_112_113Test(ComparisonTestFramework): def set_test_params(self): self.num_nodes = 1 self.setup_clean_chain = True - self.extra_args = [['-whitelist=127.0.0.1', '-blockversion=4']] + self.extra_args = [['-whitelist=127.0.0.1', '-blockversion=4', '-addresstype=legacy']] def run_test(self): test = TestManager(self, self.options.tmpdir) test.add_all_connections(self.nodes) - NetworkThread().start() # Start up network handling in another thread + network_thread_start() test.run() def send_generic_input_tx(self, node, coinbases): diff --git a/test/functional/dbcrash.py b/test/functional/feature_dbcrash.py index 24b9765b4e..24b9765b4e 100755 --- a/test/functional/dbcrash.py +++ b/test/functional/feature_dbcrash.py diff --git a/test/functional/bipdersig-p2p.py b/test/functional/feature_dersig.py index e5febde42d..3414571678 100755 --- a/test/functional/bipdersig-p2p.py +++ b/test/functional/feature_dersig.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2015-2016 The Bitcoin Core developers +# Copyright (c) 2015-2017 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 BIP66 (DER SIG). @@ -54,9 +54,9 @@ class BIP66Test(BitcoinTestFramework): self.setup_clean_chain = True def run_test(self): - self.nodes[0].add_p2p_connection(NodeConnCB()) + self.nodes[0].add_p2p_connection(P2PInterface()) - NetworkThread().start() # Start up network handling in another thread + network_thread_start() # wait_for_verack ensures that the P2P connection is fully up. self.nodes[0].p2p.wait_for_verack() diff --git a/test/functional/smartfees.py b/test/functional/feature_fee_estimation.py index 986f4546a8..68453e50f4 100755 --- a/test/functional/smartfees.py +++ b/test/functional/feature_fee_estimation.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2014-2016 The Bitcoin Core developers +# Copyright (c) 2014-2017 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 fee estimation code.""" diff --git a/test/functional/feature_logging.py b/test/functional/feature_logging.py new file mode 100755 index 0000000000..da4e7b0398 --- /dev/null +++ b/test/functional/feature_logging.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python3 +# Copyright (c) 2017 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 debug logging.""" + +import os + +from test_framework.test_framework import BitcoinTestFramework + +class LoggingTest(BitcoinTestFramework): + def set_test_params(self): + self.num_nodes = 1 + self.setup_clean_chain = True + + def run_test(self): + # test default log file name + assert os.path.isfile(os.path.join(self.nodes[0].datadir, "regtest", "debug.log")) + + # test alternative log file name in datadir + self.restart_node(0, ["-debuglogfile=foo.log"]) + assert os.path.isfile(os.path.join(self.nodes[0].datadir, "regtest", "foo.log")) + + # test alternative log file name outside datadir + tempname = os.path.join(self.options.tmpdir, "foo.log") + self.restart_node(0, ["-debuglogfile=%s" % tempname]) + assert os.path.isfile(tempname) + + # check that invalid log (relative) will cause error + invdir = os.path.join(self.nodes[0].datadir, "regtest", "foo") + invalidname = os.path.join("foo", "foo.log") + self.stop_node(0) + self.assert_start_raises_init_error(0, ["-debuglogfile=%s" % (invalidname)], + "Error: Could not open debug log file") + assert not os.path.isfile(os.path.join(invdir, "foo.log")) + + # check that invalid log (relative) works after path exists + self.stop_node(0) + os.mkdir(invdir) + self.start_node(0, ["-debuglogfile=%s" % (invalidname)]) + assert os.path.isfile(os.path.join(invdir, "foo.log")) + + # check that invalid log (absolute) will cause error + self.stop_node(0) + invdir = os.path.join(self.options.tmpdir, "foo") + invalidname = os.path.join(invdir, "foo.log") + self.assert_start_raises_init_error(0, ["-debuglogfile=%s" % invalidname], + "Error: Could not open debug log file") + assert not os.path.isfile(os.path.join(invdir, "foo.log")) + + # check that invalid log (absolute) works after path exists + self.stop_node(0) + os.mkdir(invdir) + self.start_node(0, ["-debuglogfile=%s" % (invalidname)]) + assert os.path.isfile(os.path.join(invdir, "foo.log")) + + +if __name__ == '__main__': + LoggingTest().main() diff --git a/test/functional/maxuploadtarget.py b/test/functional/feature_maxuploadtarget.py index 88e2ff2e16..45336ee801 100755 --- a/test/functional/maxuploadtarget.py +++ b/test/functional/feature_maxuploadtarget.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2015-2016 The Bitcoin Core developers +# Copyright (c) 2015-2017 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 behavior of -maxuploadtarget. @@ -17,15 +17,15 @@ from test_framework.mininode import * from test_framework.test_framework import BitcoinTestFramework from test_framework.util import * -class TestNode(NodeConnCB): +class TestNode(P2PInterface): def __init__(self): super().__init__() self.block_receive_map = defaultdict(int) - def on_inv(self, conn, message): + def on_inv(self, message): pass - def on_block(self, conn, message): + def on_block(self, message): message.block.calc_sha256() self.block_receive_map[message.block.sha256] += 1 @@ -57,7 +57,7 @@ class MaxUploadTest(BitcoinTestFramework): for _ in range(3): p2p_conns.append(self.nodes[0].add_p2p_connection(TestNode())) - NetworkThread().start() # Start up network handling in another thread + network_thread_start() for p2pc in p2p_conns: p2pc.wait_for_verack() @@ -149,7 +149,7 @@ class MaxUploadTest(BitcoinTestFramework): # Reconnect to self.nodes[0] self.nodes[0].add_p2p_connection(TestNode()) - NetworkThread().start() # Start up network handling in another thread + network_thread_start() self.nodes[0].p2p.wait_for_verack() #retrieve 20 blocks which should be enough to break the 1MB limit diff --git a/test/functional/minchainwork.py b/test/functional/feature_minchainwork.py index 35cd7ad141..90a3de0e0d 100755 --- a/test/functional/minchainwork.py +++ b/test/functional/feature_minchainwork.py @@ -18,7 +18,7 @@ only succeeds past a given node once its nMinimumChainWork has been exceeded. import time from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import sync_blocks, connect_nodes, assert_equal +from test_framework.util import connect_nodes, assert_equal # 2 hashes required per regtest block (with no difficulty adjustment) REGTEST_WORK_PER_BLOCK = 2 diff --git a/test/functional/notifications.py b/test/functional/feature_notifications.py index c88972ab91..980bef5fc8 100755 --- a/test/functional/notifications.py +++ b/test/functional/feature_notifications.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2014-2016 The Bitcoin Core developers +# Copyright (c) 2014-2017 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test the -alertnotify, -blocknotify and -walletnotify options.""" diff --git a/test/functional/nulldummy.py b/test/functional/feature_nulldummy.py index 7bc7c168f4..e4f413cc2a 100755 --- a/test/functional/nulldummy.py +++ b/test/functional/feature_nulldummy.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2016 The Bitcoin Core developers +# Copyright (c) 2016-2017 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 NULLDUMMY softfork. @@ -15,7 +15,7 @@ Generate 427 more blocks. from test_framework.test_framework import BitcoinTestFramework from test_framework.util import * -from test_framework.mininode import CTransaction, NetworkThread +from test_framework.mininode import CTransaction, network_thread_start from test_framework.blocktools import create_coinbase, create_block, add_witness_commitment from test_framework.script import CScript from io import BytesIO @@ -42,15 +42,15 @@ class NULLDUMMYTest(BitcoinTestFramework): self.setup_clean_chain = True # This script tests NULLDUMMY activation, which is part of the 'segwit' deployment, so we go through # normal segwit activation here (and don't use the default always-on behaviour). - self.extra_args = [['-whitelist=127.0.0.1', '-walletprematurewitness', '-vbparams=segwit:0:999999999999']] + self.extra_args = [['-whitelist=127.0.0.1', '-walletprematurewitness', '-vbparams=segwit:0:999999999999', '-addresstype=legacy', "-deprecatedrpc=addwitnessaddress"]] def run_test(self): self.address = self.nodes[0].getnewaddress() - self.ms_address = self.nodes[0].addmultisigaddress(1,[self.address]) + self.ms_address = self.nodes[0].addmultisigaddress(1,[self.address])['address'] self.wit_address = self.nodes[0].addwitnessaddress(self.address) - self.wit_ms_address = self.nodes[0].addwitnessaddress(self.ms_address) + self.wit_ms_address = self.nodes[0].addmultisigaddress(1, [self.address], '', 'p2sh-segwit')['address'] - NetworkThread().start() # Start up network handling in another thread + network_thread_start() self.coinbase_blocks = self.nodes[0].generate(2) # Block 2 coinbase_txid = [] for i in self.coinbase_blocks: diff --git a/test/functional/proxy_test.py b/test/functional/feature_proxy.py index 81b99d1bf4..2eb1be47a5 100755 --- a/test/functional/proxy_test.py +++ b/test/functional/feature_proxy.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2015-2016 The Bitcoin Core developers +# Copyright (c) 2015-2017 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 bitcoind with different proxy configuration. diff --git a/test/functional/pruning.py b/test/functional/feature_pruning.py index 0101f61185..49ad7f838c 100755 --- a/test/functional/pruning.py +++ b/test/functional/feature_pruning.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2014-2016 The Bitcoin Core developers +# Copyright (c) 2014-2017 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test the pruning code. diff --git a/test/functional/replace-by-fee.py b/test/functional/feature_rbf.py index 815e964848..6b7ab0f43e 100755 --- a/test/functional/replace-by-fee.py +++ b/test/functional/feature_rbf.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2014-2016 The Bitcoin Core developers +# Copyright (c) 2014-2017 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test the RBF code.""" diff --git a/test/functional/reindex.py b/test/functional/feature_reindex.py index 1f684a1afe..ac67e6e9ba 100755 --- a/test/functional/reindex.py +++ b/test/functional/feature_reindex.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2014-2016 The Bitcoin Core developers +# Copyright (c) 2014-2017 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 running bitcoind with -reindex and -reindex-chainstate options. diff --git a/test/functional/segwit.py b/test/functional/feature_segwit.py index 338fa1bc52..ba6373fa33 100755 --- a/test/functional/segwit.py +++ b/test/functional/feature_segwit.py @@ -1,13 +1,21 @@ #!/usr/bin/env python3 -# Copyright (c) 2016 The Bitcoin Core developers +# Copyright (c) 2016-2017 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test the SegWit changeover logic.""" +from test_framework.address import ( + key_to_p2sh_p2wpkh, + key_to_p2wpkh, + program_to_witness, + script_to_p2sh_p2wsh, + script_to_p2wsh, +) +from test_framework.blocktools import witness_script, send_to_witness from test_framework.test_framework import BitcoinTestFramework from test_framework.util import * from test_framework.mininode import sha256, CTransaction, CTxIn, COutPoint, CTxOut, COIN, ToHex, FromHex -from test_framework.address import script_to_p2sh, key_to_p2pkh, key_to_p2sh_p2wpkh, key_to_p2wpkh, script_to_p2sh_p2wsh, script_to_p2wsh, program_to_witness +from test_framework.address import script_to_p2sh, key_to_p2pkh from test_framework.script import CScript, OP_HASH160, OP_CHECKSIG, OP_0, hash160, OP_EQUAL, OP_DUP, OP_EQUALVERIFY, OP_1, OP_2, OP_CHECKMULTISIG, OP_TRUE from io import BytesIO @@ -16,52 +24,6 @@ NODE_2 = 2 WIT_V0 = 0 WIT_V1 = 1 -# Create a scriptPubKey corresponding to either a P2WPKH output for the -# given pubkey, or a P2WSH output of a 1-of-1 multisig for the given -# pubkey. Returns the hex encoding of the scriptPubKey. -def witness_script(use_p2wsh, pubkey): - if (use_p2wsh == False): - # P2WPKH instead - pubkeyhash = hash160(hex_str_to_bytes(pubkey)) - pkscript = CScript([OP_0, pubkeyhash]) - else: - # 1-of-1 multisig - witness_program = CScript([OP_1, hex_str_to_bytes(pubkey), OP_1, OP_CHECKMULTISIG]) - scripthash = sha256(witness_program) - pkscript = CScript([OP_0, scripthash]) - return bytes_to_hex_str(pkscript) - -# Return a transaction (in hex) that spends the given utxo to a segwit output, -# optionally wrapping the segwit output using P2SH. -def create_witness_tx(node, use_p2wsh, utxo, pubkey, encode_p2sh, amount): - if use_p2wsh: - program = CScript([OP_1, hex_str_to_bytes(pubkey), OP_1, OP_CHECKMULTISIG]) - addr = script_to_p2sh_p2wsh(program) if encode_p2sh else script_to_p2wsh(program) - else: - addr = key_to_p2sh_p2wpkh(pubkey) if encode_p2sh else key_to_p2wpkh(pubkey) - if not encode_p2sh: - assert_equal(node.validateaddress(addr)['scriptPubKey'], witness_script(use_p2wsh, pubkey)) - return node.createrawtransaction([utxo], {addr: amount}) - -# Create a transaction spending a given utxo to a segwit output corresponding -# to the given pubkey: use_p2wsh determines whether to use P2WPKH or P2WSH; -# encode_p2sh determines whether to wrap in P2SH. -# sign=True will have the given node sign the transaction. -# insert_redeem_script will be added to the scriptSig, if given. -def send_to_witness(use_p2wsh, node, utxo, pubkey, encode_p2sh, amount, sign=True, insert_redeem_script=""): - tx_to_witness = create_witness_tx(node, use_p2wsh, utxo, pubkey, encode_p2sh, amount) - if (sign): - signed = node.signrawtransaction(tx_to_witness) - assert("errors" not in signed or len(["errors"]) == 0) - return node.sendrawtransaction(signed["hex"]) - else: - if (insert_redeem_script): - tx = FromHex(CTransaction(), tx_to_witness) - tx.vin[0].scriptSig += CScript([hex_str_to_bytes(insert_redeem_script)]) - tx_to_witness = ToHex(tx) - - return node.sendrawtransaction(tx_to_witness) - def getutxo(txid): utxo = {} utxo["vout"] = 0 @@ -78,9 +40,9 @@ class SegWitTest(BitcoinTestFramework): self.setup_clean_chain = True self.num_nodes = 3 # This test tests SegWit both pre and post-activation, so use the normal BIP9 activation. - self.extra_args = [["-walletprematurewitness", "-rpcserialversion=0", "-vbparams=segwit:0:999999999999"], - ["-blockversion=4", "-promiscuousmempoolflags=517", "-prematurewitness", "-walletprematurewitness", "-rpcserialversion=1", "-vbparams=segwit:0:999999999999"], - ["-blockversion=536870915", "-promiscuousmempoolflags=517", "-prematurewitness", "-walletprematurewitness", "-vbparams=segwit:0:999999999999"]] + self.extra_args = [["-walletprematurewitness", "-rpcserialversion=0", "-vbparams=segwit:0:999999999999", "-addresstype=legacy", "-deprecatedrpc=addwitnessaddress"], + ["-blockversion=4", "-promiscuousmempoolflags=517", "-prematurewitness", "-walletprematurewitness", "-rpcserialversion=1", "-vbparams=segwit:0:999999999999", "-addresstype=legacy", "-deprecatedrpc=addwitnessaddress"], + ["-blockversion=536870915", "-promiscuousmempoolflags=517", "-prematurewitness", "-walletprematurewitness", "-vbparams=segwit:0:999999999999", "-addresstype=legacy", "-deprecatedrpc=addwitnessaddress"]] def setup_network(self): super().setup_network() @@ -133,12 +95,11 @@ class SegWitTest(BitcoinTestFramework): for i in range(3): newaddress = self.nodes[i].getnewaddress() self.pubkey.append(self.nodes[i].validateaddress(newaddress)["pubkey"]) - multiaddress = self.nodes[i].addmultisigaddress(1, [self.pubkey[-1]]) multiscript = CScript([OP_1, hex_str_to_bytes(self.pubkey[-1]), OP_1, OP_CHECKMULTISIG]) - p2sh_addr = self.nodes[i].addwitnessaddress(newaddress, True) + p2sh_addr = self.nodes[i].addwitnessaddress(newaddress) bip173_addr = self.nodes[i].addwitnessaddress(newaddress, False) - p2sh_ms_addr = self.nodes[i].addwitnessaddress(multiaddress, True) - bip173_ms_addr = self.nodes[i].addwitnessaddress(multiaddress, False) + p2sh_ms_addr = self.nodes[i].addmultisigaddress(1, [self.pubkey[-1]], '', 'p2sh-segwit')['address'] + bip173_ms_addr = self.nodes[i].addmultisigaddress(1, [self.pubkey[-1]], '', 'bech32')['address'] assert_equal(p2sh_addr, key_to_p2sh_p2wpkh(self.pubkey[-1])) assert_equal(bip173_addr, key_to_p2wpkh(self.pubkey[-1])) assert_equal(p2sh_ms_addr, script_to_p2sh_p2wsh(multiscript)) @@ -328,19 +289,19 @@ class SegWitTest(BitcoinTestFramework): solvable_anytime = [] # These outputs should be solvable after importpubkey unseen_anytime = [] # These outputs should never be seen - uncompressed_spendable_address.append(self.nodes[0].addmultisigaddress(2, [uncompressed_spendable_address[0], compressed_spendable_address[0]])) - uncompressed_spendable_address.append(self.nodes[0].addmultisigaddress(2, [uncompressed_spendable_address[0], uncompressed_spendable_address[0]])) - compressed_spendable_address.append(self.nodes[0].addmultisigaddress(2, [compressed_spendable_address[0], compressed_spendable_address[0]])) - uncompressed_solvable_address.append(self.nodes[0].addmultisigaddress(2, [compressed_spendable_address[0], uncompressed_solvable_address[0]])) - compressed_solvable_address.append(self.nodes[0].addmultisigaddress(2, [compressed_spendable_address[0], compressed_solvable_address[0]])) - compressed_solvable_address.append(self.nodes[0].addmultisigaddress(2, [compressed_solvable_address[0], compressed_solvable_address[1]])) + uncompressed_spendable_address.append(self.nodes[0].addmultisigaddress(2, [uncompressed_spendable_address[0], compressed_spendable_address[0]])['address']) + uncompressed_spendable_address.append(self.nodes[0].addmultisigaddress(2, [uncompressed_spendable_address[0], uncompressed_spendable_address[0]])['address']) + compressed_spendable_address.append(self.nodes[0].addmultisigaddress(2, [compressed_spendable_address[0], compressed_spendable_address[0]])['address']) + uncompressed_solvable_address.append(self.nodes[0].addmultisigaddress(2, [compressed_spendable_address[0], uncompressed_solvable_address[0]])['address']) + compressed_solvable_address.append(self.nodes[0].addmultisigaddress(2, [compressed_spendable_address[0], compressed_solvable_address[0]])['address']) + compressed_solvable_address.append(self.nodes[0].addmultisigaddress(2, [compressed_solvable_address[0], compressed_solvable_address[1]])['address']) unknown_address = ["mtKKyoHabkk6e4ppT7NaM7THqPUt7AzPrT", "2NDP3jLWAFT8NDAiUa9qiE6oBt2awmMq7Dx"] # Test multisig_without_privkey # We have 2 public keys without private keys, use addmultisigaddress to add to wallet. # Money sent to P2SH of multisig of this should only be seen after importaddress with the BASE58 P2SH address. - multisig_without_privkey_address = self.nodes[0].addmultisigaddress(2, [pubkeys[3], pubkeys[4]]) + multisig_without_privkey_address = self.nodes[0].addmultisigaddress(2, [pubkeys[3], pubkeys[4]])['address'] script = CScript([OP_2, hex_str_to_bytes(pubkeys[3]), hex_str_to_bytes(pubkeys[4]), OP_2, OP_CHECKMULTISIG]) solvable_after_importaddress.append(CScript([OP_HASH160, hash160(script), OP_EQUAL])) @@ -356,8 +317,10 @@ class SegWitTest(BitcoinTestFramework): [p2wpkh, p2sh_p2wpkh, p2pk, p2pkh, p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh] = self.p2pkh_address_to_script(v) # normal P2PKH and P2PK with compressed keys should always be spendable spendable_anytime.extend([p2pkh, p2pk]) - # P2SH_P2PK, P2SH_P2PKH, and witness with compressed keys are spendable after direct importaddress - spendable_after_importaddress.extend([p2wpkh, p2sh_p2wpkh, p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh]) + # P2SH_P2PK, P2SH_P2PKH with compressed keys are spendable after direct importaddress + spendable_after_importaddress.extend([p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh]) + # P2WPKH and P2SH_P2WPKH with compressed keys should always be spendable + spendable_anytime.extend([p2wpkh, p2sh_p2wpkh]) for i in uncompressed_spendable_address: v = self.nodes[0].validateaddress(i) @@ -373,7 +336,7 @@ class SegWitTest(BitcoinTestFramework): spendable_anytime.extend([p2pkh, p2pk]) # P2SH_P2PK and P2SH_P2PKH are spendable after direct importaddress spendable_after_importaddress.extend([p2sh_p2pk, p2sh_p2pkh]) - # witness with uncompressed keys are never seen + # Witness output types with uncompressed keys are never seen unseen_anytime.extend([p2wpkh, p2sh_p2wpkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh]) for i in compressed_solvable_address: @@ -384,10 +347,10 @@ class SegWitTest(BitcoinTestFramework): solvable_after_importaddress.extend([bare, p2sh, p2wsh, p2sh_p2wsh]) else: [p2wpkh, p2sh_p2wpkh, p2pk, p2pkh, p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh] = self.p2pkh_address_to_script(v) - # normal P2PKH and P2PK with compressed keys should always be seen - solvable_anytime.extend([p2pkh, p2pk]) - # P2SH_P2PK, P2SH_P2PKH, and witness with compressed keys are seen after direct importaddress - solvable_after_importaddress.extend([p2wpkh, p2sh_p2wpkh, p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh]) + # normal P2PKH, P2PK, P2WPKH and P2SH_P2WPKH with compressed keys should always be seen + solvable_anytime.extend([p2pkh, p2pk, p2wpkh, p2sh_p2wpkh]) + # P2SH_P2PK, P2SH_P2PKH with compressed keys are seen after direct importaddress + solvable_after_importaddress.extend([p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh]) for i in uncompressed_solvable_address: v = self.nodes[0].validateaddress(i) @@ -403,7 +366,7 @@ class SegWitTest(BitcoinTestFramework): solvable_anytime.extend([p2pkh, p2pk]) # P2SH_P2PK, P2SH_P2PKH with uncompressed keys are seen after direct importaddress solvable_after_importaddress.extend([p2sh_p2pk, p2sh_p2pkh]) - # witness with uncompressed keys are never seen + # Witness output types with uncompressed keys are never seen unseen_anytime.extend([p2wpkh, p2sh_p2wpkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh]) op1 = CScript([OP_1]) @@ -496,12 +459,14 @@ class SegWitTest(BitcoinTestFramework): spendable_after_addwitnessaddress = [] # These outputs should be seen after importaddress solvable_after_addwitnessaddress=[] # These outputs should be seen after importaddress but not spendable unseen_anytime = [] # These outputs should never be seen + solvable_anytime = [] # These outputs should be solvable after importpubkey + unseen_anytime = [] # These outputs should never be seen - uncompressed_spendable_address.append(self.nodes[0].addmultisigaddress(2, [uncompressed_spendable_address[0], compressed_spendable_address[0]])) - uncompressed_spendable_address.append(self.nodes[0].addmultisigaddress(2, [uncompressed_spendable_address[0], uncompressed_spendable_address[0]])) - compressed_spendable_address.append(self.nodes[0].addmultisigaddress(2, [compressed_spendable_address[0], compressed_spendable_address[0]])) - uncompressed_solvable_address.append(self.nodes[0].addmultisigaddress(2, [compressed_solvable_address[0], uncompressed_solvable_address[0]])) - compressed_solvable_address.append(self.nodes[0].addmultisigaddress(2, [compressed_spendable_address[0], compressed_solvable_address[0]])) + uncompressed_spendable_address.append(self.nodes[0].addmultisigaddress(2, [uncompressed_spendable_address[0], compressed_spendable_address[0]])['address']) + uncompressed_spendable_address.append(self.nodes[0].addmultisigaddress(2, [uncompressed_spendable_address[0], uncompressed_spendable_address[0]])['address']) + compressed_spendable_address.append(self.nodes[0].addmultisigaddress(2, [compressed_spendable_address[0], compressed_spendable_address[0]])['address']) + uncompressed_solvable_address.append(self.nodes[0].addmultisigaddress(2, [compressed_solvable_address[0], uncompressed_solvable_address[0]])['address']) + compressed_solvable_address.append(self.nodes[0].addmultisigaddress(2, [compressed_spendable_address[0], compressed_solvable_address[0]])['address']) premature_witaddress = [] @@ -514,9 +479,8 @@ class SegWitTest(BitcoinTestFramework): premature_witaddress.append(script_to_p2sh(p2wsh)) else: [p2wpkh, p2sh_p2wpkh, p2pk, p2pkh, p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh] = self.p2pkh_address_to_script(v) - # P2WPKH, P2SH_P2WPKH are spendable after addwitnessaddress - spendable_after_addwitnessaddress.extend([p2wpkh, p2sh_p2wpkh]) - premature_witaddress.append(script_to_p2sh(p2wpkh)) + # P2WPKH, P2SH_P2WPKH are always spendable + spendable_anytime.extend([p2wpkh, p2sh_p2wpkh]) for i in uncompressed_spendable_address + uncompressed_solvable_address: v = self.nodes[0].validateaddress(i) @@ -538,10 +502,11 @@ class SegWitTest(BitcoinTestFramework): premature_witaddress.append(script_to_p2sh(p2wsh)) else: [p2wpkh, p2sh_p2wpkh, p2pk, p2pkh, p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh] = self.p2pkh_address_to_script(v) - # P2SH_P2PK, P2SH_P2PKH with compressed keys are seen after addwitnessaddress - solvable_after_addwitnessaddress.extend([p2wpkh, p2sh_p2wpkh]) - premature_witaddress.append(script_to_p2sh(p2wpkh)) + # P2SH_P2PK, P2SH_P2PKH with compressed keys are always solvable + solvable_anytime.extend([p2wpkh, p2sh_p2wpkh]) + self.mine_and_test_listunspent(spendable_anytime, 2) + self.mine_and_test_listunspent(solvable_anytime, 1) self.mine_and_test_listunspent(spendable_after_addwitnessaddress + solvable_after_addwitnessaddress + unseen_anytime, 0) # addwitnessaddress should refuse to return a witness address if an uncompressed key is used @@ -558,8 +523,8 @@ class SegWitTest(BitcoinTestFramework): witaddress = self.nodes[0].addwitnessaddress(i) assert_equal(witaddress, self.nodes[0].addwitnessaddress(witaddress)) - spendable_txid.append(self.mine_and_test_listunspent(spendable_after_addwitnessaddress, 2)) - solvable_txid.append(self.mine_and_test_listunspent(solvable_after_addwitnessaddress, 1)) + spendable_txid.append(self.mine_and_test_listunspent(spendable_after_addwitnessaddress + spendable_anytime, 2)) + solvable_txid.append(self.mine_and_test_listunspent(solvable_after_addwitnessaddress + solvable_anytime, 1)) self.mine_and_test_listunspent(unseen_anytime, 0) # Check that createrawtransaction/decoderawtransaction with non-v0 Bech32 works diff --git a/test/functional/uacomment.py b/test/functional/feature_uacomment.py index 0b2c64ab69..0b2c64ab69 100755 --- a/test/functional/uacomment.py +++ b/test/functional/feature_uacomment.py diff --git a/test/functional/feature_versionbits_warning.py b/test/functional/feature_versionbits_warning.py new file mode 100755 index 0000000000..2985569a8f --- /dev/null +++ b/test/functional/feature_versionbits_warning.py @@ -0,0 +1,112 @@ +#!/usr/bin/env python3 +# Copyright (c) 2016-2017 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 version bits warning system. + +Generate chains with block versions that appear to be signalling unknown +soft-forks, and test that warning alerts are generated. +""" +import os +import re + +from test_framework.blocktools import create_block, create_coinbase +from test_framework.messages import msg_block +from test_framework.mininode import P2PInterface, network_thread_start, mininode_lock +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import wait_until + +VB_PERIOD = 144 # versionbits period length for regtest +VB_THRESHOLD = 108 # versionbits activation threshold for regtest +VB_TOP_BITS = 0x20000000 +VB_UNKNOWN_BIT = 27 # Choose a bit unassigned to any deployment +VB_UNKNOWN_VERSION = VB_TOP_BITS | (1 << VB_UNKNOWN_BIT) + +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: unknown new rules activated.*versionbit") + +class VersionBitsWarningTest(BitcoinTestFramework): + def set_test_params(self): + self.setup_clean_chain = True + self.num_nodes = 1 + + def setup_network(self): + 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', encoding='utf8'): + pass + self.extra_args = [["-alertnotify=echo %s >> \"" + self.alert_filename + "\""]] + self.setup_nodes() + + def send_blocks_with_version(self, peer, numblocks, version): + """Send numblocks blocks to peer with version set""" + tip = self.nodes[0].getbestblockhash() + height = self.nodes[0].getblockcount() + block_time = self.nodes[0].getblockheader(tip)["time"] + 1 + tip = int(tip, 16) + + for _ in range(numblocks): + block = create_block(tip, create_coinbase(height + 1), block_time) + block.nVersion = version + block.solve() + peer.send_message(msg_block(block)) + block_time += 1 + height += 1 + tip = block.sha256 + peer.sync_with_ping() + + def versionbits_in_alert_file(self): + """Test that the versionbits warning has been written to the alert file.""" + alert_text = open(self.alert_filename, 'r', encoding='utf8').read() + return VB_PATTERN.search(alert_text) is not None + + def run_test(self): + # Handy alias + node = self.nodes[0] + node.add_p2p_connection(P2PInterface()) + network_thread_start() + node.p2p.wait_for_verack() + + # Mine one period worth of blocks + node.generate(VB_PERIOD) + + self.log.info("Check that there is no warning if previous VB_BLOCKS have <VB_THRESHOLD blocks with unknown versionbits version.") + # Build one period of blocks with < VB_THRESHOLD blocks signaling some unknown bit + self.send_blocks_with_version(node.p2p, VB_THRESHOLD - 1, VB_UNKNOWN_VERSION) + node.generate(VB_PERIOD - VB_THRESHOLD + 1) + + # Check that we're not getting any versionbit-related errors in get*info() + assert(not VB_PATTERN.match(node.getmininginfo()["warnings"])) + assert(not VB_PATTERN.match(node.getnetworkinfo()["warnings"])) + + self.log.info("Check that there is a warning if >50 blocks in the last 100 were an unknown version") + # Build one period of blocks with VB_THRESHOLD blocks signaling some unknown bit + self.send_blocks_with_version(node.p2p, VB_THRESHOLD, VB_UNKNOWN_VERSION) + node.generate(VB_PERIOD - VB_THRESHOLD) + + # Check that get*info() shows the 51/100 unknown block version error. + assert(WARN_UNKNOWN_RULES_MINED in node.getmininginfo()["warnings"]) + assert(WARN_UNKNOWN_RULES_MINED in node.getnetworkinfo()["warnings"]) + + self.log.info("Check that there is a warning if previous VB_BLOCKS have >=VB_THRESHOLD blocks with unknown versionbits version.") + # Mine a period worth of expected blocks so the generic block-version warning + # is cleared. This will move the versionbit state to ACTIVE. + node.generate(VB_PERIOD) + + # Stop-start the node. This is required because bitcoind will only warn once about unknown versions or unknown rules activating. + self.restart_node(0) + + # Generating one block guarantees that we'll get out of IBD + node.generate(1) + wait_until(lambda: not node.getblockchaininfo()['initialblockdownload'], timeout=10, lock=mininode_lock) + # Generating one more block will be enough to generate an error. + node.generate(1) + # Check that get*info() shows the versionbits unknown rules warning + assert(WARN_UNKNOWN_RULES_ACTIVE in node.getmininginfo()["warnings"]) + assert(WARN_UNKNOWN_RULES_ACTIVE in node.getnetworkinfo()["warnings"]) + # Check that the alert file shows the versionbits unknown rules warning + wait_until(lambda: self.versionbits_in_alert_file(), timeout=60) + +if __name__ == '__main__': + VersionBitsWarningTest().main() diff --git a/test/functional/bitcoin_cli.py b/test/functional/interface_bitcoin_cli.py index 996cbb8a12..d8c80ab34f 100755 --- a/test/functional/bitcoin_cli.py +++ b/test/functional/interface_bitcoin_cli.py @@ -35,8 +35,11 @@ class TestBitcoinCli(BitcoinTestFramework): assert_equal(["foo", "bar"], self.nodes[0].cli('-rpcuser=%s' % user, '-stdin', '-stdinrpcpass', input=password + "\nfoo\nbar").echo()) assert_raises_process_error(1, "incorrect rpcuser or rpcpassword", self.nodes[0].cli('-rpcuser=%s' % user, '-stdin', '-stdinrpcpass', input="foo").echo) + self.log.info("Make sure that -getinfo with arguments fails") + assert_raises_process_error(1, "-getinfo takes no arguments", self.nodes[0].cli('-getinfo').help) + self.log.info("Compare responses from `bitcoin-cli -getinfo` and the RPCs data is retrieved from.") - cli_get_info = self.nodes[0].cli('-getinfo').help() + cli_get_info = self.nodes[0].cli('-getinfo').send_cli() wallet_info = self.nodes[0].getwalletinfo() network_info = self.nodes[0].getnetworkinfo() blockchain_info = self.nodes[0].getblockchaininfo() diff --git a/test/functional/httpbasics.py b/test/functional/interface_http.py index c7682cb49d..cd6d744545 100755 --- a/test/functional/httpbasics.py +++ b/test/functional/interface_http.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2014-2016 The Bitcoin Core developers +# Copyright (c) 2014-2017 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test the RPC HTTP basics.""" diff --git a/test/functional/rest.py b/test/functional/interface_rest.py index 437111a4d7..9006e27cbe 100755 --- a/test/functional/rest.py +++ b/test/functional/interface_rest.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2014-2016 The Bitcoin Core developers +# Copyright (c) 2014-2017 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test the REST API.""" diff --git a/test/functional/zmq_test.py b/test/functional/interface_zmq.py index fa30318416..86ccea4394 100755 --- a/test/functional/zmq_test.py +++ b/test/functional/interface_zmq.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2015-2016 The Bitcoin Core developers +# Copyright (c) 2015-2017 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test the ZMQ notification interface.""" diff --git a/test/functional/mempool_limit.py b/test/functional/mempool_limit.py index e24dc5a464..e7ce3820d2 100755 --- a/test/functional/mempool_limit.py +++ b/test/functional/mempool_limit.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2014-2016 The Bitcoin Core developers +# Copyright (c) 2014-2017 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 mempool limiting together/eviction with the wallet.""" @@ -17,10 +17,14 @@ class MempoolLimitTest(BitcoinTestFramework): txouts = gen_return_txouts() relayfee = self.nodes[0].getnetworkinfo()['relayfee'] + self.log.info('Check that mempoolminfee is minrelytxfee') + assert_equal(self.nodes[0].getmempoolinfo()['minrelaytxfee'], Decimal('0.00001000')) + assert_equal(self.nodes[0].getmempoolinfo()['mempoolminfee'], Decimal('0.00001000')) + txids = [] utxos = create_confirmed_utxos(relayfee, self.nodes[0], 91) - #create a mempool tx that will be evicted + self.log.info('Create a mempool tx that will be evicted') us0 = utxos.pop() inputs = [{ "txid" : us0["txid"], "vout" : us0["vout"]}] outputs = {self.nodes[0].getnewaddress() : 0.0001} @@ -37,10 +41,14 @@ class MempoolLimitTest(BitcoinTestFramework): txids.append([]) txids[i] = create_lots_of_big_transactions(self.nodes[0], txouts, utxos[30*i:30*i+30], 30, (i+1)*base_fee) - # by now, the tx should be evicted, check confirmation state + self.log.info('The tx should be evicted by now') assert(txid not in self.nodes[0].getrawmempool()) txdata = self.nodes[0].gettransaction(txid) assert(txdata['confirmations'] == 0) #confirmation should still be 0 + self.log.info('Check that mempoolminfee is larger than minrelytxfee') + assert_equal(self.nodes[0].getmempoolinfo()['minrelaytxfee'], Decimal('0.00001000')) + assert_greater_than(self.nodes[0].getmempoolinfo()['mempoolminfee'], Decimal('0.00001000')) + if __name__ == '__main__': MempoolLimitTest().main() diff --git a/test/functional/mempool_packages.py b/test/functional/mempool_packages.py index b845c75681..a3e872a8c6 100755 --- a/test/functional/mempool_packages.py +++ b/test/functional/mempool_packages.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2014-2016 The Bitcoin Core developers +# Copyright (c) 2014-2017 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 descendant package tracking code.""" diff --git a/test/functional/mempool_persist.py b/test/functional/mempool_persist.py index 92f66be2ff..17f0967219 100755 --- a/test/functional/mempool_persist.py +++ b/test/functional/mempool_persist.py @@ -57,21 +57,28 @@ class MempoolPersistTest(BitcoinTestFramework): self.log.debug("Send 5 transactions from node2 (to its own address)") for i in range(5): self.nodes[2].sendtoaddress(self.nodes[2].getnewaddress(), Decimal("10")) + node2_balance = self.nodes[2].getbalance() self.sync_all() self.log.debug("Verify that node0 and node1 have 5 transactions in their mempools") assert_equal(len(self.nodes[0].getrawmempool()), 5) assert_equal(len(self.nodes[1].getrawmempool()), 5) - self.log.debug("Stop-start node0 and node1. Verify that node0 has the transactions in its mempool and node1 does not.") + self.log.debug("Stop-start the nodes. Verify that node0 has the transactions in its mempool and node1 does not. Verify that node2 calculates its balance correctly after loading wallet transactions.") self.stop_nodes() + self.start_node(1) # Give this one a head-start, so we can be "extra-sure" that it didn't load anything later self.start_node(0) - self.start_node(1) + self.start_node(2) # Give bitcoind a second to reload the mempool - time.sleep(1) - wait_until(lambda: len(self.nodes[0].getrawmempool()) == 5) + wait_until(lambda: len(self.nodes[0].getrawmempool()) == 5, timeout=1) + wait_until(lambda: len(self.nodes[2].getrawmempool()) == 5, timeout=1) + # The others have loaded their mempool. If node_1 loaded anything, we'd probably notice by now: assert_equal(len(self.nodes[1].getrawmempool()), 0) + # Verify accounting of mempool transactions after restart is correct + self.nodes[2].syncwithvalidationinterfacequeue() # Flush mempool to wallet + assert_equal(node2_balance, self.nodes[2].getbalance()) + self.log.debug("Stop-start node0 with -persistmempool=0. Verify that it doesn't load its mempool.dat file.") self.stop_nodes() self.start_node(0, extra_args=["-persistmempool=0"]) diff --git a/test/functional/mempool_reorg.py b/test/functional/mempool_reorg.py index 2803371f5b..d6bb292a58 100755 --- a/test/functional/mempool_reorg.py +++ b/test/functional/mempool_reorg.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2014-2016 The Bitcoin Core developers +# Copyright (c) 2014-2017 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 mempool re-org scenarios. diff --git a/test/functional/mempool_resurrect_test.py b/test/functional/mempool_resurrect.py index 1263c9306b..83e84da4bc 100755 --- a/test/functional/mempool_resurrect_test.py +++ b/test/functional/mempool_resurrect.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2014-2016 The Bitcoin Core developers +# Copyright (c) 2014-2017 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 resurrection of mined transactions when the blockchain is re-organized.""" diff --git a/test/functional/mempool_spendcoinbase.py b/test/functional/mempool_spend_coinbase.py index 6e8a635a76..db0738c08a 100755 --- a/test/functional/mempool_spendcoinbase.py +++ b/test/functional/mempool_spend_coinbase.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2014-2016 The Bitcoin Core developers +# Copyright (c) 2014-2017 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 spending coinbase transactions. diff --git a/test/functional/mining.py b/test/functional/mining_basic.py index 9aee06864e..569bf71933 100755 --- a/test/functional/mining.py +++ b/test/functional/mining_basic.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2014-2016 The Bitcoin Core developers +# Copyright (c) 2014-2017 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 mining RPCs diff --git a/test/functional/getblocktemplate_longpoll.py b/test/functional/mining_getblocktemplate_longpoll.py index 89768bd2fb..252ff4dbff 100755 --- a/test/functional/getblocktemplate_longpoll.py +++ b/test/functional/mining_getblocktemplate_longpoll.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2014-2016 The Bitcoin Core developers +# Copyright (c) 2014-2017 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 longpolling with getblocktemplate.""" diff --git a/test/functional/prioritise_transaction.py b/test/functional/mining_prioritisetransaction.py index bb56db9b40..57954ce321 100755 --- a/test/functional/prioritise_transaction.py +++ b/test/functional/mining_prioritisetransaction.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2015-2016 The Bitcoin Core developers +# Copyright (c) 2015-2017 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test the prioritisetransaction mining RPC.""" @@ -15,6 +15,25 @@ class PrioritiseTransactionTest(BitcoinTestFramework): self.extra_args = [["-printpriority=1"], ["-printpriority=1"]] def run_test(self): + # Test `prioritisetransaction` required parameters + assert_raises_rpc_error(-1, "prioritisetransaction", self.nodes[0].prioritisetransaction) + assert_raises_rpc_error(-1, "prioritisetransaction", self.nodes[0].prioritisetransaction, '') + assert_raises_rpc_error(-1, "prioritisetransaction", self.nodes[0].prioritisetransaction, '', 0) + + # Test `prioritisetransaction` invalid extra parameters + assert_raises_rpc_error(-1, "prioritisetransaction", self.nodes[0].prioritisetransaction, '', 0, 0, 0) + + # Test `prioritisetransaction` invalid `txid` + assert_raises_rpc_error(-1, "txid must be hexadecimal string", self.nodes[0].prioritisetransaction, txid='foo', fee_delta=0) + + # Test `prioritisetransaction` invalid `dummy` + txid = '1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000' + assert_raises_rpc_error(-1, "JSON value is not a number as expected", self.nodes[0].prioritisetransaction, txid, 'foo', 0) + assert_raises_rpc_error(-8, "Priority is no longer supported, dummy argument to prioritisetransaction must be 0.", self.nodes[0].prioritisetransaction, txid, 1, 0) + + # Test `prioritisetransaction` invalid `fee_delta` + assert_raises_rpc_error(-1, "JSON value is not an integer as expected", self.nodes[0].prioritisetransaction, txid=txid, fee_delta='foo') + self.txouts = gen_return_txouts() self.relayfee = self.nodes[0].getnetworkinfo()['relayfee'] diff --git a/test/functional/multiwallet.py b/test/functional/multiwallet.py deleted file mode 100755 index 7a0fbce477..0000000000 --- a/test/functional/multiwallet.py +++ /dev/null @@ -1,90 +0,0 @@ -#!/usr/bin/env python3 -# Copyright (c) 2017 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 multiwallet. - -Verify that a bitcoind node can load multiple wallet files -""" -import os -import shutil - -from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import assert_equal, assert_raises_rpc_error - -class MultiWalletTest(BitcoinTestFramework): - def set_test_params(self): - self.setup_clean_chain = True - self.num_nodes = 1 - self.extra_args = [['-wallet=w1', '-wallet=w2', '-wallet=w3']] - - def run_test(self): - assert_equal(set(self.nodes[0].listwallets()), {"w1", "w2", "w3"}) - - self.stop_node(0) - - # should not initialize if there are duplicate wallets - self.assert_start_raises_init_error(0, ['-wallet=w1', '-wallet=w1'], 'Error loading wallet w1. Duplicate -wallet filename specified.') - - # should not initialize if wallet file is a directory - os.mkdir(os.path.join(self.options.tmpdir, 'node0', 'regtest', 'w11')) - self.assert_start_raises_init_error(0, ['-wallet=w11'], 'Error loading wallet w11. -wallet filename must be a regular file.') - - # should not initialize if one wallet is a copy of another - shutil.copyfile(os.path.join(self.options.tmpdir, 'node0', 'regtest', 'w2'), - os.path.join(self.options.tmpdir, 'node0', 'regtest', 'w22')) - self.assert_start_raises_init_error(0, ['-wallet=w2', '-wallet=w22'], 'duplicates fileid') - - # should not initialize if wallet file is a symlink - os.symlink(os.path.join(self.options.tmpdir, 'node0', 'regtest', 'w1'), os.path.join(self.options.tmpdir, 'node0', 'regtest', 'w12')) - self.assert_start_raises_init_error(0, ['-wallet=w12'], 'Error loading wallet w12. -wallet filename must be a regular file.') - - self.start_node(0, self.extra_args[0]) - - w1 = self.nodes[0].get_wallet_rpc("w1") - w2 = self.nodes[0].get_wallet_rpc("w2") - w3 = self.nodes[0].get_wallet_rpc("w3") - wallet_bad = self.nodes[0].get_wallet_rpc("bad") - - w1.generate(1) - - # accessing invalid wallet fails - assert_raises_rpc_error(-18, "Requested wallet does not exist or is not loaded", wallet_bad.getwalletinfo) - - # accessing wallet RPC without using wallet endpoint fails - assert_raises_rpc_error(-19, "Wallet file not specified", self.nodes[0].getwalletinfo) - - # check w1 wallet balance - w1_info = w1.getwalletinfo() - assert_equal(w1_info['immature_balance'], 50) - w1_name = w1_info['walletname'] - assert_equal(w1_name, "w1") - - # check w2 wallet balance - w2_info = w2.getwalletinfo() - assert_equal(w2_info['immature_balance'], 0) - w2_name = w2_info['walletname'] - assert_equal(w2_name, "w2") - - w3_name = w3.getwalletinfo()['walletname'] - assert_equal(w3_name, "w3") - - assert_equal({"w1", "w2", "w3"}, {w1_name, w2_name, w3_name}) - - w1.generate(101) - assert_equal(w1.getbalance(), 100) - assert_equal(w2.getbalance(), 0) - assert_equal(w3.getbalance(), 0) - - w1.sendtoaddress(w2.getnewaddress(), 1) - w1.sendtoaddress(w3.getnewaddress(), 2) - w1.generate(1) - assert_equal(w2.getbalance(), 1) - assert_equal(w3.getbalance(), 2) - - batch = w1.batch([w1.getblockchaininfo.get_request(), w1.getwalletinfo.get_request()]) - assert_equal(batch[0]["result"]["chain"], "regtest") - assert_equal(batch[1]["result"]["walletname"], "w1") - -if __name__ == '__main__': - MultiWalletTest().main() diff --git a/test/functional/p2p-versionbits-warning.py b/test/functional/p2p-versionbits-warning.py deleted file mode 100755 index 464ca5a312..0000000000 --- a/test/functional/p2p-versionbits-warning.py +++ /dev/null @@ -1,121 +0,0 @@ -#!/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. -"""Test version bits warning system. - -Generate chains with block versions that appear to be signalling unknown -soft-forks, and test that warning alerts are generated. -""" - -from test_framework.mininode import * -from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import * -import re -from test_framework.blocktools import create_block, create_coinbase - -VB_PERIOD = 144 # versionbits period length for regtest -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") - -class TestNode(NodeConnCB): - def on_inv(self, conn, message): - pass - -class VersionBitsWarningTest(BitcoinTestFramework): - def set_test_params(self): - self.setup_clean_chain = True - self.num_nodes = 1 - - def setup_network(self): - 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', encoding='utf8') as _: - pass - self.extra_args = [["-alertnotify=echo %s >> \"" + self.alert_filename + "\""]] - self.setup_nodes() - - # Send numblocks blocks via peer with nVersionToUse set. - def send_blocks_with_version(self, peer, numblocks, nVersionToUse): - tip = self.nodes[0].getbestblockhash() - height = self.nodes[0].getblockcount() - block_time = self.nodes[0].getblockheader(tip)["time"]+1 - tip = int(tip, 16) - - for _ in range(numblocks): - block = create_block(tip, create_coinbase(height+1), block_time) - block.nVersion = nVersionToUse - block.solve() - peer.send_message(msg_block(block)) - block_time += 1 - height += 1 - tip = block.sha256 - peer.sync_with_ping() - - def test_versionbits_in_alert_file(self): - with open(self.alert_filename, 'r', encoding='utf8') as f: - alert_text = f.read() - assert(VB_PATTERN.match(alert_text)) - - def run_test(self): - # Setup the p2p connection and start up the network thread. - self.nodes[0].add_p2p_connection(TestNode()) - - NetworkThread().start() # Start up network handling in another thread - - # Test logic begins here - self.nodes[0].p2p.wait_for_verack() - - # 1. Have the node mine one period worth of blocks - self.nodes[0].generate(VB_PERIOD) - - # 2. Now build one period of blocks on the tip, with < VB_THRESHOLD - # blocks signaling some unknown bit. - nVersion = VB_TOP_BITS | (1<<VB_UNKNOWN_BIT) - self.send_blocks_with_version(self.nodes[0].p2p, VB_THRESHOLD-1, nVersion) - - # 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 - # get*info() - assert(not VB_PATTERN.match(self.nodes[0].getmininginfo()["warnings"])) - 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 - self.send_blocks_with_version(self.nodes[0].p2p, VB_THRESHOLD, nVersion) - self.nodes[0].generate(VB_PERIOD - VB_THRESHOLD) - # 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 get*info() shows some kind of error. - assert(WARN_UNKNOWN_RULES_MINED in self.nodes[0].getmininginfo()["warnings"]) - 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 - # to ACTIVE. - self.nodes[0].generate(VB_PERIOD) - self.stop_nodes() - # Empty out the alert file - with open(self.alert_filename, 'w', encoding='utf8') as _: - pass - self.start_nodes() - - # Connecting one block should be enough to generate an error. - self.nodes[0].generate(1) - assert(WARN_UNKNOWN_RULES_ACTIVE in self.nodes[0].getmininginfo()["warnings"]) - assert(WARN_UNKNOWN_RULES_ACTIVE in self.nodes[0].getnetworkinfo()["warnings"]) - self.stop_nodes() - self.test_versionbits_in_alert_file() - - # Test framework expects the node to still be running... - self.start_nodes() - -if __name__ == '__main__': - VersionBitsWarningTest().main() diff --git a/test/functional/p2p-compactblocks.py b/test/functional/p2p_compactblocks.py index d2c4d39305..d9f461a049 100755 --- a/test/functional/p2p-compactblocks.py +++ b/test/functional/p2p_compactblocks.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2016 The Bitcoin Core developers +# Copyright (c) 2016-2017 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 compact blocks (BIP 152). @@ -15,7 +15,7 @@ from test_framework.blocktools import create_block, create_coinbase, add_witness from test_framework.script import CScript, OP_TRUE # TestNode: A peer we use to send messages to bitcoind, and store responses. -class TestNode(NodeConnCB): +class TestNode(P2PInterface): def __init__(self): super().__init__() self.last_sendcmpct = [] @@ -25,21 +25,21 @@ class TestNode(NodeConnCB): # so we can eg wait until a particular block is announced. self.announced_blockhashes = set() - def on_sendcmpct(self, conn, message): + def on_sendcmpct(self, message): self.last_sendcmpct.append(message) - def on_cmpctblock(self, conn, message): + def on_cmpctblock(self, message): self.block_announced = True self.last_message["cmpctblock"].header_and_shortids.header.calc_sha256() self.announced_blockhashes.add(self.last_message["cmpctblock"].header_and_shortids.header.sha256) - def on_headers(self, conn, message): + def on_headers(self, message): self.block_announced = True for x in self.last_message["headers"].headers: x.calc_sha256() self.announced_blockhashes.add(x.sha256) - def on_inv(self, conn, message): + def on_inv(self, message): for x in self.last_message["inv"].inv: if x.type == 2: self.block_announced = True @@ -60,7 +60,7 @@ class TestNode(NodeConnCB): msg = msg_getheaders() msg.locator.vHave = locator msg.hashstop = hashstop - self.connection.send_message(msg) + self.send_message(msg) def send_header_for_blocks(self, new_blocks): headers_message = msg_headers() @@ -86,7 +86,7 @@ class TestNode(NodeConnCB): This is used when we want to send a message into the node that we expect will get us disconnected, eg an invalid block.""" self.send_message(message) - wait_until(lambda: not self.connected, timeout=timeout, lock=mininode_lock) + wait_until(lambda: self.state != "connected", timeout=timeout, lock=mininode_lock) class CompactBlocksTest(BitcoinTestFramework): def set_test_params(self): @@ -95,7 +95,7 @@ class CompactBlocksTest(BitcoinTestFramework): self.num_nodes = 2 # This test was written assuming SegWit is activated using BIP9 at height 432 (3x confirmation window). # TODO: Rewrite this test to support SegWit being always active. - self.extra_args = [["-vbparams=segwit:0:0"], ["-vbparams=segwit:0:999999999999", "-txindex"]] + self.extra_args = [["-vbparams=segwit:0:0"], ["-vbparams=segwit:0:999999999999", "-txindex", "-deprecatedrpc=addwitnessaddress"]] self.utxos = [] def build_block_on_tip(self, node, segwit=False): @@ -792,7 +792,7 @@ class CompactBlocksTest(BitcoinTestFramework): self.segwit_node = self.nodes[1].add_p2p_connection(TestNode(), services=NODE_NETWORK|NODE_WITNESS) self.old_node = self.nodes[1].add_p2p_connection(TestNode(), services=NODE_NETWORK) - NetworkThread().start() # Start up network handling in another thread + network_thread_start() self.test_node.wait_for_verack() diff --git a/test/functional/disconnect_ban.py b/test/functional/p2p_disconnect_ban.py index 59655d37fb..c6067befb2 100755 --- a/test/functional/disconnect_ban.py +++ b/test/functional/p2p_disconnect_ban.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2014-2016 The Bitcoin Core developers +# Copyright (c) 2014-2017 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 node disconnect and ban behavior""" diff --git a/test/functional/p2p-feefilter.py b/test/functional/p2p_feefilter.py index 624278df40..47d9c55160 100755 --- a/test/functional/p2p-feefilter.py +++ b/test/functional/p2p_feefilter.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2016 The Bitcoin Core developers +# Copyright (c) 2016-2017 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 processing of feefilter messages.""" @@ -22,12 +22,12 @@ def allInvsMatch(invsExpected, testnode): time.sleep(1) return False -class TestNode(NodeConnCB): +class TestNode(P2PInterface): def __init__(self): super().__init__() self.txinvs = [] - def on_inv(self, conn, message): + def on_inv(self, message): for i in message.inv: if (i.type == 1): self.txinvs.append(hashToHex(i.hash)) @@ -49,7 +49,7 @@ class FeeFilterTest(BitcoinTestFramework): # Setup the p2p connections and start up the network thread. self.nodes[0].add_p2p_connection(TestNode()) - NetworkThread().start() + network_thread_start() self.nodes[0].p2p.wait_for_verack() # Test that invs are received for all txs at feerate of 20 sat/byte diff --git a/test/functional/p2p-fingerprint.py b/test/functional/p2p_fingerprint.py index 4b6446fc5b..93ef73e25e 100755 --- a/test/functional/p2p-fingerprint.py +++ b/test/functional/p2p_fingerprint.py @@ -13,18 +13,17 @@ import time from test_framework.blocktools import (create_block, create_coinbase) from test_framework.mininode import ( CInv, - NetworkThread, - NodeConnCB, + P2PInterface, msg_headers, msg_block, msg_getdata, msg_getheaders, + network_thread_start, wait_until, ) from test_framework.test_framework import BitcoinTestFramework from test_framework.util import ( assert_equal, - p2p_port, ) class P2PFingerprintTest(BitcoinTestFramework): @@ -76,9 +75,9 @@ class P2PFingerprintTest(BitcoinTestFramework): # This does not currently test that stale blocks timestamped within the # last month but that have over a month's worth of work are also withheld. def run_test(self): - node0 = self.nodes[0].add_p2p_connection(NodeConnCB()) + node0 = self.nodes[0].add_p2p_connection(P2PInterface()) - NetworkThread().start() + network_thread_start() node0.wait_for_verack() # Set node time to 60 days ago diff --git a/test/functional/invalidblockrequest.py b/test/functional/p2p_invalid_block.py index 9f44b44927..edcade63c1 100755 --- a/test/functional/invalidblockrequest.py +++ b/test/functional/p2p_invalid_block.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2015-2016 The Bitcoin Core developers +# Copyright (c) 2015-2017 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 node responses to invalid blocks. @@ -15,6 +15,7 @@ from test_framework.test_framework import ComparisonTestFramework from test_framework.util import * from test_framework.comptool import TestManager, TestInstance, RejectResult from test_framework.blocktools import * +from test_framework.mininode import network_thread_start import copy import time @@ -32,7 +33,7 @@ class InvalidBlockRequestTest(ComparisonTestFramework): test.add_all_connections(self.nodes) self.tip = None self.block_time = None - NetworkThread().start() # Start up network handling in another thread + network_thread_start() test.run() def get_tests(self): diff --git a/test/functional/invalidtxrequest.py b/test/functional/p2p_invalid_tx.py index a22bd8f8cd..9c1100e070 100755 --- a/test/functional/invalidtxrequest.py +++ b/test/functional/p2p_invalid_tx.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2015-2016 The Bitcoin Core developers +# Copyright (c) 2015-2017 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 node responses to invalid transactions. @@ -28,7 +28,7 @@ class InvalidTxRequestTest(ComparisonTestFramework): test.add_all_connections(self.nodes) self.tip = None self.block_time = None - NetworkThread().start() # Start up network handling in another thread + network_thread_start() test.run() def get_tests(self): diff --git a/test/functional/p2p-leaktests.py b/test/functional/p2p_leak.py index 719a03914d..ce4e6e9144 100755 --- a/test/functional/p2p-leaktests.py +++ b/test/functional/p2p_leak.py @@ -20,7 +20,7 @@ from test_framework.util import * banscore = 10 -class CLazyNode(NodeConnCB): +class CLazyNode(P2PInterface): def __init__(self): super().__init__() self.unexpected_msg = False @@ -30,43 +30,42 @@ class CLazyNode(NodeConnCB): self.unexpected_msg = True self.log.info("should not have received message: %s" % message.command) - def on_open(self, conn): - self.connected = True + def on_open(self): self.ever_connected = True - def on_version(self, conn, message): self.bad_message(message) - def on_verack(self, conn, message): self.bad_message(message) - def on_reject(self, conn, message): self.bad_message(message) - def on_inv(self, conn, message): self.bad_message(message) - def on_addr(self, conn, message): self.bad_message(message) - def on_getdata(self, conn, message): self.bad_message(message) - def on_getblocks(self, conn, message): self.bad_message(message) - def on_tx(self, conn, message): self.bad_message(message) - def on_block(self, conn, message): self.bad_message(message) - def on_getaddr(self, conn, message): self.bad_message(message) - def on_headers(self, conn, message): self.bad_message(message) - def on_getheaders(self, conn, message): self.bad_message(message) - def on_ping(self, conn, message): self.bad_message(message) - def on_mempool(self, conn): self.bad_message(message) - def on_pong(self, conn, message): self.bad_message(message) - def on_feefilter(self, conn, message): self.bad_message(message) - def on_sendheaders(self, conn, message): self.bad_message(message) - def on_sendcmpct(self, conn, message): self.bad_message(message) - def on_cmpctblock(self, conn, message): self.bad_message(message) - def on_getblocktxn(self, conn, message): self.bad_message(message) - def on_blocktxn(self, conn, message): self.bad_message(message) + def on_version(self, message): self.bad_message(message) + def on_verack(self, message): self.bad_message(message) + def on_reject(self, message): self.bad_message(message) + def on_inv(self, message): self.bad_message(message) + def on_addr(self, message): self.bad_message(message) + def on_getdata(self, message): self.bad_message(message) + def on_getblocks(self, message): self.bad_message(message) + def on_tx(self, message): self.bad_message(message) + def on_block(self, message): self.bad_message(message) + def on_getaddr(self, message): self.bad_message(message) + def on_headers(self, message): self.bad_message(message) + def on_getheaders(self, message): self.bad_message(message) + def on_ping(self, message): self.bad_message(message) + def on_mempool(self, message): self.bad_message(message) + def on_pong(self, message): self.bad_message(message) + def on_feefilter(self, message): self.bad_message(message) + def on_sendheaders(self, message): self.bad_message(message) + def on_sendcmpct(self, message): self.bad_message(message) + def on_cmpctblock(self, message): self.bad_message(message) + def on_getblocktxn(self, message): self.bad_message(message) + def on_blocktxn(self, message): self.bad_message(message) # Node that never sends a version. We'll use this to send a bunch of messages # anyway, and eventually get disconnected. class CNodeNoVersionBan(CLazyNode): # send a bunch of veracks without sending a message. This should get us disconnected. # NOTE: implementation-specific check here. Remove if bitcoind ban behavior changes - def on_open(self, conn): - super().on_open(conn) + def on_open(self): + super().on_open() for i in range(banscore): self.send_message(msg_verack()) - def on_reject(self, conn, message): pass + def on_reject(self, message): pass # Node that never sends a version. This one just sits idle and hopes to receive # any message (it shouldn't!) @@ -80,15 +79,15 @@ class CNodeNoVerackIdle(CLazyNode): self.version_received = False super().__init__() - def on_reject(self, conn, message): pass - def on_verack(self, conn, message): pass + def on_reject(self, message): pass + def on_verack(self, message): pass # When version is received, don't reply with a verack. Instead, see if the # node will give us a message that it shouldn't. This is not an exhaustive # list! - def on_version(self, conn, message): + def on_version(self, message): self.version_received = True - conn.send_message(msg_ping()) - conn.send_message(msg_getaddr()) + self.send_message(msg_ping()) + self.send_message(msg_getaddr()) class P2PLeakTest(BitcoinTestFramework): def set_test_params(self): @@ -104,7 +103,7 @@ class P2PLeakTest(BitcoinTestFramework): unsupported_service_bit5_node = self.nodes[0].add_p2p_connection(CLazyNode(), services=NODE_NETWORK|NODE_UNSUPPORTED_SERVICE_BIT_5) unsupported_service_bit7_node = self.nodes[0].add_p2p_connection(CLazyNode(), services=NODE_NETWORK|NODE_UNSUPPORTED_SERVICE_BIT_7) - NetworkThread().start() # Start up network handling in another thread + network_thread_start() wait_until(lambda: no_version_bannode.ever_connected, timeout=10, lock=mininode_lock) wait_until(lambda: no_version_idlenode.ever_connected, timeout=10, lock=mininode_lock) @@ -119,16 +118,17 @@ class P2PLeakTest(BitcoinTestFramework): time.sleep(5) #This node should have been banned - assert not no_version_bannode.connected + assert no_version_bannode.state != "connected" # These nodes should have been disconnected - assert not unsupported_service_bit5_node.connected - assert not unsupported_service_bit7_node.connected + assert unsupported_service_bit5_node.state != "connected" + assert unsupported_service_bit7_node.state != "connected" self.nodes[0].disconnect_p2ps() - # Wait until all connections are closed + # Wait until all connections are closed and the network thread has terminated wait_until(lambda: len(self.nodes[0].getpeerinfo()) == 0) + network_thread_join() # Make sure no unexpected messages came in assert(no_version_bannode.unexpected_msg == False) @@ -140,10 +140,11 @@ class P2PLeakTest(BitcoinTestFramework): self.log.info("Service bits 5 and 7 are allowed after August 1st 2018") self.nodes[0].setmocktime(1533168000) # August 2nd 2018 - allowed_service_bit5_node = self.nodes[0].add_p2p_connection(NodeConnCB(), services=NODE_NETWORK|NODE_UNSUPPORTED_SERVICE_BIT_5) - allowed_service_bit7_node = self.nodes[0].add_p2p_connection(NodeConnCB(), services=NODE_NETWORK|NODE_UNSUPPORTED_SERVICE_BIT_7) + allowed_service_bit5_node = self.nodes[0].add_p2p_connection(P2PInterface(), services=NODE_NETWORK|NODE_UNSUPPORTED_SERVICE_BIT_5) + allowed_service_bit7_node = self.nodes[0].add_p2p_connection(P2PInterface(), services=NODE_NETWORK|NODE_UNSUPPORTED_SERVICE_BIT_7) - NetworkThread().start() # Network thread stopped when all previous NodeConnCBs disconnected. Restart it + # Network thread stopped when all previous P2PInterfaces disconnected. Restart it + network_thread_start() wait_until(lambda: allowed_service_bit5_node.message_count["verack"], lock=mininode_lock) wait_until(lambda: allowed_service_bit7_node.message_count["verack"], lock=mininode_lock) diff --git a/test/functional/p2p-mempool.py b/test/functional/p2p_mempool.py index be467c4223..485a8af3d0 100755 --- a/test/functional/p2p-mempool.py +++ b/test/functional/p2p_mempool.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2015-2016 The Bitcoin Core developers +# Copyright (c) 2015-2017 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 p2p mempool message. @@ -20,8 +20,8 @@ class P2PMempoolTests(BitcoinTestFramework): def run_test(self): # Add a p2p connection - self.nodes[0].add_p2p_connection(NodeConnCB()) - NetworkThread().start() + self.nodes[0].add_p2p_connection(P2PInterface()) + network_thread_start() self.nodes[0].p2p.wait_for_verack() #request mempool diff --git a/test/functional/p2p_node_network_limited.py b/test/functional/p2p_node_network_limited.py new file mode 100755 index 0000000000..70415e0168 --- /dev/null +++ b/test/functional/p2p_node_network_limited.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python3 +# Copyright (c) 2017 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 NODE_NETWORK_LIMITED. + +Tests that a node configured with -prune=550 signals NODE_NETWORK_LIMITED correctly +and that it responds to getdata requests for blocks correctly: + - send a block within 288 + 2 of the tip + - disconnect peers who request blocks older than that.""" +from test_framework.messages import CInv, msg_getdata +from test_framework.mininode import NODE_BLOOM, NODE_NETWORK_LIMITED, NODE_WITNESS, NetworkThread, P2PInterface +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import assert_equal + +class P2PIgnoreInv(P2PInterface): + def on_inv(self, message): + # The node will send us invs for other blocks. Ignore them. + pass + + def send_getdata_for_block(self, blockhash): + getdata_request = msg_getdata() + getdata_request.inv.append(CInv(2, int(blockhash, 16))) + self.send_message(getdata_request) + +class NodeNetworkLimitedTest(BitcoinTestFramework): + def set_test_params(self): + self.setup_clean_chain = True + self.num_nodes = 1 + self.extra_args = [['-prune=550']] + + def run_test(self): + node = self.nodes[0].add_p2p_connection(P2PIgnoreInv()) + NetworkThread().start() + node.wait_for_verack() + + expected_services = NODE_BLOOM | NODE_WITNESS | NODE_NETWORK_LIMITED + + self.log.info("Check that node has signalled expected services.") + assert_equal(node.nServices, expected_services) + + self.log.info("Check that the localservices is as expected.") + assert_equal(int(self.nodes[0].getnetworkinfo()['localservices'], 16), expected_services) + + self.log.info("Mine enough blocks to reach the NODE_NETWORK_LIMITED range.") + blocks = self.nodes[0].generate(292) + + self.log.info("Make sure we can max retrive block at tip-288.") + node.send_getdata_for_block(blocks[1]) # last block in valid range + node.wait_for_block(int(blocks[1], 16), timeout=3) + + self.log.info("Requesting block at height 2 (tip-289) must fail (ignored).") + node.send_getdata_for_block(blocks[0]) # first block outside of the 288+2 limit + node.wait_for_disconnect(5) + +if __name__ == '__main__': + NodeNetworkLimitedTest().main() diff --git a/test/functional/p2p-segwit.py b/test/functional/p2p_segwit.py index b940bc4096..20e4805df0 100755 --- a/test/functional/p2p-segwit.py +++ b/test/functional/p2p_segwit.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2016 The Bitcoin Core developers +# Copyright (c) 2016-2017 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 segwit transactions and blocks on P2P network.""" @@ -25,19 +25,46 @@ MAX_SIGOP_COST = 80000 # Calculate the virtual size of a witness block: # (base + witness/4) def get_virtual_size(witness_block): - base_size = len(witness_block.serialize()) + base_size = len(witness_block.serialize(with_witness=False)) total_size = len(witness_block.serialize(with_witness=True)) # the "+3" is so we round up vsize = int((3*base_size + total_size + 3)/4) return vsize -class TestNode(NodeConnCB): - def __init__(self, rpc): +def test_transaction_acceptance(rpc, p2p, tx, with_witness, accepted, reason=None): + """Send a transaction to the node and check that it's accepted to the mempool + + - Submit the transaction over the p2p interface + - use the getrawmempool rpc to check for acceptance.""" + tx_message = msg_tx(tx) + if with_witness: + tx_message = msg_witness_tx(tx) + p2p.send_message(tx_message) + p2p.sync_with_ping() + assert_equal(tx.hash in rpc.getrawmempool(), accepted) + if (reason != None and not accepted): + # Check the rejection reason as well. + with mininode_lock: + assert_equal(p2p.last_message["reject"].reason, reason) + +def test_witness_block(rpc, p2p, block, accepted, with_witness=True): + """Send a block to the node and check that it's accepted + + - Submit the block over the p2p interface + - use the getbestblockhash rpc to check for acceptance.""" + if with_witness: + p2p.send_message(msg_witness_block(block)) + else: + p2p.send_message(msg_block(block)) + p2p.sync_with_ping() + assert_equal(rpc.getbestblockhash() == block.hash, accepted) + +class TestNode(P2PInterface): + def __init__(self): super().__init__() self.getdataset = set() - self.rpc = rpc - def on_getdata(self, conn, message): + def on_getdata(self, message): for inv in message.inv: self.getdataset.add(inv.hash) @@ -68,27 +95,6 @@ class TestNode(NodeConnCB): self.wait_for_block(blockhash, timeout) return self.last_message["block"].block - def test_transaction_acceptance(self, tx, with_witness, accepted, reason=None): - tx_message = msg_tx(tx) - if with_witness: - tx_message = msg_witness_tx(tx) - self.send_message(tx_message) - self.sync_with_ping() - assert_equal(tx.hash in self.rpc.getrawmempool(), accepted) - if (reason != None and not accepted): - # Check the rejection reason as well. - with mininode_lock: - assert_equal(self.last_message["reject"].reason, reason) - - # Test whether a witness block had the correct effect on the tip - def test_witness_block(self, block, accepted, with_witness=True): - if with_witness: - self.send_message(msg_witness_block(block)) - else: - self.send_message(msg_block(block)) - self.sync_with_ping() - assert_equal(self.rpc.getbestblockhash() == block.hash, accepted) - # Used to keep track of anyone-can-spend outputs that we can use in the tests class UTXO(): def __init__(self, sha256, n, nValue): @@ -142,7 +148,7 @@ class SegWitTest(BitcoinTestFramework): ''' Individual tests ''' def test_witness_services(self): self.log.info("Verifying NODE_WITNESS service bit") - assert((self.test_node.connection.nServices & NODE_WITNESS) != 0) + assert((self.test_node.nServices & NODE_WITNESS) != 0) # See if sending a regular transaction works, and create a utxo @@ -201,7 +207,7 @@ class SegWitTest(BitcoinTestFramework): self.update_witness_block_with_transactions(block, [tx]) # Sending witness data before activation is not allowed (anti-spam # rule). - self.test_node.test_witness_block(block, accepted=False) + test_witness_block(self.nodes[0].rpc, self.test_node, block, accepted=False) # TODO: fix synchronization so we can test reject reason # Right now, bitcoind delays sending reject messages for blocks # until the future, making synchronization here difficult. @@ -228,7 +234,7 @@ class SegWitTest(BitcoinTestFramework): tx2.vin.append(CTxIn(COutPoint(tx.sha256, 0), b"")) tx2.vout.append(CTxOut(tx.vout[0].nValue-1000, scriptPubKey)) tx2.rehash() - self.test_node.test_transaction_acceptance(tx2, False, True) + test_transaction_acceptance(self.nodes[0].rpc, self.test_node, tx2, False, True) self.nodes[0].generate(1) sync_blocks(self.nodes) @@ -245,18 +251,18 @@ class SegWitTest(BitcoinTestFramework): 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') + test_transaction_acceptance(self.nodes[1].rpc, self.std_node, tx3, True, False, b'no-witness-yet') # If we send without witness, it should be accepted. - self.std_node.test_transaction_acceptance(tx3, False, True) + test_transaction_acceptance(self.nodes[1].rpc, self.std_node, tx3, False, True) # Now create a new anyone-can-spend utxo for the next test. tx4 = CTransaction() tx4.vin.append(CTxIn(COutPoint(tx3.sha256, 0), CScript([p2sh_program]))) tx4.vout.append(CTxOut(tx3.vout[0].nValue-1000, CScript([OP_TRUE]))) tx4.rehash() - self.test_node.test_transaction_acceptance(tx3, False, True) - self.test_node.test_transaction_acceptance(tx4, False, True) + test_transaction_acceptance(self.nodes[0].rpc, self.test_node, tx3, False, True) + test_transaction_acceptance(self.nodes[0].rpc, self.test_node, tx4, False, True) self.nodes[0].generate(1) sync_blocks(self.nodes) @@ -317,7 +323,7 @@ class SegWitTest(BitcoinTestFramework): assert(msg_witness_block(block).serialize() != msg_block(block).serialize()) # This empty block should be valid. - self.test_node.test_witness_block(block, accepted=True) + test_witness_block(self.nodes[0].rpc, self.test_node, block, accepted=True) # Try to tweak the nonce block_2 = self.build_next_block() @@ -328,7 +334,7 @@ class SegWitTest(BitcoinTestFramework): assert(block_2.vtx[0].vout[-1] != block.vtx[0].vout[-1]) # This should also be valid. - self.test_node.test_witness_block(block_2, accepted=True) + test_witness_block(self.nodes[0].rpc, self.test_node, block_2, accepted=True) # Now test commitments with actual transactions assert (len(self.utxo) > 0) @@ -361,7 +367,7 @@ class SegWitTest(BitcoinTestFramework): block_3.rehash() block_3.solve() - self.test_node.test_witness_block(block_3, accepted=False) + test_witness_block(self.nodes[0].rpc, self.test_node, block_3, accepted=False) # Add a different commitment with different nonce, but in the # right location, and with some funds burned(!). @@ -375,7 +381,7 @@ class SegWitTest(BitcoinTestFramework): block_3.rehash() assert(len(block_3.vtx[0].vout) == 4) # 3 OP_returns block_3.solve() - self.test_node.test_witness_block(block_3, accepted=True) + test_witness_block(self.nodes[0].rpc, self.test_node, block_3, accepted=True) # Finally test that a block with no witness transactions can # omit the commitment. @@ -387,7 +393,7 @@ class SegWitTest(BitcoinTestFramework): block_4.vtx.append(tx3) block_4.hashMerkleRoot = block_4.calc_merkle_root() block_4.solve() - self.test_node.test_witness_block(block_4, with_witness=False, accepted=True) + test_witness_block(self.nodes[0].rpc, self.test_node, block_4, with_witness=False, accepted=True) # Update available utxo's for use in later test. self.utxo.pop(0) @@ -428,11 +434,11 @@ class SegWitTest(BitcoinTestFramework): # Change the nonce -- should not cause the block to be permanently # failed block.vtx[0].wit.vtxinwit[0].scriptWitness.stack = [ ser_uint256(1) ] - self.test_node.test_witness_block(block, accepted=False) + test_witness_block(self.nodes[0].rpc, self.test_node, block, accepted=False) # Changing the witness nonce doesn't change the block hash block.vtx[0].wit.vtxinwit[0].scriptWitness.stack = [ ser_uint256(0) ] - self.test_node.test_witness_block(block, accepted=True) + test_witness_block(self.nodes[0].rpc, self.test_node, block, accepted=True) def test_witness_block_size(self): @@ -497,7 +503,7 @@ class SegWitTest(BitcoinTestFramework): # limit assert(len(block.serialize(True)) > 2*1024*1024) - self.test_node.test_witness_block(block, accepted=False) + test_witness_block(self.nodes[0].rpc, self.test_node, block, accepted=False) # Now resize the second transaction to make the block fit. cur_length = len(block.vtx[-1].wit.vtxinwit[0].scriptWitness.stack[0]) @@ -507,7 +513,7 @@ class SegWitTest(BitcoinTestFramework): block.solve() assert(get_virtual_size(block) == MAX_BLOCK_BASE_SIZE) - self.test_node.test_witness_block(block, accepted=True) + test_witness_block(self.nodes[0].rpc, self.test_node, block, accepted=True) # Update available utxo's self.utxo.pop(0) @@ -574,7 +580,7 @@ class SegWitTest(BitcoinTestFramework): self.update_witness_block_with_transactions(block, [tx]) # Extra witness data should not be allowed. - self.test_node.test_witness_block(block, accepted=False) + test_witness_block(self.nodes[0].rpc, self.test_node, block, accepted=False) # Try extra signature data. Ok if we're not spending a witness output. block.vtx[1].wit.vtxinwit = [] @@ -583,7 +589,7 @@ class SegWitTest(BitcoinTestFramework): add_witness_commitment(block) block.solve() - self.test_node.test_witness_block(block, accepted=True) + test_witness_block(self.nodes[0].rpc, self.test_node, block, accepted=True) # Now try extra witness/signature data on an input that DOES require a # witness @@ -599,7 +605,7 @@ class SegWitTest(BitcoinTestFramework): self.update_witness_block_with_transactions(block, [tx2]) # This has extra witness data, so it should fail. - self.test_node.test_witness_block(block, accepted=False) + test_witness_block(self.nodes[0].rpc, self.test_node, block, accepted=False) # Now get rid of the extra witness, but add extra scriptSig data tx2.vin[0].scriptSig = CScript([OP_TRUE]) @@ -611,7 +617,7 @@ class SegWitTest(BitcoinTestFramework): block.solve() # This has extra signature data for a witness input, so it should fail. - self.test_node.test_witness_block(block, accepted=False) + test_witness_block(self.nodes[0].rpc, self.test_node, block, accepted=False) # Now get rid of the extra scriptsig on the witness input, and verify # success (even with extra scriptsig data in the non-witness input) @@ -620,7 +626,7 @@ class SegWitTest(BitcoinTestFramework): add_witness_commitment(block) block.solve() - self.test_node.test_witness_block(block, accepted=True) + test_witness_block(self.nodes[0].rpc, self.test_node, block, accepted=True) # Update utxo for later tests self.utxo.pop(0) @@ -653,14 +659,14 @@ class SegWitTest(BitcoinTestFramework): tx2.rehash() self.update_witness_block_with_transactions(block, [tx, tx2]) - self.test_node.test_witness_block(block, accepted=False) + test_witness_block(self.nodes[0].rpc, self.test_node, block, accepted=False) # Now reduce the length of the stack element tx2.wit.vtxinwit[0].scriptWitness.stack[0] = b'a'*(MAX_SCRIPT_ELEMENT_SIZE) add_witness_commitment(block) block.solve() - self.test_node.test_witness_block(block, accepted=True) + test_witness_block(self.nodes[0].rpc, self.test_node, block, accepted=True) # Update the utxo for later tests self.utxo.pop() @@ -695,7 +701,7 @@ class SegWitTest(BitcoinTestFramework): self.update_witness_block_with_transactions(block, [tx, tx2]) - self.test_node.test_witness_block(block, accepted=False) + test_witness_block(self.nodes[0].rpc, self.test_node, block, accepted=False) # Try again with one less byte in the witness program witness_program = CScript([b'a'*520]*19 + [OP_DROP]*62 + [OP_TRUE]) @@ -710,7 +716,7 @@ class SegWitTest(BitcoinTestFramework): tx2.rehash() block.vtx = [block.vtx[0]] self.update_witness_block_with_transactions(block, [tx, tx2]) - self.test_node.test_witness_block(block, accepted=True) + test_witness_block(self.nodes[0].rpc, self.test_node, block, accepted=True) self.utxo.pop() self.utxo.append(UTXO(tx2.sha256, 0, tx2.vout[0].nValue)) @@ -736,7 +742,7 @@ class SegWitTest(BitcoinTestFramework): block = self.build_next_block() self.update_witness_block_with_transactions(block, [tx]) - self.test_node.test_witness_block(block, accepted=True) + test_witness_block(self.nodes[0].rpc, self.test_node, block, accepted=True) # Try various ways to spend tx that should all break. # This "broken" transaction serializer will not normalize @@ -771,7 +777,7 @@ class SegWitTest(BitcoinTestFramework): block = self.build_next_block() self.update_witness_block_with_transactions(block, [tx2]) - self.test_node.test_witness_block(block, accepted=False) + test_witness_block(self.nodes[0].rpc, self.test_node, block, accepted=False) # Now try using a too short vtxinwit tx2.wit.vtxinwit.pop() @@ -779,7 +785,7 @@ class SegWitTest(BitcoinTestFramework): block.vtx = [block.vtx[0]] self.update_witness_block_with_transactions(block, [tx2]) - self.test_node.test_witness_block(block, accepted=False) + test_witness_block(self.nodes[0].rpc, self.test_node, block, accepted=False) # Now make one of the intermediate witnesses be incorrect tx2.wit.vtxinwit.append(CTxInWitness()) @@ -788,13 +794,13 @@ class SegWitTest(BitcoinTestFramework): block.vtx = [block.vtx[0]] self.update_witness_block_with_transactions(block, [tx2]) - self.test_node.test_witness_block(block, accepted=False) + test_witness_block(self.nodes[0].rpc, self.test_node, block, accepted=False) # Fix the broken witness and the block should be accepted. tx2.wit.vtxinwit[5].scriptWitness.stack = [b'a', witness_program] block.vtx = [block.vtx[0]] self.update_witness_block_with_transactions(block, [tx2]) - self.test_node.test_witness_block(block, accepted=True) + test_witness_block(self.nodes[0].rpc, self.test_node, block, accepted=True) self.utxo.pop() self.utxo.append(UTXO(tx2.sha256, 0, tx2.vout[0].nValue)) @@ -834,11 +840,11 @@ class SegWitTest(BitcoinTestFramework): # its from) assert_equal(len(self.nodes[0].getrawmempool()), 0) assert_equal(len(self.nodes[1].getrawmempool()), 0) - self.old_node.test_transaction_acceptance(tx, with_witness=True, accepted=False) - self.test_node.test_transaction_acceptance(tx, with_witness=True, accepted=False) + test_transaction_acceptance(self.nodes[0].rpc, self.old_node, tx, with_witness=True, accepted=False) + test_transaction_acceptance(self.nodes[0].rpc, self.test_node, tx, with_witness=True, accepted=False) # But eliminating the witness should fix it - self.test_node.test_transaction_acceptance(tx, with_witness=False, accepted=True) + test_transaction_acceptance(self.nodes[0].rpc, self.test_node, tx, with_witness=False, accepted=True) # Cleanup: mine the first transaction and update utxo self.nodes[0].generate(1) @@ -870,11 +876,11 @@ class SegWitTest(BitcoinTestFramework): # Verify that unnecessary witnesses are rejected. self.test_node.announce_tx_and_wait_for_getdata(tx) assert_equal(len(self.nodes[0].getrawmempool()), 0) - self.test_node.test_transaction_acceptance(tx, with_witness=True, accepted=False) + test_transaction_acceptance(self.nodes[0].rpc, self.test_node, tx, with_witness=True, accepted=False) # Verify that removing the witness succeeds. self.test_node.announce_tx_and_wait_for_getdata(tx) - self.test_node.test_transaction_acceptance(tx, with_witness=False, accepted=True) + test_transaction_acceptance(self.nodes[0].rpc, self.test_node, tx, with_witness=False, accepted=True) # Now try to add extra witness data to a valid witness tx. witness_program = CScript([OP_TRUE]) @@ -899,24 +905,24 @@ class SegWitTest(BitcoinTestFramework): # Node will not be blinded to the transaction self.std_node.announce_tx_and_wait_for_getdata(tx3) - self.std_node.test_transaction_acceptance(tx3, True, False, b'tx-size') + test_transaction_acceptance(self.nodes[1].rpc, self.std_node, tx3, True, False, b'tx-size') self.std_node.announce_tx_and_wait_for_getdata(tx3) - self.std_node.test_transaction_acceptance(tx3, True, False, b'tx-size') + test_transaction_acceptance(self.nodes[1].rpc, self.std_node, tx3, True, False, b'tx-size') # Remove witness stuffing, instead add extra witness push on stack tx3.vout[0] = CTxOut(tx2.vout[0].nValue-1000, CScript([OP_TRUE])) tx3.wit.vtxinwit[0].scriptWitness.stack = [CScript([CScriptNum(1)]), witness_program ] tx3.rehash() - self.test_node.test_transaction_acceptance(tx2, with_witness=True, accepted=True) - self.test_node.test_transaction_acceptance(tx3, with_witness=True, accepted=False) + test_transaction_acceptance(self.nodes[0].rpc, self.test_node, tx2, with_witness=True, accepted=True) + test_transaction_acceptance(self.nodes[0].rpc, self.test_node, tx3, with_witness=True, accepted=False) # Get rid of the extra witness, and verify acceptance. tx3.wit.vtxinwit[0].scriptWitness.stack = [ witness_program ] # Also check that old_node gets a tx announcement, even though this is # a witness transaction. self.old_node.wait_for_inv([CInv(1, tx2.sha256)]) # wait until tx2 was inv'ed - self.test_node.test_transaction_acceptance(tx3, with_witness=True, accepted=True) + test_transaction_acceptance(self.nodes[0].rpc, self.test_node, tx3, with_witness=True, accepted=True) self.old_node.wait_for_inv([CInv(1, tx3.sha256)]) # Test that getrawtransaction returns correct witness information @@ -955,20 +961,20 @@ class SegWitTest(BitcoinTestFramework): self.test_node.announce_block_and_wait_for_getdata(block1, use_header=False) assert(self.test_node.last_message["getdata"].inv[0].type == blocktype) - self.test_node.test_witness_block(block1, True) + test_witness_block(self.nodes[0].rpc, self.test_node, block1, True) block2 = self.build_next_block(nVersion=4) block2.solve() self.test_node.announce_block_and_wait_for_getdata(block2, use_header=True) assert(self.test_node.last_message["getdata"].inv[0].type == blocktype) - self.test_node.test_witness_block(block2, True) + test_witness_block(self.nodes[0].rpc, self.test_node, block2, True) block3 = self.build_next_block(nVersion=(VB_TOP_BITS | (1<<15))) block3.solve() self.test_node.announce_block_and_wait_for_getdata(block3, use_header=True) assert(self.test_node.last_message["getdata"].inv[0].type == blocktype) - self.test_node.test_witness_block(block3, True) + test_witness_block(self.nodes[0].rpc, self.test_node, block3, True) # Check that we can getdata for witness blocks or regular blocks, # and the right thing happens. @@ -998,7 +1004,7 @@ class SegWitTest(BitcoinTestFramework): # This gives us a witness commitment. assert(len(block.vtx[0].wit.vtxinwit) == 1) assert(len(block.vtx[0].wit.vtxinwit[0].scriptWitness.stack) == 1) - self.test_node.test_witness_block(block, accepted=True) + test_witness_block(self.nodes[0].rpc, self.test_node, block, accepted=True) # Now try to retrieve it... rpc_block = self.nodes[0].getblock(block.hash, False) non_wit_block = self.test_node.request_block(block.sha256, 2) @@ -1052,7 +1058,7 @@ class SegWitTest(BitcoinTestFramework): p2sh_tx.rehash() # Mine it on test_node to create the confirmed output. - self.test_node.test_transaction_acceptance(p2sh_tx, with_witness=True, accepted=True) + test_transaction_acceptance(self.nodes[0].rpc, self.test_node, p2sh_tx, with_witness=True, accepted=True) self.nodes[0].generate(1) sync_blocks(self.nodes) @@ -1064,7 +1070,7 @@ class SegWitTest(BitcoinTestFramework): tx.vout.append(CTxOut(8000, scriptPubKey)) # Might burn this later tx.rehash() - self.std_node.test_transaction_acceptance(tx, with_witness=True, accepted=segwit_activated) + test_transaction_acceptance(self.nodes[1].rpc, self.std_node, tx, with_witness=True, accepted=segwit_activated) # Now create something that looks like a P2PKH output. This won't be spendable. scriptPubKey = CScript([OP_0, hash160(witness_hash)]) @@ -1081,7 +1087,7 @@ class SegWitTest(BitcoinTestFramework): tx2.vout = [CTxOut(p2sh_tx.vout[0].nValue-1000, scriptPubKey)] tx2.rehash() - self.std_node.test_transaction_acceptance(tx2, with_witness=True, accepted=segwit_activated) + test_transaction_acceptance(self.nodes[1].rpc, self.std_node, tx2, with_witness=True, accepted=segwit_activated) # Now update self.utxo for later tests. tx3 = CTransaction() @@ -1094,13 +1100,13 @@ class SegWitTest(BitcoinTestFramework): tx3.wit.vtxinwit.append(CTxInWitness()) tx3.wit.vtxinwit[0].scriptWitness.stack = [witness_program] tx3.rehash() - self.test_node.test_transaction_acceptance(tx3, with_witness=True, accepted=True) + test_transaction_acceptance(self.nodes[0].rpc, self.test_node, tx3, with_witness=True, accepted=True) else: # tx and tx2 didn't go anywhere; just clean up the p2sh_tx output. tx3.vin = [CTxIn(COutPoint(p2sh_tx.sha256, 0), CScript([witness_program]))] tx3.vout = [CTxOut(p2sh_tx.vout[0].nValue-1000, witness_program)] tx3.rehash() - self.test_node.test_transaction_acceptance(tx3, with_witness=True, accepted=True) + test_transaction_acceptance(self.nodes[0].rpc, self.test_node, tx3, with_witness=True, accepted=True) self.nodes[0].generate(1) sync_blocks(self.nodes) @@ -1124,7 +1130,7 @@ class SegWitTest(BitcoinTestFramework): tx.rehash() block = self.build_next_block() self.update_witness_block_with_transactions(block, [tx]) - self.test_node.test_witness_block(block, accepted=True) + test_witness_block(self.nodes[0].rpc, self.test_node, block, accepted=True) self.utxo.pop(0) for i in range(NUM_TESTS): self.utxo.append(UTXO(tx.sha256, i, split_value)) @@ -1143,8 +1149,8 @@ class SegWitTest(BitcoinTestFramework): tx.vin = [CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b"")] tx.vout = [CTxOut(self.utxo[0].nValue-1000, scriptPubKey)] tx.rehash() - self.std_node.test_transaction_acceptance(tx, with_witness=True, accepted=False) - self.test_node.test_transaction_acceptance(tx, with_witness=True, accepted=True) + test_transaction_acceptance(self.nodes[1].rpc, self.std_node, tx, with_witness=True, accepted=False) + test_transaction_acceptance(self.nodes[0].rpc, self.test_node, tx, with_witness=True, accepted=True) self.utxo.pop(0) temp_utxo.append(UTXO(tx.sha256, 0, tx.vout[0].nValue)) @@ -1163,8 +1169,8 @@ class SegWitTest(BitcoinTestFramework): tx2.rehash() # Gets accepted to test_node, because standardness of outputs isn't # checked with fRequireStandard - self.test_node.test_transaction_acceptance(tx2, with_witness=True, accepted=True) - self.std_node.test_transaction_acceptance(tx2, with_witness=True, accepted=False) + test_transaction_acceptance(self.nodes[0].rpc, self.test_node, tx2, with_witness=True, accepted=True) + test_transaction_acceptance(self.nodes[1].rpc, self.std_node, tx2, with_witness=True, accepted=False) temp_utxo.pop() # last entry in temp_utxo was the output we just spent temp_utxo.append(UTXO(tx2.sha256, 0, tx2.vout[0].nValue)) @@ -1180,7 +1186,7 @@ class SegWitTest(BitcoinTestFramework): tx3.rehash() # Spending a higher version witness output is not allowed by policy, # even with fRequireStandard=false. - self.test_node.test_transaction_acceptance(tx3, with_witness=True, accepted=False) + test_transaction_acceptance(self.nodes[0].rpc, self.test_node, tx3, with_witness=True, accepted=False) self.test_node.sync_with_ping() with mininode_lock: assert(b"reserved for soft-fork upgrades" in self.test_node.last_message["reject"].reason) @@ -1188,7 +1194,7 @@ class SegWitTest(BitcoinTestFramework): # Building a block with the transaction must be valid, however. block = self.build_next_block() self.update_witness_block_with_transactions(block, [tx2, tx3]) - self.test_node.test_witness_block(block, accepted=True) + test_witness_block(self.nodes[0].rpc, self.test_node, block, accepted=True) sync_blocks(self.nodes) # Add utxo to our list @@ -1206,7 +1212,7 @@ class SegWitTest(BitcoinTestFramework): # This next line will rehash the coinbase and update the merkle # root, and solve. self.update_witness_block_with_transactions(block, []) - self.test_node.test_witness_block(block, accepted=True) + test_witness_block(self.nodes[0].rpc, self.test_node, block, accepted=True) spend_tx = CTransaction() spend_tx.vin = [CTxIn(COutPoint(block.vtx[0].sha256, 0), b"")] @@ -1220,13 +1226,13 @@ class SegWitTest(BitcoinTestFramework): sync_blocks(self.nodes) block2 = self.build_next_block() self.update_witness_block_with_transactions(block2, [spend_tx]) - self.test_node.test_witness_block(block2, accepted=False) + test_witness_block(self.nodes[0].rpc, self.test_node, block2, accepted=False) # Advancing one more block should allow the spend. self.nodes[0].generate(1) block2 = self.build_next_block() self.update_witness_block_with_transactions(block2, [spend_tx]) - self.test_node.test_witness_block(block2, accepted=True) + test_witness_block(self.nodes[0].rpc, self.test_node, block2, accepted=True) sync_blocks(self.nodes) @@ -1247,11 +1253,11 @@ class SegWitTest(BitcoinTestFramework): tx.vout.append(CTxOut(self.utxo[0].nValue-1000, scriptPubKey)) tx.rehash() - self.test_node.test_transaction_acceptance(tx, with_witness=True, accepted=True) + test_transaction_acceptance(self.nodes[0].rpc, self.test_node, tx, with_witness=True, accepted=True) # Mine this transaction in preparation for following tests. block = self.build_next_block() self.update_witness_block_with_transactions(block, [tx]) - self.test_node.test_witness_block(block, accepted=True) + test_witness_block(self.nodes[0].rpc, self.test_node, block, accepted=True) sync_blocks(self.nodes) self.utxo.pop(0) @@ -1268,19 +1274,19 @@ class SegWitTest(BitcoinTestFramework): # Too-large input value sign_P2PK_witness_input(witness_program, tx, 0, hashtype, prev_utxo.nValue+1, key) self.update_witness_block_with_transactions(block, [tx]) - self.test_node.test_witness_block(block, accepted=False) + test_witness_block(self.nodes[0].rpc, self.test_node, block, accepted=False) # Too-small input value sign_P2PK_witness_input(witness_program, tx, 0, hashtype, prev_utxo.nValue-1, key) block.vtx.pop() # remove last tx self.update_witness_block_with_transactions(block, [tx]) - self.test_node.test_witness_block(block, accepted=False) + test_witness_block(self.nodes[0].rpc, self.test_node, block, accepted=False) # Now try correct value sign_P2PK_witness_input(witness_program, tx, 0, hashtype, prev_utxo.nValue, key) block.vtx.pop() self.update_witness_block_with_transactions(block, [tx]) - self.test_node.test_witness_block(block, accepted=True) + test_witness_block(self.nodes[0].rpc, self.test_node, block, accepted=True) prev_utxo = UTXO(tx.sha256, 0, tx.vout[0].nValue) @@ -1304,7 +1310,7 @@ class SegWitTest(BitcoinTestFramework): block = self.build_next_block() self.update_witness_block_with_transactions(block, [tx]) - self.test_node.test_witness_block(block, accepted=True) + test_witness_block(self.nodes[0].rpc, self.test_node, block, accepted=True) block = self.build_next_block() used_sighash_single_out_of_bounds = False @@ -1346,7 +1352,7 @@ class SegWitTest(BitcoinTestFramework): # Test the block periodically, if we're close to maxblocksize if (get_virtual_size(block) > MAX_BLOCK_BASE_SIZE - 1000): self.update_witness_block_with_transactions(block, []) - self.test_node.test_witness_block(block, accepted=True) + test_witness_block(self.nodes[0].rpc, self.test_node, block, accepted=True) block = self.build_next_block() if (not used_sighash_single_out_of_bounds): @@ -1354,7 +1360,7 @@ class SegWitTest(BitcoinTestFramework): # Test the transactions we've added to the block if (len(block.vtx) > 1): self.update_witness_block_with_transactions(block, []) - self.test_node.test_witness_block(block, accepted=True) + test_witness_block(self.nodes[0].rpc, self.test_node, block, accepted=True) # Now test witness version 0 P2PKH transactions pubkeyhash = hash160(pubkey) @@ -1376,7 +1382,7 @@ class SegWitTest(BitcoinTestFramework): tx2.vin[0].scriptSig = CScript([signature, pubkey]) block = self.build_next_block() self.update_witness_block_with_transactions(block, [tx, tx2]) - self.test_node.test_witness_block(block, accepted=False) + test_witness_block(self.nodes[0].rpc, self.test_node, block, accepted=False) # Move the signature to the witness. block.vtx.pop() @@ -1386,26 +1392,28 @@ class SegWitTest(BitcoinTestFramework): tx2.rehash() self.update_witness_block_with_transactions(block, [tx2]) - self.test_node.test_witness_block(block, accepted=True) + test_witness_block(self.nodes[0].rpc, self.test_node, block, accepted=True) temp_utxos.pop(0) - # Update self.utxos for later tests. Just spend everything in - # temp_utxos to a corresponding entry in self.utxos + # Update self.utxos for later tests by creating two outputs + # that consolidate all the coins in temp_utxos. + output_value = sum(i.nValue for i in temp_utxos) // 2 + tx = CTransaction() index = 0 + # Just spend to our usual anyone-can-spend output + tx.vout = [CTxOut(output_value, CScript([OP_TRUE]))] * 2 for i in temp_utxos: - # Just spend to our usual anyone-can-spend output - # Use SIGHASH_SINGLE|SIGHASH_ANYONECANPAY so we can build up + # Use SIGHASH_ALL|SIGHASH_ANYONECANPAY so we can build up # the signatures as we go. tx.vin.append(CTxIn(COutPoint(i.sha256, i.n), b"")) - tx.vout.append(CTxOut(i.nValue, CScript([OP_TRUE]))) tx.wit.vtxinwit.append(CTxInWitness()) - sign_P2PK_witness_input(witness_program, tx, index, SIGHASH_SINGLE|SIGHASH_ANYONECANPAY, i.nValue, key) + sign_P2PK_witness_input(witness_program, tx, index, SIGHASH_ALL|SIGHASH_ANYONECANPAY, i.nValue, key) index += 1 block = self.build_next_block() self.update_witness_block_with_transactions(block, [tx]) - self.test_node.test_witness_block(block, accepted=True) + test_witness_block(self.nodes[0].rpc, self.test_node, block, accepted=True) for i in range(len(tx.vout)): self.utxo.append(UTXO(tx.sha256, i, tx.vout[i].nValue)) @@ -1432,10 +1440,10 @@ class SegWitTest(BitcoinTestFramework): tx.rehash() # Verify mempool acceptance and block validity - self.test_node.test_transaction_acceptance(tx, with_witness=False, accepted=True) + test_transaction_acceptance(self.nodes[0].rpc, self.test_node, tx, with_witness=False, accepted=True) block = self.build_next_block() self.update_witness_block_with_transactions(block, [tx]) - self.test_node.test_witness_block(block, accepted=True, with_witness=segwit_activated) + test_witness_block(self.nodes[0].rpc, self.test_node, block, accepted=True, with_witness=segwit_activated) sync_blocks(self.nodes) # Now test attempts to spend the output. @@ -1449,12 +1457,12 @@ class SegWitTest(BitcoinTestFramework): # will require a witness to spend a witness program regardless of # segwit activation. Note that older bitcoind's that are not # segwit-aware would also reject this for failing CLEANSTACK. - self.test_node.test_transaction_acceptance(spend_tx, with_witness=False, accepted=False) + test_transaction_acceptance(self.nodes[0].rpc, self.test_node, spend_tx, with_witness=False, accepted=False) # Try to put the witness script in the scriptSig, should also fail. spend_tx.vin[0].scriptSig = CScript([p2wsh_pubkey, b'a']) spend_tx.rehash() - self.test_node.test_transaction_acceptance(spend_tx, with_witness=False, accepted=False) + test_transaction_acceptance(self.nodes[0].rpc, self.test_node, spend_tx, with_witness=False, accepted=False) # Now put the witness script in the witness, should succeed after # segwit activates. @@ -1464,7 +1472,7 @@ class SegWitTest(BitcoinTestFramework): spend_tx.wit.vtxinwit[0].scriptWitness.stack = [ b'a', witness_program ] # Verify mempool acceptance - self.test_node.test_transaction_acceptance(spend_tx, with_witness=True, accepted=segwit_activated) + test_transaction_acceptance(self.nodes[0].rpc, self.test_node, spend_tx, with_witness=True, accepted=segwit_activated) block = self.build_next_block() self.update_witness_block_with_transactions(block, [spend_tx]) @@ -1472,9 +1480,9 @@ class SegWitTest(BitcoinTestFramework): # should be valid. If we're after activation, then sending this with # witnesses should be valid. if segwit_activated: - self.test_node.test_witness_block(block, accepted=True) + test_witness_block(self.nodes[0].rpc, self.test_node, block, accepted=True) else: - self.test_node.test_witness_block(block, accepted=True, with_witness=False) + test_witness_block(self.nodes[0].rpc, self.test_node, block, accepted=True, with_witness=False) # Update self.utxo self.utxo.pop(0) @@ -1558,7 +1566,7 @@ class SegWitTest(BitcoinTestFramework): block_1 = self.build_next_block() self.update_witness_block_with_transactions(block_1, [tx]) - self.test_node.test_witness_block(block_1, accepted=True) + test_witness_block(self.nodes[0].rpc, self.test_node, block_1, accepted=True) tx2 = CTransaction() # If we try to spend the first n-1 outputs from tx, that should be @@ -1575,7 +1583,7 @@ class SegWitTest(BitcoinTestFramework): block_2 = self.build_next_block() self.update_witness_block_with_transactions(block_2, [tx2]) - self.test_node.test_witness_block(block_2, accepted=False) + test_witness_block(self.nodes[0].rpc, self.test_node, block_2, accepted=False) # Try dropping the last input in tx2, and add an output that has # too many sigops (contributing to legacy sigop count). @@ -1588,14 +1596,14 @@ class SegWitTest(BitcoinTestFramework): tx2.rehash() block_3 = self.build_next_block() self.update_witness_block_with_transactions(block_3, [tx2]) - self.test_node.test_witness_block(block_3, accepted=False) + test_witness_block(self.nodes[0].rpc, self.test_node, block_3, accepted=False) # If we drop the last checksig in this output, the tx should succeed. block_4 = self.build_next_block() tx2.vout[-1].scriptPubKey = CScript([OP_CHECKSIG]*(checksig_count-1)) tx2.rehash() self.update_witness_block_with_transactions(block_4, [tx2]) - self.test_node.test_witness_block(block_4, accepted=True) + test_witness_block(self.nodes[0].rpc, self.test_node, block_4, accepted=True) # Reset the tip back down for the next test sync_blocks(self.nodes) @@ -1611,7 +1619,7 @@ class SegWitTest(BitcoinTestFramework): tx2.wit.vtxinwit[-1].scriptWitness.stack = [ witness_program_justright ] tx2.rehash() self.update_witness_block_with_transactions(block_5, [tx2]) - self.test_node.test_witness_block(block_5, accepted=True) + test_witness_block(self.nodes[0].rpc, self.test_node, block_5, accepted=True) # TODO: test p2sh sigop counting @@ -1689,7 +1697,7 @@ class SegWitTest(BitcoinTestFramework): # Confirm it in a block. block = self.build_next_block() self.update_witness_block_with_transactions(block, [tx]) - self.test_node.test_witness_block(block, accepted=True) + test_witness_block(self.nodes[0].rpc, self.test_node, block, accepted=True) # Now try to spend it. Send it to a P2WSH output, which we'll # use in the next test. @@ -1708,11 +1716,11 @@ class SegWitTest(BitcoinTestFramework): tx2.rehash() # Should fail policy test. - self.test_node.test_transaction_acceptance(tx2, True, False, b'non-mandatory-script-verify-flag (Using non-compressed keys in segwit)') + test_transaction_acceptance(self.nodes[0].rpc, self.test_node, tx2, True, False, b'non-mandatory-script-verify-flag (Using non-compressed keys in segwit)') # But passes consensus. block = self.build_next_block() self.update_witness_block_with_transactions(block, [tx2]) - self.test_node.test_witness_block(block, accepted=True) + test_witness_block(self.nodes[0].rpc, self.test_node, block, accepted=True) # Test 2: P2WSH # Try to spend the P2WSH output created in last test. @@ -1728,11 +1736,11 @@ class SegWitTest(BitcoinTestFramework): sign_P2PK_witness_input(witness_program, tx3, 0, SIGHASH_ALL, tx2.vout[0].nValue, key) # Should fail policy test. - self.test_node.test_transaction_acceptance(tx3, True, False, b'non-mandatory-script-verify-flag (Using non-compressed keys in segwit)') + test_transaction_acceptance(self.nodes[0].rpc, self.test_node, tx3, True, False, b'non-mandatory-script-verify-flag (Using non-compressed keys in segwit)') # But passes consensus. block = self.build_next_block() self.update_witness_block_with_transactions(block, [tx3]) - self.test_node.test_witness_block(block, accepted=True) + test_witness_block(self.nodes[0].rpc, self.test_node, block, accepted=True) # Test 3: P2SH(P2WSH) # Try to spend the P2SH output created in the last test. @@ -1745,10 +1753,10 @@ class SegWitTest(BitcoinTestFramework): sign_P2PK_witness_input(witness_program, tx4, 0, SIGHASH_ALL, tx3.vout[0].nValue, key) # Should fail policy test. - self.test_node.test_transaction_acceptance(tx4, True, False, b'non-mandatory-script-verify-flag (Using non-compressed keys in segwit)') + test_transaction_acceptance(self.nodes[0].rpc, self.test_node, tx4, True, False, b'non-mandatory-script-verify-flag (Using non-compressed keys in segwit)') block = self.build_next_block() self.update_witness_block_with_transactions(block, [tx4]) - self.test_node.test_witness_block(block, accepted=True) + test_witness_block(self.nodes[0].rpc, self.test_node, block, accepted=True) # Test 4: Uncompressed pubkeys should still be valid in non-segwit # transactions. @@ -1760,10 +1768,10 @@ class SegWitTest(BitcoinTestFramework): tx5.vin[0].scriptSig = CScript([signature, pubkey]) tx5.rehash() # Should pass policy and consensus. - self.test_node.test_transaction_acceptance(tx5, True, True) + test_transaction_acceptance(self.nodes[0].rpc, self.test_node, tx5, True, True) block = self.build_next_block() self.update_witness_block_with_transactions(block, [tx5]) - self.test_node.test_witness_block(block, accepted=True) + test_witness_block(self.nodes[0].rpc, self.test_node, block, accepted=True) self.utxo.append(UTXO(tx5.sha256, 0, tx5.vout[0].nValue)) def test_non_standard_witness(self): @@ -1793,7 +1801,7 @@ class SegWitTest(BitcoinTestFramework): tx.vout.append(CTxOut(outputvalue, CScript([OP_HASH160, p2sh, OP_EQUAL]))) tx.rehash() txid = tx.sha256 - self.test_node.test_transaction_acceptance(tx, with_witness=False, accepted=True) + test_transaction_acceptance(self.nodes[0].rpc, self.test_node, tx, with_witness=False, accepted=True) self.nodes[0].generate(1) sync_blocks(self.nodes) @@ -1818,45 +1826,45 @@ class SegWitTest(BitcoinTestFramework): # Testing native P2WSH # Witness stack size, excluding witnessScript, over 100 is non-standard p2wsh_txs[0].wit.vtxinwit[0].scriptWitness.stack = [pad] * 101 + [scripts[0]] - self.std_node.test_transaction_acceptance(p2wsh_txs[0], True, False, b'bad-witness-nonstandard') + test_transaction_acceptance(self.nodes[1].rpc, self.std_node, p2wsh_txs[0], True, False, b'bad-witness-nonstandard') # Non-standard nodes should accept - self.test_node.test_transaction_acceptance(p2wsh_txs[0], True, True) + test_transaction_acceptance(self.nodes[0].rpc, self.test_node, p2wsh_txs[0], True, True) # Stack element size over 80 bytes is non-standard p2wsh_txs[1].wit.vtxinwit[0].scriptWitness.stack = [pad * 81] * 100 + [scripts[1]] - self.std_node.test_transaction_acceptance(p2wsh_txs[1], True, False, b'bad-witness-nonstandard') + test_transaction_acceptance(self.nodes[1].rpc, self.std_node, p2wsh_txs[1], True, False, b'bad-witness-nonstandard') # Non-standard nodes should accept - self.test_node.test_transaction_acceptance(p2wsh_txs[1], True, True) + test_transaction_acceptance(self.nodes[0].rpc, self.test_node, p2wsh_txs[1], True, True) # Standard nodes should accept if element size is not over 80 bytes p2wsh_txs[1].wit.vtxinwit[0].scriptWitness.stack = [pad * 80] * 100 + [scripts[1]] - self.std_node.test_transaction_acceptance(p2wsh_txs[1], True, True) + test_transaction_acceptance(self.nodes[1].rpc, self.std_node, p2wsh_txs[1], True, True) # witnessScript size at 3600 bytes is standard p2wsh_txs[2].wit.vtxinwit[0].scriptWitness.stack = [pad, pad, scripts[2]] - self.test_node.test_transaction_acceptance(p2wsh_txs[2], True, True) - self.std_node.test_transaction_acceptance(p2wsh_txs[2], True, True) + test_transaction_acceptance(self.nodes[0].rpc, self.test_node, p2wsh_txs[2], True, True) + test_transaction_acceptance(self.nodes[1].rpc, self.std_node, p2wsh_txs[2], True, True) # witnessScript size at 3601 bytes is non-standard p2wsh_txs[3].wit.vtxinwit[0].scriptWitness.stack = [pad, pad, pad, scripts[3]] - self.std_node.test_transaction_acceptance(p2wsh_txs[3], True, False, b'bad-witness-nonstandard') + test_transaction_acceptance(self.nodes[1].rpc, self.std_node, p2wsh_txs[3], True, False, b'bad-witness-nonstandard') # Non-standard nodes should accept - self.test_node.test_transaction_acceptance(p2wsh_txs[3], True, True) + test_transaction_acceptance(self.nodes[0].rpc, self.test_node, p2wsh_txs[3], True, True) # Repeating the same tests with P2SH-P2WSH p2sh_txs[0].wit.vtxinwit[0].scriptWitness.stack = [pad] * 101 + [scripts[0]] - self.std_node.test_transaction_acceptance(p2sh_txs[0], True, False, b'bad-witness-nonstandard') - self.test_node.test_transaction_acceptance(p2sh_txs[0], True, True) + test_transaction_acceptance(self.nodes[1].rpc, self.std_node, p2sh_txs[0], True, False, b'bad-witness-nonstandard') + test_transaction_acceptance(self.nodes[0].rpc, self.test_node, p2sh_txs[0], True, True) p2sh_txs[1].wit.vtxinwit[0].scriptWitness.stack = [pad * 81] * 100 + [scripts[1]] - self.std_node.test_transaction_acceptance(p2sh_txs[1], True, False, b'bad-witness-nonstandard') - self.test_node.test_transaction_acceptance(p2sh_txs[1], True, True) + test_transaction_acceptance(self.nodes[1].rpc, self.std_node, p2sh_txs[1], True, False, b'bad-witness-nonstandard') + test_transaction_acceptance(self.nodes[0].rpc, self.test_node, p2sh_txs[1], True, True) p2sh_txs[1].wit.vtxinwit[0].scriptWitness.stack = [pad * 80] * 100 + [scripts[1]] - self.std_node.test_transaction_acceptance(p2sh_txs[1], True, True) + test_transaction_acceptance(self.nodes[1].rpc, self.std_node, p2sh_txs[1], True, True) p2sh_txs[2].wit.vtxinwit[0].scriptWitness.stack = [pad, pad, scripts[2]] - self.test_node.test_transaction_acceptance(p2sh_txs[2], True, True) - self.std_node.test_transaction_acceptance(p2sh_txs[2], True, True) + test_transaction_acceptance(self.nodes[0].rpc, self.test_node, p2sh_txs[2], True, True) + test_transaction_acceptance(self.nodes[1].rpc, self.std_node, p2sh_txs[2], True, True) p2sh_txs[3].wit.vtxinwit[0].scriptWitness.stack = [pad, pad, pad, scripts[3]] - self.std_node.test_transaction_acceptance(p2sh_txs[3], True, False, b'bad-witness-nonstandard') - self.test_node.test_transaction_acceptance(p2sh_txs[3], True, True) + test_transaction_acceptance(self.nodes[1].rpc, self.std_node, p2sh_txs[3], True, False, b'bad-witness-nonstandard') + test_transaction_acceptance(self.nodes[0].rpc, self.test_node, p2sh_txs[3], True, True) self.nodes[0].generate(1) # Mine and clean up the mempool of non-standard node # Valid but non-standard transactions in a block should be accepted by standard node @@ -1870,13 +1878,13 @@ class SegWitTest(BitcoinTestFramework): def run_test(self): # Setup the p2p connections and start up the network thread. # self.test_node sets NODE_WITNESS|NODE_NETWORK - self.test_node = self.nodes[0].add_p2p_connection(TestNode(self.nodes[0].rpc), services=NODE_NETWORK|NODE_WITNESS) + self.test_node = self.nodes[0].add_p2p_connection(TestNode(), services=NODE_NETWORK|NODE_WITNESS) # self.old_node sets only NODE_NETWORK - self.old_node = self.nodes[0].add_p2p_connection(TestNode(self.nodes[0].rpc), services=NODE_NETWORK) + self.old_node = self.nodes[0].add_p2p_connection(TestNode(), services=NODE_NETWORK) # self.std_node is for testing node1 (fRequireStandard=true) - self.std_node = self.nodes[1].add_p2p_connection(TestNode(self.nodes[1].rpc), services=NODE_NETWORK|NODE_WITNESS) + self.std_node = self.nodes[1].add_p2p_connection(TestNode(), services=NODE_NETWORK|NODE_WITNESS) - NetworkThread().start() # Start up network handling in another thread + network_thread_start() # Keep a place to store utxo's that can be used in later tests self.utxo = [] diff --git a/test/functional/sendheaders.py b/test/functional/p2p_sendheaders.py index 55bb80ea00..8869aeaaea 100755 --- a/test/functional/sendheaders.py +++ b/test/functional/p2p_sendheaders.py @@ -1,14 +1,16 @@ #!/usr/bin/env python3 -# Copyright (c) 2014-2016 The Bitcoin Core developers +# Copyright (c) 2014-2017 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 behavior of headers messages to announce blocks. -Setup: +Setup: -- Two nodes, two p2p connections to node0. One p2p connection should only ever - receive inv's (omitted from testing description below, this is our control). - Second node is used for creating reorgs. +- Two nodes: + - node0 is the node-under-test. We create two p2p connections to it. The + first p2p connection is a control and should only ever receive inv's. The + second p2p connection tests the headers sending logic. + - node1 is used to create reorgs. test_null_locators ================== @@ -83,146 +85,160 @@ d. Announce 49 headers that don't connect. e. Announce one more that doesn't connect. Expect: disconnect. """ - -from test_framework.mininode import * -from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import * from test_framework.blocktools import create_block, create_coinbase +from test_framework.mininode import ( + CBlockHeader, + CInv, + NODE_WITNESS, + network_thread_start, + P2PInterface, + mininode_lock, + msg_block, + msg_getblocks, + msg_getdata, + msg_getheaders, + msg_headers, + msg_inv, + msg_sendheaders, +) +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import ( + assert_equal, + sync_blocks, + wait_until, +) +DIRECT_FETCH_RESPONSE_TIME = 0.05 -direct_fetch_response_time = 0.05 - -class TestNode(NodeConnCB): +class BaseNode(P2PInterface): def __init__(self): super().__init__() + self.block_announced = False self.last_blockhash_announced = None - def clear_last_announcement(self): - with mininode_lock: - self.block_announced = False - self.last_message.pop("inv", None) - self.last_message.pop("headers", None) - - # Request data for a list of block hashes - def get_data(self, block_hashes): + def send_get_data(self, block_hashes): + """Request data for a list of block hashes.""" msg = msg_getdata() for x in block_hashes: msg.inv.append(CInv(2, x)) - self.connection.send_message(msg) + self.send_message(msg) - def get_headers(self, locator, hashstop): + def send_get_headers(self, locator, hashstop): msg = msg_getheaders() msg.locator.vHave = locator msg.hashstop = hashstop - self.connection.send_message(msg) + self.send_message(msg) def send_block_inv(self, blockhash): msg = msg_inv() msg.inv = [CInv(2, blockhash)] - self.connection.send_message(msg) + self.send_message(msg) + + def send_header_for_blocks(self, new_blocks): + headers_message = msg_headers() + headers_message.headers = [CBlockHeader(b) for b in new_blocks] + self.send_message(headers_message) - def on_inv(self, conn, message): + def send_getblocks(self, locator): + getblocks_message = msg_getblocks() + getblocks_message.locator.vHave = locator + self.send_message(getblocks_message) + + def wait_for_getdata(self, hash_list, timeout=60): + if hash_list == []: + return + + test_function = lambda: "getdata" in self.last_message and [x.hash for x in self.last_message["getdata"].inv] == hash_list + wait_until(test_function, timeout=timeout, lock=mininode_lock) + + def wait_for_block_announcement(self, block_hash, timeout=60): + test_function = lambda: self.last_blockhash_announced == block_hash + wait_until(test_function, timeout=timeout, lock=mininode_lock) + + def on_inv(self, message): self.block_announced = True self.last_blockhash_announced = message.inv[-1].hash - def on_headers(self, conn, message): + def on_headers(self, message): if len(message.headers): self.block_announced = True message.headers[-1].calc_sha256() self.last_blockhash_announced = message.headers[-1].sha256 - # Test whether the last announcement we received had the - # right header or the right inv - # inv and headers should be lists of block hashes + def clear_last_announcement(self): + with mininode_lock: + self.block_announced = False + self.last_message.pop("inv", None) + self.last_message.pop("headers", None) + def check_last_announcement(self, headers=None, inv=None): - expect_headers = headers if headers != None else [] - expect_inv = inv if inv != None else [] + """Test whether the last announcement received had the right header or the right inv. + + inv and headers should be lists of block hashes.""" + test_function = lambda: self.block_announced wait_until(test_function, timeout=60, lock=mininode_lock) + with mininode_lock: self.block_announced = False - success = True compare_inv = [] if "inv" in self.last_message: compare_inv = [x.hash for x in self.last_message["inv"].inv] - if compare_inv != expect_inv: - success = False + if inv is not None: + assert_equal(compare_inv, inv) - hash_headers = [] + compare_headers = [] if "headers" in self.last_message: - # treat headers as a list of block hashes - hash_headers = [ x.sha256 for x in self.last_message["headers"].headers ] - if hash_headers != expect_headers: - success = False + compare_headers = [x.sha256 for x in self.last_message["headers"].headers] + if headers is not None: + assert_equal(compare_headers, headers) self.last_message.pop("inv", None) self.last_message.pop("headers", None) - return success - - def wait_for_getdata(self, hash_list, timeout=60): - if hash_list == []: - return - - test_function = lambda: "getdata" in self.last_message and [x.hash for x in self.last_message["getdata"].inv] == hash_list - wait_until(test_function, timeout=timeout, lock=mininode_lock) - return - - def wait_for_block_announcement(self, block_hash, timeout=60): - test_function = lambda: self.last_blockhash_announced == block_hash - wait_until(test_function, timeout=timeout, lock=mininode_lock) - return - - def send_header_for_blocks(self, new_blocks): - headers_message = msg_headers() - headers_message.headers = [ CBlockHeader(b) for b in new_blocks ] - self.send_message(headers_message) - - def send_getblocks(self, locator): - getblocks_message = msg_getblocks() - getblocks_message.locator.vHave = locator - self.send_message(getblocks_message) class SendHeadersTest(BitcoinTestFramework): def set_test_params(self): self.setup_clean_chain = True self.num_nodes = 2 - # mine count blocks and return the new tip def mine_blocks(self, count): + """Mine count blocks and return the new tip.""" + # Clear out last block announcement from each p2p listener [x.clear_last_announcement() for x in self.nodes[0].p2ps] self.nodes[0].generate(count) return int(self.nodes[0].getbestblockhash(), 16) - # mine a reorg that invalidates length blocks (replacing them with - # length+1 blocks). - # Note: we clear the state of our p2p connections after the - # to-be-reorged-out blocks are mined, so that we don't break later tests. - # return the list of block hashes newly mined def mine_reorg(self, length): - self.nodes[0].generate(length) # make sure all invalidated blocks are node0's + """Mine a reorg that invalidates length blocks (replacing them with # length+1 blocks). + + Note: we clear the state of our p2p connections after the + to-be-reorged-out blocks are mined, so that we don't break later tests. + return the list of block hashes newly mined.""" + + self.nodes[0].generate(length) # make sure all invalidated blocks are node0's sync_blocks(self.nodes, wait=0.1) for x in self.nodes[0].p2ps: x.wait_for_block_announcement(int(self.nodes[0].getbestblockhash(), 16)) x.clear_last_announcement() tip_height = self.nodes[1].getblockcount() - hash_to_invalidate = self.nodes[1].getblockhash(tip_height-(length-1)) + hash_to_invalidate = self.nodes[1].getblockhash(tip_height - (length - 1)) self.nodes[1].invalidateblock(hash_to_invalidate) - all_hashes = self.nodes[1].generate(length+1) # Must be longer than the orig chain + all_hashes = self.nodes[1].generate(length + 1) # Must be longer than the orig chain sync_blocks(self.nodes, wait=0.1) return [int(x, 16) for x in all_hashes] def run_test(self): # Setup the p2p connections and start up the network thread. - inv_node = self.nodes[0].add_p2p_connection(TestNode()) - # Set nServices to 0 for test_node, so no block download will occur outside of - # direct fetching - test_node = self.nodes[0].add_p2p_connection(TestNode(), services=NODE_WITNESS) + inv_node = self.nodes[0].add_p2p_connection(BaseNode()) + # Make sure NODE_NETWORK is not set for test_node, so no block download + # will occur outside of direct fetching + test_node = self.nodes[0].add_p2p_connection(BaseNode(), services=NODE_WITNESS) - NetworkThread().start() # Start up network handling in another thread + network_thread_start() # Test logic begins here inv_node.wait_for_verack() @@ -232,27 +248,32 @@ class SendHeadersTest(BitcoinTestFramework): inv_node.sync_with_ping() test_node.sync_with_ping() - self.test_null_locators(test_node) + self.test_null_locators(test_node, inv_node) self.test_nonnull_locators(test_node, inv_node) - def test_null_locators(self, test_node): + def test_null_locators(self, test_node, inv_node): tip = self.nodes[0].getblockheader(self.nodes[0].generate(1)[0]) tip_hash = int(tip["hash"], 16) + inv_node.check_last_announcement(inv=[tip_hash], headers=[]) + test_node.check_last_announcement(inv=[tip_hash], headers=[]) + self.log.info("Verify getheaders with null locator and valid hashstop returns headers.") test_node.clear_last_announcement() - test_node.get_headers(locator=[], hashstop=tip_hash) - assert_equal(test_node.check_last_announcement(headers=[tip_hash]), True) + test_node.send_get_headers(locator=[], hashstop=tip_hash) + test_node.check_last_announcement(headers=[tip_hash]) self.log.info("Verify getheaders with null locator and invalid hashstop does not return headers.") block = create_block(int(tip["hash"], 16), create_coinbase(tip["height"] + 1), tip["mediantime"] + 1) block.solve() test_node.send_header_for_blocks([block]) test_node.clear_last_announcement() - test_node.get_headers(locator=[], hashstop=int(block.hash, 16)) + test_node.send_get_headers(locator=[], hashstop=int(block.hash, 16)) test_node.sync_with_ping() assert_equal(test_node.block_announced, False) + inv_node.clear_last_announcement() test_node.send_message(msg_block(block)) + inv_node.check_last_announcement(inv=[int(block.hash, 16)], headers=[]) def test_nonnull_locators(self, test_node, inv_node): tip = int(self.nodes[0].getbestblockhash(), 16) @@ -263,30 +284,30 @@ class SendHeadersTest(BitcoinTestFramework): for i in range(4): old_tip = tip tip = self.mine_blocks(1) - assert_equal(inv_node.check_last_announcement(inv=[tip]), True) - assert_equal(test_node.check_last_announcement(inv=[tip]), True) + inv_node.check_last_announcement(inv=[tip], headers=[]) + test_node.check_last_announcement(inv=[tip], headers=[]) # Try a few different responses; none should affect next announcement if i == 0: # first request the block - test_node.get_data([tip]) + test_node.send_get_data([tip]) test_node.wait_for_block(tip) elif i == 1: # next try requesting header and block - test_node.get_headers(locator=[old_tip], hashstop=tip) - test_node.get_data([tip]) + test_node.send_get_headers(locator=[old_tip], hashstop=tip) + test_node.send_get_data([tip]) test_node.wait_for_block(tip) - test_node.clear_last_announcement() # since we requested headers... + test_node.clear_last_announcement() # since we requested headers... elif i == 2: # this time announce own block via headers height = self.nodes[0].getblockcount() last_time = self.nodes[0].getblock(self.nodes[0].getbestblockhash())['time'] block_time = last_time + 1 - new_block = create_block(tip, create_coinbase(height+1), block_time) + new_block = create_block(tip, create_coinbase(height + 1), block_time) new_block.solve() test_node.send_header_for_blocks([new_block]) test_node.wait_for_getdata([new_block.sha256]) test_node.send_message(msg_block(new_block)) - test_node.sync_with_ping() # make sure this block is processed + test_node.sync_with_ping() # make sure this block is processed inv_node.clear_last_announcement() test_node.clear_last_announcement() @@ -297,15 +318,15 @@ class SendHeadersTest(BitcoinTestFramework): # commence and keep working. test_node.send_message(msg_sendheaders()) prev_tip = int(self.nodes[0].getbestblockhash(), 16) - test_node.get_headers(locator=[prev_tip], hashstop=0) + test_node.send_get_headers(locator=[prev_tip], hashstop=0) test_node.sync_with_ping() # Now that we've synced headers, headers announcements should work tip = self.mine_blocks(1) - assert_equal(inv_node.check_last_announcement(inv=[tip]), True) - assert_equal(test_node.check_last_announcement(headers=[tip]), True) + inv_node.check_last_announcement(inv=[tip], headers=[]) + test_node.check_last_announcement(headers=[tip]) - height = self.nodes[0].getblockcount()+1 + height = self.nodes[0].getblockcount() + 1 block_time += 10 # Advance far enough ahead for i in range(10): # Mine i blocks, and alternate announcing either via @@ -314,7 +335,7 @@ class SendHeadersTest(BitcoinTestFramework): # with block header, even though the blocks are never requested for j in range(2): blocks = [] - for b in range(i+1): + for b in range(i + 1): blocks.append(create_block(tip, create_coinbase(height), block_time)) blocks[-1].solve() tip = blocks[-1].sha256 @@ -328,7 +349,7 @@ class SendHeadersTest(BitcoinTestFramework): test_node.send_header_for_blocks(blocks) # Test that duplicate inv's won't result in duplicate # getdata requests, or duplicate headers announcements - [ inv_node.send_block_inv(x.sha256) for x in blocks ] + [inv_node.send_block_inv(x.sha256) for x in blocks] test_node.wait_for_getdata([x.sha256 for x in blocks]) inv_node.sync_with_ping() else: @@ -339,7 +360,7 @@ class SendHeadersTest(BitcoinTestFramework): # getdata requests (the check is further down) inv_node.send_header_for_blocks(blocks) inv_node.sync_with_ping() - [ test_node.send_message(msg_block(x)) for x in blocks ] + [test_node.send_message(msg_block(x)) for x in blocks] test_node.sync_with_ping() inv_node.sync_with_ping() # This block should not be announced to the inv node (since it also @@ -347,8 +368,8 @@ class SendHeadersTest(BitcoinTestFramework): assert "inv" not in inv_node.last_message assert "headers" not in inv_node.last_message tip = self.mine_blocks(1) - assert_equal(inv_node.check_last_announcement(inv=[tip]), True) - assert_equal(test_node.check_last_announcement(headers=[tip]), True) + inv_node.check_last_announcement(inv=[tip], headers=[]) + test_node.check_last_announcement(headers=[tip]) height += 1 block_time += 1 @@ -362,16 +383,16 @@ class SendHeadersTest(BitcoinTestFramework): # First try mining a reorg that can propagate with header announcement new_block_hashes = self.mine_reorg(length=7) tip = new_block_hashes[-1] - assert_equal(inv_node.check_last_announcement(inv=[tip]), True) - assert_equal(test_node.check_last_announcement(headers=new_block_hashes), True) + inv_node.check_last_announcement(inv=[tip], headers=[]) + test_node.check_last_announcement(headers=new_block_hashes) - block_time += 8 + block_time += 8 # Mine a too-large reorg, which should be announced with a single inv new_block_hashes = self.mine_reorg(length=8) tip = new_block_hashes[-1] - assert_equal(inv_node.check_last_announcement(inv=[tip]), True) - assert_equal(test_node.check_last_announcement(inv=[tip]), True) + inv_node.check_last_announcement(inv=[tip], headers=[]) + test_node.check_last_announcement(inv=[tip], headers=[]) block_time += 9 @@ -379,42 +400,42 @@ class SendHeadersTest(BitcoinTestFramework): fork_point = int(fork_point, 16) # Use getblocks/getdata - test_node.send_getblocks(locator = [fork_point]) - assert_equal(test_node.check_last_announcement(inv=new_block_hashes), True) - test_node.get_data(new_block_hashes) + test_node.send_getblocks(locator=[fork_point]) + test_node.check_last_announcement(inv=new_block_hashes, headers=[]) + test_node.send_get_data(new_block_hashes) test_node.wait_for_block(new_block_hashes[-1]) for i in range(3): # Mine another block, still should get only an inv tip = self.mine_blocks(1) - assert_equal(inv_node.check_last_announcement(inv=[tip]), True) - assert_equal(test_node.check_last_announcement(inv=[tip]), True) + inv_node.check_last_announcement(inv=[tip], headers=[]) + test_node.check_last_announcement(inv=[tip], headers=[]) if i == 0: # Just get the data -- shouldn't cause headers announcements to resume - test_node.get_data([tip]) + test_node.send_get_data([tip]) test_node.wait_for_block(tip) elif i == 1: # Send a getheaders message that shouldn't trigger headers announcements # to resume (best header sent will be too old) - test_node.get_headers(locator=[fork_point], hashstop=new_block_hashes[1]) - test_node.get_data([tip]) + test_node.send_get_headers(locator=[fork_point], hashstop=new_block_hashes[1]) + test_node.send_get_data([tip]) test_node.wait_for_block(tip) elif i == 2: - test_node.get_data([tip]) + test_node.send_get_data([tip]) test_node.wait_for_block(tip) # This time, try sending either a getheaders to trigger resumption - # of headers announcements, or mine a new block and inv it, also + # of headers announcements, or mine a new block and inv it, also # triggering resumption of headers announcements. if j == 0: - test_node.get_headers(locator=[tip], hashstop=0) + test_node.send_get_headers(locator=[tip], hashstop=0) test_node.sync_with_ping() else: test_node.send_block_inv(tip) test_node.sync_with_ping() # New blocks should now be announced with header tip = self.mine_blocks(1) - assert_equal(inv_node.check_last_announcement(inv=[tip]), True) - assert_equal(test_node.check_last_announcement(headers=[tip]), True) + inv_node.check_last_announcement(inv=[tip], headers=[]) + test_node.check_last_announcement(headers=[tip]) self.log.info("Part 3: success!") @@ -434,7 +455,7 @@ class SendHeadersTest(BitcoinTestFramework): height += 1 inv_node.send_message(msg_block(blocks[-1])) - inv_node.sync_with_ping() # Make sure blocks are processed + inv_node.sync_with_ping() # Make sure blocks are processed test_node.last_message.pop("getdata", None) test_node.send_header_for_blocks(blocks) test_node.sync_with_ping() @@ -453,9 +474,9 @@ class SendHeadersTest(BitcoinTestFramework): test_node.send_header_for_blocks(blocks) test_node.sync_with_ping() - test_node.wait_for_getdata([x.sha256 for x in blocks], timeout=direct_fetch_response_time) + test_node.wait_for_getdata([x.sha256 for x in blocks], timeout=DIRECT_FETCH_RESPONSE_TIME) - [ test_node.send_message(msg_block(x)) for x in blocks ] + [test_node.send_message(msg_block(x)) for x in blocks] test_node.sync_with_ping() @@ -484,13 +505,13 @@ class SendHeadersTest(BitcoinTestFramework): # both blocks (same work as tip) test_node.send_header_for_blocks(blocks[1:2]) test_node.sync_with_ping() - test_node.wait_for_getdata([x.sha256 for x in blocks[0:2]], timeout=direct_fetch_response_time) + test_node.wait_for_getdata([x.sha256 for x in blocks[0:2]], timeout=DIRECT_FETCH_RESPONSE_TIME) # Announcing 16 more headers should trigger direct fetch for 14 more # blocks test_node.send_header_for_blocks(blocks[2:18]) test_node.sync_with_ping() - test_node.wait_for_getdata([x.sha256 for x in blocks[2:16]], timeout=direct_fetch_response_time) + test_node.wait_for_getdata([x.sha256 for x in blocks[2:16]], timeout=DIRECT_FETCH_RESPONSE_TIME) # Announcing 1 more header should not trigger any response test_node.last_message.pop("getdata", None) @@ -502,7 +523,7 @@ class SendHeadersTest(BitcoinTestFramework): self.log.info("Part 4: success!") # Now deliver all those blocks we announced. - [ test_node.send_message(msg_block(x)) for x in blocks ] + [test_node.send_message(msg_block(x)) for x in blocks] self.log.info("Part 5: Testing handling of unconnecting headers") # First we test that receipt of an unconnecting header doesn't prevent @@ -524,7 +545,7 @@ class SendHeadersTest(BitcoinTestFramework): test_node.wait_for_getheaders() test_node.send_header_for_blocks(blocks) test_node.wait_for_getdata([x.sha256 for x in blocks]) - [ test_node.send_message(msg_block(x)) for x in blocks ] + [test_node.send_message(msg_block(x)) for x in blocks] test_node.sync_with_ping() assert_equal(int(self.nodes[0].getbestblockhash(), 16), blocks[1].sha256) @@ -532,7 +553,7 @@ class SendHeadersTest(BitcoinTestFramework): # Now we test that if we repeatedly don't send connecting headers, we # don't go into an infinite loop trying to get them to connect. MAX_UNCONNECTING_HEADERS = 10 - for j in range(MAX_UNCONNECTING_HEADERS+1): + for j in range(MAX_UNCONNECTING_HEADERS + 1): blocks.append(create_block(tip, create_coinbase(height), block_time)) blocks[-1].solve() tip = blocks[-1].sha256 @@ -554,11 +575,11 @@ class SendHeadersTest(BitcoinTestFramework): # Now try to see how many unconnecting headers we can send # before we get disconnected. Should be 5*MAX_UNCONNECTING_HEADERS - for i in range(5*MAX_UNCONNECTING_HEADERS - 1): + for i in range(5 * MAX_UNCONNECTING_HEADERS - 1): # Send a header that doesn't connect, check that we get a getheaders. with mininode_lock: test_node.last_message.pop("getheaders", None) - test_node.send_header_for_blocks([blocks[i%len(blocks)]]) + test_node.send_header_for_blocks([blocks[i % len(blocks)]]) test_node.wait_for_getheaders() # Eventually this stops working. diff --git a/test/functional/p2p-timeouts.py b/test/functional/p2p_timeouts.py index 14a3bf48fb..6d21095cc6 100755 --- a/test/functional/p2p-timeouts.py +++ b/test/functional/p2p_timeouts.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2016 The Bitcoin Core developers +# Copyright (c) 2016-2017 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 various net timeouts. @@ -27,8 +27,8 @@ from test_framework.mininode import * from test_framework.test_framework import BitcoinTestFramework from test_framework.util import * -class TestNode(NodeConnCB): - def on_version(self, conn, message): +class TestNode(P2PInterface): + def on_version(self, message): # Don't send a verack in response pass @@ -43,7 +43,7 @@ class TimeoutsTest(BitcoinTestFramework): no_version_node = self.nodes[0].add_p2p_connection(TestNode(), send_version=False) no_send_node = self.nodes[0].add_p2p_connection(TestNode(), send_version=False) - NetworkThread().start() # Start up network handling in another thread + network_thread_start() sleep(1) diff --git a/test/functional/p2p-acceptblock.py b/test/functional/p2p_unrequested_blocks.py index ca0e0080a1..672626f15b 100755 --- a/test/functional/p2p-acceptblock.py +++ b/test/functional/p2p_unrequested_blocks.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2015-2016 The Bitcoin Core developers +# Copyright (c) 2015-2017 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 processing of unrequested blocks. @@ -7,7 +7,7 @@ Setup: two nodes, node0+node1, not connected to each other. Node1 will have nMinimumChainWork set to 0x10, so it won't process low-work unrequested blocks. -We have one NodeConn connection to node0 called test_node, and one to node1 +We have one P2PInterface connection to node0 called test_node, and one to node1 called min_work_node. The test: @@ -79,11 +79,11 @@ class AcceptBlockTest(BitcoinTestFramework): def run_test(self): # Setup the p2p connections and start up the network thread. # test_node connects to node0 (not whitelisted) - test_node = self.nodes[0].add_p2p_connection(NodeConnCB()) - # min_work_node connects to node1 - min_work_node = self.nodes[1].add_p2p_connection(NodeConnCB()) + test_node = self.nodes[0].add_p2p_connection(P2PInterface()) + # min_work_node connects to node1 (whitelisted) + min_work_node = self.nodes[1].add_p2p_connection(P2PInterface()) - NetworkThread().start() # Start up network handling in another thread + network_thread_start() # Test logic begins here test_node.wait_for_verack() @@ -207,9 +207,13 @@ class AcceptBlockTest(BitcoinTestFramework): # disconnect/reconnect first self.nodes[0].disconnect_p2ps() - test_node = self.nodes[0].add_p2p_connection(NodeConnCB()) + self.nodes[1].disconnect_p2ps() + network_thread_join() + test_node = self.nodes[0].add_p2p_connection(P2PInterface()) + network_thread_start() test_node.wait_for_verack() + test_node.send_message(msg_block(block_h1f)) test_node.sync_with_ping() @@ -292,9 +296,9 @@ class AcceptBlockTest(BitcoinTestFramework): test_node.wait_for_disconnect() self.nodes[0].disconnect_p2ps() - test_node = self.nodes[0].add_p2p_connection(NodeConnCB()) + test_node = self.nodes[0].add_p2p_connection(P2PInterface()) - NetworkThread().start() # Start up network handling in another thread + network_thread_start() test_node.wait_for_verack() # We should have failed reorg and switched back to 290 (but have block 291) diff --git a/test/functional/rpcbind_test.py b/test/functional/rpc_bind.py index 0e8c3fa209..05433c7e24 100755 --- a/test/functional/rpcbind_test.py +++ b/test/functional/rpc_bind.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2014-2016 The Bitcoin Core developers +# Copyright (c) 2014-2017 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 running bitcoind with the -rpcbind and -rpcallowip options.""" diff --git a/test/functional/blockchain.py b/test/functional/rpc_blockchain.py index 49fafbc9aa..11acff4be1 100755 --- a/test/functional/blockchain.py +++ b/test/functional/rpc_blockchain.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2014-2016 The Bitcoin Core developers +# Copyright (c) 2014-2017 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 RPCs related to blockchainstate. diff --git a/test/functional/decodescript.py b/test/functional/rpc_decodescript.py index 6611da8831..1ffc570437 100755 --- a/test/functional/decodescript.py +++ b/test/functional/rpc_decodescript.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2015-2016 The Bitcoin Core developers +# Copyright (c) 2015-2017 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 decoding scripts via decodescript RPC command.""" diff --git a/test/functional/deprecated_rpc.py b/test/functional/rpc_deprecated.py index 19fd24edb9..d6f25158ef 100755 --- a/test/functional/deprecated_rpc.py +++ b/test/functional/rpc_deprecated.py @@ -10,7 +10,7 @@ class DeprecatedRpcTest(BitcoinTestFramework): def set_test_params(self): self.num_nodes = 2 self.setup_clean_chain = True - self.extra_args = [[], ["-deprecatedrpc=estimatefee"]] + self.extra_args = [[], ["-deprecatedrpc=estimatefee", "-deprecatedrpc=createmultisig"]] def run_test(self): self.log.info("estimatefee: Shows deprecated message") @@ -19,5 +19,9 @@ class DeprecatedRpcTest(BitcoinTestFramework): self.log.info("Using -deprecatedrpc=estimatefee bypasses the error") self.nodes[1].estimatefee(1) + self.log.info("Make sure that -deprecatedrpc=createmultisig allows it to take addresses") + assert_raises_rpc_error(-5, "Invalid public key", self.nodes[0].createmultisig, 1, [self.nodes[0].getnewaddress()]) + self.nodes[1].createmultisig(1, [self.nodes[1].getnewaddress()]) + if __name__ == '__main__': DeprecatedRpcTest().main() diff --git a/test/functional/fundrawtransaction.py b/test/functional/rpc_fundrawtransaction.py index d446f56d0e..5f7a0586e0 100755 --- a/test/functional/fundrawtransaction.py +++ b/test/functional/rpc_fundrawtransaction.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2014-2016 The Bitcoin Core developers +# Copyright (c) 2014-2017 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test the fundrawtransaction RPC.""" @@ -212,6 +212,19 @@ class RawTransactionsTest(BitcoinTestFramework): out = dec_tx['vout'][0] assert_equal(change, out['scriptPubKey']['addresses'][0]) + ######################################################### + # test a fundrawtransaction with a provided change type # + ######################################################### + utx = get_unspent(self.nodes[2].listunspent(), 5) + + inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']} ] + outputs = { self.nodes[0].getnewaddress() : Decimal(4.0) } + rawtx = self.nodes[2].createrawtransaction(inputs, outputs) + assert_raises_rpc_error(-1, "JSON value is not a string as expected", self.nodes[2].fundrawtransaction, rawtx, {'change_type': None}) + assert_raises_rpc_error(-5, "Unknown change type", self.nodes[2].fundrawtransaction, rawtx, {'change_type': ''}) + rawtx = self.nodes[2].fundrawtransaction(rawtx, {'change_type': 'bech32'}) + tx = self.nodes[2].decoderawtransaction(rawtx['hex']) + assert_equal('witness_v0_keyhash', tx['vout'][rawtx['changepos']]['scriptPubKey']['type']) ######################################################################### # test a fundrawtransaction with a VIN smaller than the required amount # @@ -358,7 +371,7 @@ class RawTransactionsTest(BitcoinTestFramework): addr1Obj = self.nodes[1].validateaddress(addr1) addr2Obj = self.nodes[1].validateaddress(addr2) - mSigObj = self.nodes[1].addmultisigaddress(2, [addr1Obj['pubkey'], addr2Obj['pubkey']]) + mSigObj = self.nodes[1].addmultisigaddress(2, [addr1Obj['pubkey'], addr2Obj['pubkey']])['address'] inputs = [] outputs = {mSigObj:1.1} @@ -391,7 +404,7 @@ class RawTransactionsTest(BitcoinTestFramework): addr4Obj = self.nodes[1].validateaddress(addr4) addr5Obj = self.nodes[1].validateaddress(addr5) - mSigObj = self.nodes[1].addmultisigaddress(4, [addr1Obj['pubkey'], addr2Obj['pubkey'], addr3Obj['pubkey'], addr4Obj['pubkey'], addr5Obj['pubkey']]) + mSigObj = self.nodes[1].addmultisigaddress(4, [addr1Obj['pubkey'], addr2Obj['pubkey'], addr3Obj['pubkey'], addr4Obj['pubkey'], addr5Obj['pubkey']])['address'] inputs = [] outputs = {mSigObj:1.1} @@ -418,7 +431,7 @@ class RawTransactionsTest(BitcoinTestFramework): addr1Obj = self.nodes[2].validateaddress(addr1) addr2Obj = self.nodes[2].validateaddress(addr2) - mSigObj = self.nodes[2].addmultisigaddress(2, [addr1Obj['pubkey'], addr2Obj['pubkey']]) + mSigObj = self.nodes[2].addmultisigaddress(2, [addr1Obj['pubkey'], addr2Obj['pubkey']])['address'] # send 1.2 BTC to msig addr diff --git a/test/functional/getchaintips.py b/test/functional/rpc_getchaintips.py index 21b67bfc64..277930bb1a 100755 --- a/test/functional/getchaintips.py +++ b/test/functional/rpc_getchaintips.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2014-2016 The Bitcoin Core developers +# Copyright (c) 2014-2017 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test the getchaintips RPC. diff --git a/test/functional/invalidateblock.py b/test/functional/rpc_invalidateblock.py index dd3daf1e07..b037c2431d 100755 --- a/test/functional/invalidateblock.py +++ b/test/functional/rpc_invalidateblock.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2014-2016 The Bitcoin Core developers +# Copyright (c) 2014-2017 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test the invalidateblock RPC.""" diff --git a/test/functional/listtransactions.py b/test/functional/rpc_listtransactions.py index e4522cc3b5..ba71ac0967 100755 --- a/test/functional/listtransactions.py +++ b/test/functional/rpc_listtransactions.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2014-2016 The Bitcoin Core developers +# Copyright (c) 2014-2017 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test the listtransactions API.""" @@ -81,7 +81,8 @@ class ListTransactionsTest(BitcoinTestFramework): {"category":"receive","amount":Decimal("0.44")}, {"txid":txid, "account" : "toself"} ) - multisig = self.nodes[1].createmultisig(1, [self.nodes[1].getnewaddress()]) + pubkey = self.nodes[1].validateaddress(self.nodes[1].getnewaddress())['pubkey'] + multisig = self.nodes[1].createmultisig(1, [pubkey]) self.nodes[0].importaddress(multisig["redeemScript"], "watchonly", False, True) txid = self.nodes[1].sendtoaddress(multisig["address"], 0.1) self.nodes[1].generate(1) diff --git a/test/functional/rpcnamedargs.py b/test/functional/rpc_named_arguments.py index c47212bddb..97bee39614 100755 --- a/test/functional/rpcnamedargs.py +++ b/test/functional/rpc_named_arguments.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2016 The Bitcoin Core developers +# Copyright (c) 2016-2017 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 using named arguments for RPCs.""" diff --git a/test/functional/net.py b/test/functional/rpc_net.py index 16e4f6adb4..16e4f6adb4 100755 --- a/test/functional/net.py +++ b/test/functional/rpc_net.py diff --git a/test/functional/preciousblock.py b/test/functional/rpc_preciousblock.py index 1466f901c0..960cd0ad12 100755 --- a/test/functional/preciousblock.py +++ b/test/functional/rpc_preciousblock.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2015-2016 The Bitcoin Core developers +# Copyright (c) 2015-2017 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test the preciousblock RPC.""" diff --git a/test/functional/rawtransactions.py b/test/functional/rpc_rawtransaction.py index 2777cb9693..d39d86b310 100755 --- a/test/functional/rawtransactions.py +++ b/test/functional/rpc_rawtransaction.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2014-2016 The Bitcoin Core developers +# Copyright (c) 2014-2017 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test the rawtransaction RPCs. @@ -15,11 +15,31 @@ Test the following RPCs: from test_framework.test_framework import BitcoinTestFramework from test_framework.util import * + +class multidict(dict): + """Dictionary that allows duplicate keys. + + Constructed with a list of (key, value) tuples. When dumped by the json module, + will output invalid json with repeated keys, eg: + >>> json.dumps(multidict([(1,2),(1,2)]) + '{"1": 2, "1": 2}' + + Used to test calls to rpc methods with repeated keys in the json object.""" + + def __init__(self, x): + dict.__init__(self, x) + self.x = x + + def items(self): + return self.x + + # Create one-input, one-output, no-fee transaction: class RawTransactionsTest(BitcoinTestFramework): def set_test_params(self): self.setup_clean_chain = True self.num_nodes = 3 + self.extra_args = [["-addresstype=legacy"], ["-addresstype=legacy"], ["-addresstype=legacy"]] def setup_network(self, split=False): super().setup_network() @@ -39,6 +59,41 @@ class RawTransactionsTest(BitcoinTestFramework): self.nodes[0].generate(5) self.sync_all() + # Test `createrawtransaction` required parameters + assert_raises_rpc_error(-1, "createrawtransaction", self.nodes[0].createrawtransaction) + assert_raises_rpc_error(-1, "createrawtransaction", self.nodes[0].createrawtransaction, []) + + # Test `createrawtransaction` invalid extra parameters + assert_raises_rpc_error(-1, "createrawtransaction", self.nodes[0].createrawtransaction, [], {}, 0, False, 'foo') + + # Test `createrawtransaction` invalid `inputs` + txid = '1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000' + assert_raises_rpc_error(-3, "Expected type array", self.nodes[0].createrawtransaction, 'foo', {}) + assert_raises_rpc_error(-1, "JSON value is not an object as expected", self.nodes[0].createrawtransaction, ['foo'], {}) + assert_raises_rpc_error(-8, "txid must be hexadecimal string", self.nodes[0].createrawtransaction, [{}], {}) + assert_raises_rpc_error(-8, "txid must be hexadecimal string", self.nodes[0].createrawtransaction, [{'txid': 'foo'}], {}) + assert_raises_rpc_error(-8, "Invalid parameter, missing vout key", self.nodes[0].createrawtransaction, [{'txid': txid}], {}) + assert_raises_rpc_error(-8, "Invalid parameter, missing vout key", self.nodes[0].createrawtransaction, [{'txid': txid, 'vout': 'foo'}], {}) + assert_raises_rpc_error(-8, "Invalid parameter, vout must be positive", self.nodes[0].createrawtransaction, [{'txid': txid, 'vout': -1}], {}) + assert_raises_rpc_error(-8, "Invalid parameter, sequence number is out of range", self.nodes[0].createrawtransaction, [{'txid': txid, 'vout': 0, 'sequence': -1}], {}) + + # Test `createrawtransaction` invalid `outputs` + address = self.nodes[0].getnewaddress() + assert_raises_rpc_error(-3, "Expected type object", self.nodes[0].createrawtransaction, [], 'foo') + assert_raises_rpc_error(-8, "Data must be hexadecimal string", self.nodes[0].createrawtransaction, [], {'data': 'foo'}) + assert_raises_rpc_error(-5, "Invalid Bitcoin address", self.nodes[0].createrawtransaction, [], {'foo': 0}) + assert_raises_rpc_error(-3, "Invalid amount", self.nodes[0].createrawtransaction, [], {address: 'foo'}) + assert_raises_rpc_error(-3, "Amount out of range", self.nodes[0].createrawtransaction, [], {address: -1}) + assert_raises_rpc_error(-8, "Invalid parameter, duplicated address: %s" % address, self.nodes[0].createrawtransaction, [], multidict([(address, 1), (address, 1)])) + + # Test `createrawtransaction` invalid `locktime` + assert_raises_rpc_error(-3, "Expected type number", self.nodes[0].createrawtransaction, [], {}, 'foo') + assert_raises_rpc_error(-8, "Invalid parameter, locktime out of range", self.nodes[0].createrawtransaction, [], {}, -1) + assert_raises_rpc_error(-8, "Invalid parameter, locktime out of range", self.nodes[0].createrawtransaction, [], {}, 4294967296) + + # Test `createrawtransaction` invalid `replaceable` + assert_raises_rpc_error(-3, "Expected type bool", self.nodes[0].createrawtransaction, [], {}, 0, 'foo') + ######################################### # sendrawtransaction with missing input # ######################################### @@ -50,6 +105,36 @@ class RawTransactionsTest(BitcoinTestFramework): # This will raise an exception since there are missing inputs assert_raises_rpc_error(-25, "Missing inputs", self.nodes[2].sendrawtransaction, rawtx['hex']) + ##################################### + # getrawtransaction with block hash # + ##################################### + + # make a tx by sending then generate 2 blocks; block1 has the tx in it + tx = self.nodes[2].sendtoaddress(self.nodes[1].getnewaddress(), 1) + block1, block2 = self.nodes[2].generate(2) + self.sync_all() + # We should be able to get the raw transaction by providing the correct block + gottx = self.nodes[0].getrawtransaction(tx, True, block1) + assert_equal(gottx['txid'], tx) + assert_equal(gottx['in_active_chain'], True) + # We should not have the 'in_active_chain' flag when we don't provide a block + gottx = self.nodes[0].getrawtransaction(tx, True) + assert_equal(gottx['txid'], tx) + assert 'in_active_chain' not in gottx + # We should not get the tx if we provide an unrelated block + assert_raises_rpc_error(-5, "No such transaction found", self.nodes[0].getrawtransaction, tx, True, block2) + # An invalid block hash should raise the correct errors + assert_raises_rpc_error(-8, "parameter 3 must be hexadecimal", self.nodes[0].getrawtransaction, tx, True, True) + assert_raises_rpc_error(-8, "parameter 3 must be hexadecimal", self.nodes[0].getrawtransaction, tx, True, "foobar") + assert_raises_rpc_error(-8, "parameter 3 must be of length 64", self.nodes[0].getrawtransaction, tx, True, "abcd1234") + assert_raises_rpc_error(-5, "Block hash not found", self.nodes[0].getrawtransaction, tx, True, "0000000000000000000000000000000000000000000000000000000000000000") + # Undo the blocks and check in_active_chain + self.nodes[0].invalidateblock(block1) + gottx = self.nodes[0].getrawtransaction(txid=tx, verbose=True, blockhash=block1) + assert_equal(gottx['in_active_chain'], False) + self.nodes[0].reconsiderblock(block1) + assert_equal(self.nodes[0].getbestblockhash(), block2) + ######################### # RAW TX MULTISIG TESTS # ######################### @@ -60,7 +145,12 @@ class RawTransactionsTest(BitcoinTestFramework): addr1Obj = self.nodes[2].validateaddress(addr1) addr2Obj = self.nodes[2].validateaddress(addr2) - mSigObj = self.nodes[2].addmultisigaddress(2, [addr1Obj['pubkey'], addr2Obj['pubkey']]) + # Tests for createmultisig and addmultisigaddress + assert_raises_rpc_error(-5, "Invalid public key", self.nodes[0].createmultisig, 1, ["01020304"]) + self.nodes[0].createmultisig(2, [addr1Obj['pubkey'], addr2Obj['pubkey']]) # createmultisig can only take public keys + assert_raises_rpc_error(-5, "Invalid public key", self.nodes[0].createmultisig, 2, [addr1Obj['pubkey'], addr1]) # addmultisigaddress can take both pubkeys and addresses so long as they are in the wallet, which is tested here. + + mSigObj = self.nodes[2].addmultisigaddress(2, [addr1Obj['pubkey'], addr1])['address'] #use balance deltas instead of absolute values bal = self.nodes[2].getbalance() @@ -83,7 +173,7 @@ class RawTransactionsTest(BitcoinTestFramework): addr2Obj = self.nodes[2].validateaddress(addr2) addr3Obj = self.nodes[2].validateaddress(addr3) - mSigObj = self.nodes[2].addmultisigaddress(2, [addr1Obj['pubkey'], addr2Obj['pubkey'], addr3Obj['pubkey']]) + mSigObj = self.nodes[2].addmultisigaddress(2, [addr1Obj['pubkey'], addr2Obj['pubkey'], addr3Obj['pubkey']])['address'] txId = self.nodes[0].sendtoaddress(mSigObj, 2.2) decTx = self.nodes[0].gettransaction(txId) @@ -105,7 +195,7 @@ class RawTransactionsTest(BitcoinTestFramework): break bal = self.nodes[0].getbalance() - inputs = [{ "txid" : txId, "vout" : vout['n'], "scriptPubKey" : vout['scriptPubKey']['hex']}] + inputs = [{ "txid" : txId, "vout" : vout['n'], "scriptPubKey" : vout['scriptPubKey']['hex'], "amount" : vout['value']}] outputs = { self.nodes[0].getnewaddress() : 2.19 } rawTx = self.nodes[2].createrawtransaction(inputs, outputs) rawTxPartialSigned = self.nodes[1].signrawtransaction(rawTx, inputs) @@ -128,8 +218,8 @@ class RawTransactionsTest(BitcoinTestFramework): addr1Obj = self.nodes[1].validateaddress(addr1) addr2Obj = self.nodes[2].validateaddress(addr2) - self.nodes[1].addmultisigaddress(2, [addr1Obj['pubkey'], addr2Obj['pubkey']]) - mSigObj = self.nodes[2].addmultisigaddress(2, [addr1Obj['pubkey'], addr2Obj['pubkey']]) + self.nodes[1].addmultisigaddress(2, [addr1Obj['pubkey'], addr2Obj['pubkey']])['address'] + mSigObj = self.nodes[2].addmultisigaddress(2, [addr1Obj['pubkey'], addr2Obj['pubkey']])['address'] mSigObjValid = self.nodes[2].validateaddress(mSigObj) txId = self.nodes[0].sendtoaddress(mSigObj, 2.2) @@ -150,7 +240,7 @@ class RawTransactionsTest(BitcoinTestFramework): break bal = self.nodes[0].getbalance() - inputs = [{ "txid" : txId, "vout" : vout['n'], "scriptPubKey" : vout['scriptPubKey']['hex'], "redeemScript" : mSigObjValid['hex']}] + inputs = [{ "txid" : txId, "vout" : vout['n'], "scriptPubKey" : vout['scriptPubKey']['hex'], "redeemScript" : mSigObjValid['hex'], "amount" : vout['value']}] outputs = { self.nodes[0].getnewaddress() : 2.19 } rawTx2 = self.nodes[2].createrawtransaction(inputs, outputs) rawTxPartialSigned1 = self.nodes[1].signrawtransaction(rawTx2, inputs) @@ -169,6 +259,17 @@ class RawTransactionsTest(BitcoinTestFramework): self.sync_all() assert_equal(self.nodes[0].getbalance(), bal+Decimal('50.00000000')+Decimal('2.19000000')) #block reward + tx + # decoderawtransaction tests + # witness transaction + encrawtx = "010000000001010000000000000072c1a6a246ae63f74f931e8365e15a089c68d61900000000000000000000ffffffff0100e1f50500000000000000000000" + decrawtx = self.nodes[0].decoderawtransaction(encrawtx, True) # decode as witness transaction + assert_equal(decrawtx['vout'][0]['value'], Decimal('1.00000000')) + assert_raises_rpc_error(-22, 'TX decode failed', self.nodes[0].decoderawtransaction, encrawtx, False) # force decode as non-witness transaction + # non-witness transaction + encrawtx = "01000000010000000000000072c1a6a246ae63f74f931e8365e15a089c68d61900000000000000000000ffffffff0100e1f505000000000000000000" + decrawtx = self.nodes[0].decoderawtransaction(encrawtx, False) # decode as non-witness transaction + assert_equal(decrawtx['vout'][0]['value'], Decimal('1.00000000')) + # getrawtransaction tests # 1. valid parameters - only supply txid txHash = rawTx["hash"] @@ -188,13 +289,13 @@ class RawTransactionsTest(BitcoinTestFramework): assert_equal(self.nodes[0].getrawtransaction(txHash, True)["hex"], rawTxSigned['hex']) # 6. invalid parameters - supply txid and string "Flase" - assert_raises_rpc_error(-3,"Invalid type", self.nodes[0].getrawtransaction, txHash, "Flase") + assert_raises_rpc_error(-1, "not a boolean", self.nodes[0].getrawtransaction, txHash, "Flase") # 7. invalid parameters - supply txid and empty array - assert_raises_rpc_error(-3,"Invalid type", self.nodes[0].getrawtransaction, txHash, []) + assert_raises_rpc_error(-1, "not a boolean", self.nodes[0].getrawtransaction, txHash, []) # 8. invalid parameters - supply txid and empty dict - assert_raises_rpc_error(-3,"Invalid type", self.nodes[0].getrawtransaction, txHash, {}) + assert_raises_rpc_error(-1, "not a boolean", self.nodes[0].getrawtransaction, txHash, {}) inputs = [ {'txid' : "1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000", 'vout' : 1, 'sequence' : 1000}] outputs = { self.nodes[0].getnewaddress() : 1 } diff --git a/test/functional/signmessages.py b/test/functional/rpc_signmessage.py index 52ba6a5ad7..5b6935ceea 100755 --- a/test/functional/signmessages.py +++ b/test/functional/rpc_signmessage.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2016 The Bitcoin Core developers +# Copyright (c) 2016-2017 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 RPC commands for signing and verifying messages.""" @@ -11,6 +11,7 @@ class SignMessagesTest(BitcoinTestFramework): def set_test_params(self): self.setup_clean_chain = True self.num_nodes = 1 + self.extra_args = [["-addresstype=legacy"]] def run_test(self): message = 'This is just a test message' diff --git a/test/functional/signrawtransactions.py b/test/functional/rpc_signrawtransaction.py index 9a45d53cb8..dd0fa6c02c 100755 --- a/test/functional/signrawtransactions.py +++ b/test/functional/rpc_signrawtransaction.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2015-2016 The Bitcoin Core developers +# Copyright (c) 2015-2017 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 transaction signing using the signrawtransaction RPC.""" diff --git a/test/functional/merkle_blocks.py b/test/functional/rpc_txoutproof.py index b3989a4c54..50e0371fdf 100755 --- a/test/functional/merkle_blocks.py +++ b/test/functional/rpc_txoutproof.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2014-2016 The Bitcoin Core developers +# Copyright (c) 2014-2017 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 gettxoutproof and verifytxoutproof RPCs.""" diff --git a/test/functional/uptime.py b/test/functional/rpc_uptime.py index 78236b2393..78236b2393 100755 --- a/test/functional/uptime.py +++ b/test/functional/rpc_uptime.py diff --git a/test/functional/multi_rpc.py b/test/functional/rpc_users.py index a2b346f274..01f68344ae 100755 --- a/test/functional/multi_rpc.py +++ b/test/functional/rpc_users.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2015-2016 The Bitcoin Core developers +# Copyright (c) 2015-2017 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 multiple RPC users.""" diff --git a/test/functional/test_framework/address.py b/test/functional/test_framework/address.py index 2e2db5ffb2..b076c9dd43 100644 --- a/test/functional/test_framework/address.py +++ b/test/functional/test_framework/address.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2016 The Bitcoin Core developers +# Copyright (c) 2016-2017 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Encode and decode BASE58, P2PKH and P2SH addresses.""" diff --git a/test/functional/test_framework/blockstore.py b/test/functional/test_framework/blockstore.py index 051c57a6c7..6067a407cc 100644 --- a/test/functional/test_framework/blockstore.py +++ b/test/functional/test_framework/blockstore.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2015-2016 The Bitcoin Core developers +# Copyright (c) 2015-2017 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 and TxStore helper classes.""" diff --git a/test/functional/test_framework/blocktools.py b/test/functional/test_framework/blocktools.py index 5dcf516dc6..642ef98a27 100644 --- a/test/functional/test_framework/blocktools.py +++ b/test/functional/test_framework/blocktools.py @@ -1,11 +1,27 @@ #!/usr/bin/env python3 -# Copyright (c) 2015-2016 The Bitcoin Core developers +# Copyright (c) 2015-2017 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Utilities for manipulating blocks and transactions.""" +from .address import ( + key_to_p2sh_p2wpkh, + key_to_p2wpkh, + script_to_p2sh_p2wsh, + script_to_p2wsh, +) from .mininode import * -from .script import CScript, OP_TRUE, OP_CHECKSIG, OP_RETURN +from .script import ( + CScript, + OP_0, + OP_1, + OP_CHECKMULTISIG, + OP_CHECKSIG, + OP_RETURN, + OP_TRUE, + hash160, +) +from .util import assert_equal # Create a block (with regtest difficulty) def create_block(hashprev, coinbase, nTime=None): @@ -108,3 +124,49 @@ def get_legacy_sigopcount_tx(tx, fAccurate=True): # scriptSig might be of type bytes, so convert to CScript for the moment count += CScript(j.scriptSig).GetSigOpCount(fAccurate) return count + +# Create a scriptPubKey corresponding to either a P2WPKH output for the +# given pubkey, or a P2WSH output of a 1-of-1 multisig for the given +# pubkey. Returns the hex encoding of the scriptPubKey. +def witness_script(use_p2wsh, pubkey): + if (use_p2wsh == False): + # P2WPKH instead + pubkeyhash = hash160(hex_str_to_bytes(pubkey)) + pkscript = CScript([OP_0, pubkeyhash]) + else: + # 1-of-1 multisig + witness_program = CScript([OP_1, hex_str_to_bytes(pubkey), OP_1, OP_CHECKMULTISIG]) + scripthash = sha256(witness_program) + pkscript = CScript([OP_0, scripthash]) + return bytes_to_hex_str(pkscript) + +# Return a transaction (in hex) that spends the given utxo to a segwit output, +# optionally wrapping the segwit output using P2SH. +def create_witness_tx(node, use_p2wsh, utxo, pubkey, encode_p2sh, amount): + if use_p2wsh: + program = CScript([OP_1, hex_str_to_bytes(pubkey), OP_1, OP_CHECKMULTISIG]) + addr = script_to_p2sh_p2wsh(program) if encode_p2sh else script_to_p2wsh(program) + else: + addr = key_to_p2sh_p2wpkh(pubkey) if encode_p2sh else key_to_p2wpkh(pubkey) + if not encode_p2sh: + assert_equal(node.validateaddress(addr)['scriptPubKey'], witness_script(use_p2wsh, pubkey)) + return node.createrawtransaction([utxo], {addr: amount}) + +# Create a transaction spending a given utxo to a segwit output corresponding +# to the given pubkey: use_p2wsh determines whether to use P2WPKH or P2WSH; +# encode_p2sh determines whether to wrap in P2SH. +# sign=True will have the given node sign the transaction. +# insert_redeem_script will be added to the scriptSig, if given. +def send_to_witness(use_p2wsh, node, utxo, pubkey, encode_p2sh, amount, sign=True, insert_redeem_script=""): + tx_to_witness = create_witness_tx(node, use_p2wsh, utxo, pubkey, encode_p2sh, amount) + if (sign): + signed = node.signrawtransaction(tx_to_witness) + assert("errors" not in signed or len(["errors"]) == 0) + return node.sendrawtransaction(signed["hex"]) + else: + if (insert_redeem_script): + tx = FromHex(CTransaction(), tx_to_witness) + tx.vin[0].scriptSig += CScript([hex_str_to_bytes(insert_redeem_script)]) + tx_to_witness = ToHex(tx) + + return node.sendrawtransaction(tx_to_witness) diff --git a/test/functional/test_framework/comptool.py b/test/functional/test_framework/comptool.py index 723826bae4..61ea2280e2 100755 --- a/test/functional/test_framework/comptool.py +++ b/test/functional/test_framework/comptool.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2015-2016 The Bitcoin Core developers +# Copyright (c) 2015-2017 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Compare two or more bitcoinds to each other. @@ -39,11 +39,10 @@ class RejectResult(): def __repr__(self): return '%i:%s' % (self.code,self.reason or '*') -class TestNode(NodeConnCB): +class TestNode(P2PInterface): def __init__(self, block_store, tx_store): super().__init__() - self.conn = None self.bestblockhash = None self.block_store = block_store self.block_request_map = {} @@ -58,26 +57,23 @@ class TestNode(NodeConnCB): self.lastInv = [] self.closed = False - def on_close(self, conn): + def on_close(self): self.closed = True - def add_connection(self, conn): - self.conn = conn - - def on_headers(self, conn, message): + def on_headers(self, message): if len(message.headers) > 0: best_header = message.headers[-1] best_header.calc_sha256() self.bestblockhash = best_header.sha256 - def on_getheaders(self, conn, message): + def on_getheaders(self, message): response = self.block_store.headers_for(message.locator, message.hashstop) if response is not None: - conn.send_message(response) + self.send_message(response) - def on_getdata(self, conn, message): - [conn.send_message(r) for r in self.block_store.get_blocks(message.inv)] - [conn.send_message(r) for r in self.tx_store.get_transactions(message.inv)] + def on_getdata(self, message): + [self.send_message(r) for r in self.block_store.get_blocks(message.inv)] + [self.send_message(r) for r in self.tx_store.get_transactions(message.inv)] for i in message.inv: if i.type == 1 or i.type == 1 | (1 << 30): # MSG_TX or MSG_WITNESS_TX @@ -85,16 +81,16 @@ class TestNode(NodeConnCB): elif i.type == 2 or i.type == 2 | (1 << 30): # MSG_BLOCK or MSG_WITNESS_BLOCK self.block_request_map[i.hash] = True - def on_inv(self, conn, message): + def on_inv(self, message): self.lastInv = [x.hash for x in message.inv] - def on_pong(self, conn, message): + def on_pong(self, message): try: del self.pingMap[message.nonce] except KeyError: raise AssertionError("Got pong for unknown ping [%s]" % repr(message)) - def on_reject(self, conn, message): + def on_reject(self, message): if message.message == b'tx': self.tx_reject_map[message.data] = RejectResult(message.code, message.reason) if message.message == b'block': @@ -102,30 +98,30 @@ class TestNode(NodeConnCB): def send_inv(self, obj): mtype = 2 if isinstance(obj, CBlock) else 1 - self.conn.send_message(msg_inv([CInv(mtype, obj.sha256)])) + self.send_message(msg_inv([CInv(mtype, obj.sha256)])) def send_getheaders(self): # We ask for headers from their last tip. m = msg_getheaders() m.locator = self.block_store.get_locator(self.bestblockhash) - self.conn.send_message(m) + self.send_message(m) def send_header(self, header): m = msg_headers() m.headers.append(header) - self.conn.send_message(m) + self.send_message(m) # This assumes BIP31 def send_ping(self, nonce): self.pingMap[nonce] = True - self.conn.send_message(msg_ping(nonce)) + self.send_message(msg_ping(nonce)) def received_ping_response(self, nonce): return nonce not in self.pingMap def send_mempool(self): self.lastInv = [] - self.conn.send_message(msg_mempool()) + self.send_message(msg_mempool()) # TestInstance: # @@ -166,8 +162,7 @@ class TestManager(): def __init__(self, testgen, datadir): self.test_generator = testgen - self.connections = [] - self.test_nodes = [] + self.p2p_connections= [] self.block_store = BlockStore(datadir) self.tx_store = TxStore(datadir) self.ping_counter = 1 @@ -175,28 +170,24 @@ class TestManager(): def add_all_connections(self, nodes): for i in range(len(nodes)): # Create a p2p connection to each node - test_node = TestNode(self.block_store, self.tx_store) - self.test_nodes.append(test_node) - self.connections.append(NodeConn('127.0.0.1', p2p_port(i), test_node)) - # Make sure the TestNode (callback class) has a reference to its - # associated NodeConn - test_node.add_connection(self.connections[-1]) + node = TestNode(self.block_store, self.tx_store) + node.peer_connect('127.0.0.1', p2p_port(i)) + self.p2p_connections.append(node) def clear_all_connections(self): - self.connections = [] - self.test_nodes = [] + self.p2p_connections = [] def wait_for_disconnections(self): def disconnected(): - return all(node.closed for node in self.test_nodes) + return all(node.closed for node in self.p2p_connections) wait_until(disconnected, timeout=10, lock=mininode_lock) def wait_for_verack(self): - return all(node.wait_for_verack() for node in self.test_nodes) + return all(node.wait_for_verack() for node in self.p2p_connections) def wait_for_pings(self, counter): def received_pongs(): - return all(node.received_ping_response(counter) for node in self.test_nodes) + return all(node.received_ping_response(counter) for node in self.p2p_connections) wait_until(received_pongs, lock=mininode_lock) # sync_blocks: Wait for all connections to request the blockhash given @@ -206,17 +197,17 @@ class TestManager(): def blocks_requested(): return all( blockhash in node.block_request_map and node.block_request_map[blockhash] - for node in self.test_nodes + for node in self.p2p_connections ) # --> error if not requested wait_until(blocks_requested, attempts=20*num_blocks, lock=mininode_lock) # Send getheaders message - [ c.cb.send_getheaders() for c in self.connections ] + [ c.send_getheaders() for c in self.p2p_connections ] # Send ping and wait for response -- synchronization hack - [ c.cb.send_ping(self.ping_counter) for c in self.connections ] + [ c.send_ping(self.ping_counter) for c in self.p2p_connections ] self.wait_for_pings(self.ping_counter) self.ping_counter += 1 @@ -226,42 +217,42 @@ class TestManager(): def transaction_requested(): return all( txhash in node.tx_request_map and node.tx_request_map[txhash] - for node in self.test_nodes + for node in self.p2p_connections ) # --> error if not requested wait_until(transaction_requested, attempts=20*num_events, lock=mininode_lock) # Get the mempool - [ c.cb.send_mempool() for c in self.connections ] + [ c.send_mempool() for c in self.p2p_connections ] # Send ping and wait for response -- synchronization hack - [ c.cb.send_ping(self.ping_counter) for c in self.connections ] + [ c.send_ping(self.ping_counter) for c in self.p2p_connections ] self.wait_for_pings(self.ping_counter) self.ping_counter += 1 # Sort inv responses from each node with mininode_lock: - [ c.cb.lastInv.sort() for c in self.connections ] + [ c.lastInv.sort() for c in self.p2p_connections ] # Verify that the tip of each connection all agree with each other, and # with the expected outcome (if given) def check_results(self, blockhash, outcome): with mininode_lock: - for c in self.connections: + for c in self.p2p_connections: if outcome is None: - if c.cb.bestblockhash != self.connections[0].cb.bestblockhash: + if c.bestblockhash != self.p2p_connections[0].bestblockhash: return False elif isinstance(outcome, RejectResult): # Check that block was rejected w/ code - if c.cb.bestblockhash == blockhash: + if c.bestblockhash == blockhash: return False - if blockhash not in c.cb.block_reject_map: + if blockhash not in c.block_reject_map: logger.error('Block not in reject map: %064x' % (blockhash)) return False - if not outcome.match(c.cb.block_reject_map[blockhash]): - logger.error('Block rejected with %s instead of expected %s: %064x' % (c.cb.block_reject_map[blockhash], outcome, blockhash)) + if not outcome.match(c.block_reject_map[blockhash]): + logger.error('Block rejected with %s instead of expected %s: %064x' % (c.block_reject_map[blockhash], outcome, blockhash)) return False - elif ((c.cb.bestblockhash == blockhash) != outcome): + elif ((c.bestblockhash == blockhash) != outcome): return False return True @@ -273,21 +264,21 @@ class TestManager(): # a particular tx's existence in the mempool is the same across all nodes. def check_mempool(self, txhash, outcome): with mininode_lock: - for c in self.connections: + for c in self.p2p_connections: if outcome is None: # Make sure the mempools agree with each other - if c.cb.lastInv != self.connections[0].cb.lastInv: + if c.lastInv != self.p2p_connections[0].lastInv: return False elif isinstance(outcome, RejectResult): # Check that tx was rejected w/ code - if txhash in c.cb.lastInv: + if txhash in c.lastInv: return False - if txhash not in c.cb.tx_reject_map: + if txhash not in c.tx_reject_map: logger.error('Tx not in reject map: %064x' % (txhash)) return False - if not outcome.match(c.cb.tx_reject_map[txhash]): - logger.error('Tx rejected with %s instead of expected %s: %064x' % (c.cb.tx_reject_map[txhash], outcome, txhash)) + if not outcome.match(c.tx_reject_map[txhash]): + logger.error('Tx rejected with %s instead of expected %s: %064x' % (c.tx_reject_map[txhash], outcome, txhash)) return False - elif ((txhash in c.cb.lastInv) != outcome): + elif ((txhash in c.lastInv) != outcome): return False return True @@ -332,25 +323,25 @@ class TestManager(): first_block_with_hash = False with mininode_lock: self.block_store.add_block(block) - for c in self.connections: - if first_block_with_hash and block.sha256 in c.cb.block_request_map and c.cb.block_request_map[block.sha256] == True: + for c in self.p2p_connections: + if first_block_with_hash and block.sha256 in c.block_request_map and c.block_request_map[block.sha256] == True: # There was a previous request for this block hash # Most likely, we delivered a header for this block # but never had the block to respond to the getdata c.send_message(msg_block(block)) else: - c.cb.block_request_map[block.sha256] = False + c.block_request_map[block.sha256] = False # Either send inv's to each node and sync, or add # to invqueue for later inv'ing. if (test_instance.sync_every_block): # if we expect success, send inv and sync every block # if we expect failure, just push the block and see what happens. if outcome == True: - [ c.cb.send_inv(block) for c in self.connections ] + [ c.send_inv(block) for c in self.p2p_connections ] self.sync_blocks(block.sha256, 1) else: - [ c.send_message(msg_block(block)) for c in self.connections ] - [ c.cb.send_ping(self.ping_counter) for c in self.connections ] + [ c.send_message(msg_block(block)) for c in self.p2p_connections ] + [ c.send_ping(self.ping_counter) for c in self.p2p_connections ] self.wait_for_pings(self.ping_counter) self.ping_counter += 1 if (not self.check_results(tip, outcome)): @@ -360,7 +351,7 @@ class TestManager(): elif isinstance(b_or_t, CBlockHeader): block_header = b_or_t self.block_store.add_header(block_header) - [ c.cb.send_header(block_header) for c in self.connections ] + [ c.send_header(block_header) for c in self.p2p_connections ] else: # Tx test runner assert(isinstance(b_or_t, CTransaction)) @@ -369,11 +360,11 @@ class TestManager(): # Add to shared tx store and clear map entry with mininode_lock: self.tx_store.add_transaction(tx) - for c in self.connections: - c.cb.tx_request_map[tx.sha256] = False + for c in self.p2p_connections: + c.tx_request_map[tx.sha256] = False # Again, either inv to all nodes or save for later if (test_instance.sync_every_tx): - [ c.cb.send_inv(tx) for c in self.connections ] + [ c.send_inv(tx) for c in self.p2p_connections ] self.sync_transaction(tx.sha256, 1) if (not self.check_mempool(tx.sha256, outcome)): raise AssertionError("Test failed at test %d" % test_number) @@ -381,26 +372,26 @@ class TestManager(): invqueue.append(CInv(1, tx.sha256)) # Ensure we're not overflowing the inv queue if len(invqueue) == MAX_INV_SZ: - [ c.send_message(msg_inv(invqueue)) for c in self.connections ] + [ c.send_message(msg_inv(invqueue)) for c in self.p2p_connections ] invqueue = [] # Do final sync if we weren't syncing on every block or every tx. if (not test_instance.sync_every_block and block is not None): if len(invqueue) > 0: - [ c.send_message(msg_inv(invqueue)) for c in self.connections ] + [ c.send_message(msg_inv(invqueue)) for c in self.p2p_connections ] invqueue = [] self.sync_blocks(block.sha256, len(test_instance.blocks_and_transactions)) if (not self.check_results(tip, block_outcome)): raise AssertionError("Block test failed at test %d" % test_number) if (not test_instance.sync_every_tx and tx is not None): if len(invqueue) > 0: - [ c.send_message(msg_inv(invqueue)) for c in self.connections ] + [ c.send_message(msg_inv(invqueue)) for c in self.p2p_connections ] invqueue = [] self.sync_transaction(tx.sha256, len(test_instance.blocks_and_transactions)) if (not self.check_mempool(tx.sha256, tx_outcome)): raise AssertionError("Mempool test failed at test %d" % test_number) - [ c.disconnect_node() for c in self.connections ] + [ c.disconnect_node() for c in self.p2p_connections ] self.wait_for_disconnections() self.block_store.close() self.tx_store.close() diff --git a/test/functional/test_framework/coverage.py b/test/functional/test_framework/coverage.py index ddc3c515b2..f8761f2bb3 100644 --- a/test/functional/test_framework/coverage.py +++ b/test/functional/test_framework/coverage.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2015-2016 The Bitcoin Core developers +# Copyright (c) 2015-2017 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Utilities for doing coverage analysis on the RPC interface. diff --git a/test/functional/test_framework/messages.py b/test/functional/test_framework/messages.py index 40d02f3ee0..a54a0299c7 100644 --- a/test/functional/test_framework/messages.py +++ b/test/functional/test_framework/messages.py @@ -24,7 +24,7 @@ import struct import time from test_framework.siphash import siphash256 -from test_framework.util import hex_str_to_bytes, bytes_to_hex_str, wait_until +from test_framework.util import hex_str_to_bytes, bytes_to_hex_str MIN_VERSION_SUPPORTED = 60001 MY_VERSION = 70014 # past bip-31 for ping/pong @@ -38,10 +38,11 @@ COIN = 100000000 # 1 btc in satoshis NODE_NETWORK = (1 << 0) # NODE_GETUTXO = (1 << 1) -# NODE_BLOOM = (1 << 2) +NODE_BLOOM = (1 << 2) NODE_WITNESS = (1 << 3) NODE_UNSUPPORTED_SERVICE_BIT_5 = (1 << 5) NODE_UNSUPPORTED_SERVICE_BIT_7 = (1 << 7) +NODE_NETWORK_LIMITED = (1 << 10) # Serialization/deserialization tools def sha256(s): @@ -167,21 +168,6 @@ def ser_string_vector(l): return r -def deser_int_vector(f): - nit = deser_compact_size(f) - r = [] - for i in range(nit): - t = struct.unpack("<i", f.read(4))[0] - r.append(t) - return r - - -def ser_int_vector(l): - r = ser_compact_size(len(l)) - for i in l: - r += struct.pack("<i", i) - return r - # Deserialize from a hex string representation (eg from RPC) def FromHex(obj, hex_string): obj.deserialize(BytesIO(hex_str_to_bytes(hex_string))) @@ -467,10 +453,10 @@ class CTransaction(): r += struct.pack("<I", self.nLockTime) return r - # Regular serialization is without witness -- must explicitly - # call serialize_with_witness to include witness data. + # Regular serialization is with witness -- must explicitly + # call serialize_without_witness to exclude witness data. def serialize(self): - return self.serialize_without_witness() + return self.serialize_with_witness() # Recalculate the txid (transaction hash without witness) def rehash(self): @@ -486,7 +472,7 @@ class CTransaction(): if self.sha256 is None: self.sha256 = uint256_from_str(hash256(self.serialize_without_witness())) - self.hash = encode(hash256(self.serialize())[::-1], 'hex_codec').decode('ascii') + self.hash = encode(hash256(self.serialize_without_witness())[::-1], 'hex_codec').decode('ascii') def is_valid(self): self.calc_sha256() @@ -583,7 +569,7 @@ class CBlock(CBlockHeader): if with_witness: r += ser_vector(self.vtx, "serialize_with_witness") else: - r += ser_vector(self.vtx) + r += ser_vector(self.vtx, "serialize_without_witness") return r # Calculate the merkle root given a vector of transaction hashes @@ -650,7 +636,7 @@ class PrefilledTransaction(): self.tx = CTransaction() self.tx.deserialize(f) - def serialize(self, with_witness=False): + def serialize(self, with_witness=True): r = b"" r += ser_compact_size(self.index) if with_witness: @@ -659,6 +645,9 @@ class PrefilledTransaction(): r += self.tx.serialize_without_witness() return r + def serialize_without_witness(self): + return self.serialize(with_witness=False) + def serialize_with_witness(self): return self.serialize(with_witness=True) @@ -698,7 +687,7 @@ class P2PHeaderAndShortIDs(): if with_witness: r += ser_vector(self.prefilled_txn, "serialize_with_witness") else: - r += ser_vector(self.prefilled_txn) + r += ser_vector(self.prefilled_txn, "serialize_without_witness") return r def __repr__(self): @@ -829,13 +818,13 @@ class BlockTransactions(): self.blockhash = deser_uint256(f) self.transactions = deser_vector(f, CTransaction) - def serialize(self, with_witness=False): + def serialize(self, with_witness=True): r = b"" r += ser_uint256(self.blockhash) if with_witness: r += ser_vector(self.transactions, "serialize_with_witness") else: - r += ser_vector(self.transactions) + r += ser_vector(self.transactions, "serialize_without_witness") return r def __repr__(self): @@ -1035,7 +1024,7 @@ class msg_block(): self.block.deserialize(f) def serialize(self): - return self.block.serialize() + return self.block.serialize(with_witness=False) def __repr__(self): return "msg_block(block=%s)" % (repr(self.block)) @@ -1306,7 +1295,7 @@ class msg_blocktxn(): def serialize(self): r = b"" - r += self.block_transactions.serialize() + r += self.block_transactions.serialize(with_witness=False) return r def __repr__(self): diff --git a/test/functional/test_framework/mininode.py b/test/functional/test_framework/mininode.py index 24c96b5681..fe14591139 100755 --- a/test/functional/test_framework/mininode.py +++ b/test/functional/test_framework/mininode.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # Copyright (c) 2010 ArtForz -- public domain half-a-node # Copyright (c) 2012 Jeff Garzik -# Copyright (c) 2010-2016 The Bitcoin Core developers +# Copyright (c) 2010-2017 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 P2P network half-a-node. @@ -9,10 +9,8 @@ This python code was modified from ArtForz' public domain half-a-node, as found in the mini-node branch of http://github.com/jgarzik/pynode. -NodeConn: an object which manages p2p connectivity to a bitcoin node -NodeConnCB: a base class that describes the interface for receiving - callbacks with network messages from a NodeConn -""" +P2PConnection: A low-level connection object to a node's P2P interface +P2PInterface: A high-level interface object for communicating to a node over P2P""" import asyncore from collections import defaultdict from io import BytesIO @@ -20,10 +18,10 @@ import logging import socket import struct import sys -import time -from threading import RLock, Thread +import threading from test_framework.messages import * +from test_framework.util import wait_until logger = logging.getLogger("TestFramework.mininode") @@ -57,173 +55,36 @@ MAGIC_BYTES = { "regtest": b"\xfa\xbf\xb5\xda", # regtest } -class NodeConnCB(): - """Callback and helper functions for P2P connection to a bitcoind node. +class P2PConnection(asyncore.dispatcher): + """A low-level connection object to a node's P2P interface. - Individual testcases should subclass this and override the on_* methods - if they want to alter message handling behaviour.""" - def __init__(self): - # Track whether we have a P2P connection open to the node - self.connected = False - self.connection = None - - # Track number of messages of each type received and the most recent - # message of each type - self.message_count = defaultdict(int) - self.last_message = {} - - # A count of the number of ping messages we've sent to the node - self.ping_counter = 1 - - # Message receiving methods - - def deliver(self, conn, message): - """Receive message and dispatch message to appropriate callback. - - We keep a count of how many of each message type has been received - and the most recent message of each type.""" - with mininode_lock: - try: - command = message.command.decode('ascii') - self.message_count[command] += 1 - self.last_message[command] = message - getattr(self, 'on_' + command)(conn, message) - except: - print("ERROR delivering %s (%s)" % (repr(message), - sys.exc_info()[0])) - raise - - # Callback methods. Can be overridden by subclasses in individual test - # cases to provide custom message handling behaviour. - - def on_open(self, conn): - self.connected = True - - def on_close(self, conn): - self.connected = False - self.connection = None - - def on_addr(self, conn, message): pass - def on_block(self, conn, message): pass - def on_blocktxn(self, conn, message): pass - def on_cmpctblock(self, conn, message): pass - def on_feefilter(self, conn, message): pass - def on_getaddr(self, conn, message): pass - def on_getblocks(self, conn, message): pass - def on_getblocktxn(self, conn, message): pass - def on_getdata(self, conn, message): pass - def on_getheaders(self, conn, message): pass - def on_headers(self, conn, message): pass - def on_mempool(self, conn): pass - def on_pong(self, conn, message): pass - def on_reject(self, conn, message): pass - def on_sendcmpct(self, conn, message): pass - def on_sendheaders(self, conn, message): pass - def on_tx(self, conn, message): pass - - def on_inv(self, conn, message): - want = msg_getdata() - for i in message.inv: - if i.type != 0: - want.inv.append(i) - if len(want.inv): - conn.send_message(want) - - def on_ping(self, conn, message): - conn.send_message(msg_pong(message.nonce)) - - def on_verack(self, conn, message): - self.verack_received = True - - def on_version(self, conn, message): - assert message.nVersion >= MIN_VERSION_SUPPORTED, "Version {} received. Test framework only supports versions greater than {}".format(message.nVersion, MIN_VERSION_SUPPORTED) - conn.send_message(msg_verack()) - conn.nServices = message.nServices + This class is responsible for: - # Connection helper methods - - def add_connection(self, conn): - self.connection = conn + - opening and closing the TCP connection to the node + - reading bytes from and writing bytes to the socket + - deserializing and serializing the P2P message header + - logging messages as they are sent and received - def wait_for_disconnect(self, timeout=60): - test_function = lambda: not self.connected - wait_until(test_function, timeout=timeout, lock=mininode_lock) + This class contains no logic for handing the P2P message payloads. It must be + sub-classed and the on_message() callback overridden.""" - # Message receiving helper methods - - def wait_for_block(self, blockhash, timeout=60): - test_function = lambda: self.last_message.get("block") and self.last_message["block"].block.rehash() == blockhash - wait_until(test_function, timeout=timeout, lock=mininode_lock) - - def wait_for_getdata(self, timeout=60): - test_function = lambda: self.last_message.get("getdata") - wait_until(test_function, timeout=timeout, lock=mininode_lock) - - def wait_for_getheaders(self, timeout=60): - test_function = lambda: self.last_message.get("getheaders") - wait_until(test_function, timeout=timeout, lock=mininode_lock) - - def wait_for_inv(self, expected_inv, timeout=60): - """Waits for an INV message and checks that the first inv object in the message was as expected.""" - if len(expected_inv) > 1: - raise NotImplementedError("wait_for_inv() will only verify the first inv object") - test_function = lambda: self.last_message.get("inv") and \ - self.last_message["inv"].inv[0].type == expected_inv[0].type and \ - self.last_message["inv"].inv[0].hash == expected_inv[0].hash - wait_until(test_function, timeout=timeout, lock=mininode_lock) - - def wait_for_verack(self, timeout=60): - test_function = lambda: self.message_count["verack"] - wait_until(test_function, timeout=timeout, lock=mininode_lock) - - # Message sending helper functions - - def send_message(self, message): - if self.connection: - self.connection.send_message(message) - else: - logger.error("Cannot send message. No connection to node!") - - def send_and_ping(self, message): - self.send_message(message) - self.sync_with_ping() - - # Sync up with the node - def sync_with_ping(self, timeout=60): - self.send_message(msg_ping(nonce=self.ping_counter)) - test_function = lambda: self.last_message.get("pong") and self.last_message["pong"].nonce == self.ping_counter - wait_until(test_function, timeout=timeout, lock=mininode_lock) - self.ping_counter += 1 - -class NodeConn(asyncore.dispatcher): - """The actual NodeConn class + def __init__(self): + # All P2PConnections must be created before starting the NetworkThread. + # assert that the network thread is not running. + assert not network_thread_running() - This class provides an interface for a p2p connection to a specified node.""" + super().__init__(map=mininode_socket_map) - def __init__(self, dstaddr, dstport, callback, net="regtest", services=NODE_NETWORK|NODE_WITNESS, send_version=True): - asyncore.dispatcher.__init__(self, map=mininode_socket_map) + def peer_connect(self, dstaddr, dstport, net="regtest"): self.dstaddr = dstaddr self.dstport = dstport self.create_socket(socket.AF_INET, socket.SOCK_STREAM) self.socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) self.sendbuf = b"" self.recvbuf = b"" - self.last_sent = 0 self.state = "connecting" self.network = net - self.cb = callback self.disconnect = False - self.nServices = 0 - - if send_version: - # stuff version msg into sendbuf - vt = msg_version() - vt.nServices = services - vt.addrTo.ip = self.dstaddr - vt.addrTo.port = self.dstport - vt.addrFrom.ip = "0.0.0.0" - vt.addrFrom.port = 0 - self.send_message(vt, True) logger.info('Connecting to Bitcoin Node: %s:%d' % (self.dstaddr, self.dstport)) @@ -232,15 +93,22 @@ class NodeConn(asyncore.dispatcher): except: self.handle_close() + def peer_disconnect(self): + # Connection could have already been closed by other end. + if self.state == "connected": + self.disconnect_node() + # Connection and disconnection methods def handle_connect(self): + """asyncore callback when a connection is opened.""" if self.state != "connected": logger.debug("Connected & Listening: %s:%d" % (self.dstaddr, self.dstport)) self.state = "connected" - self.cb.on_open(self) + self.on_open() def handle_close(self): + """asyncore callback when a connection is closed.""" logger.debug("Closing connection to: %s:%d" % (self.dstaddr, self.dstport)) self.state = "closed" self.recvbuf = b"" @@ -249,10 +117,10 @@ class NodeConn(asyncore.dispatcher): self.close() except: pass - self.cb.on_close(self) + self.on_close() def disconnect_node(self): - """ Disconnect the p2p connection. + """Disconnect the p2p connection. Called by the test logic thread. Causes the p2p connection to be disconnected on the next iteration of the asyncore loop.""" @@ -260,16 +128,19 @@ class NodeConn(asyncore.dispatcher): # Socket read methods - def readable(self): - return True - def handle_read(self): + """asyncore callback when data is read from the socket.""" t = self.recv(8192) if len(t) > 0: self.recvbuf += t - self.got_data() + self._on_data() - def got_data(self): + def _on_data(self): + """Try to read P2P messages from the recv buffer. + + This method reads data from the buffer in a loop. It deserializes, + parses and verifies the P2P header, then passes the P2P payload to + the on_message callback for processing.""" try: while True: if len(self.recvbuf) < 4: @@ -294,26 +165,27 @@ class NodeConn(asyncore.dispatcher): f = BytesIO(msg) t = MESSAGEMAP[command]() t.deserialize(f) - self.got_message(t) + self._log_message("receive", t) + self.on_message(t) except Exception as e: logger.exception('Error reading message:', repr(e)) raise - def got_message(self, message): - if self.last_sent + 30 * 60 < time.time(): - self.send_message(MESSAGEMAP[b'ping']()) - self._log_message("receive", message) - self.cb.deliver(self, message) + def on_message(self, message): + """Callback for processing a P2P payload. Must be overridden by derived class.""" + raise NotImplementedError # Socket write methods def writable(self): + """asyncore method to determine whether the handle_write() callback should be called on the next loop.""" with mininode_lock: pre_connection = self.state == "connecting" length = len(self.sendbuf) return (length > 0 or pre_connection) def handle_write(self): + """asyncore callback when data should be written to the socket.""" with mininode_lock: # asyncore does not expose socket connection, only the first read/write # event, thus we must check connection manually here to know when we @@ -331,6 +203,10 @@ class NodeConn(asyncore.dispatcher): self.sendbuf = self.sendbuf[sent:] def send_message(self, message, pushbuf=False): + """Send a P2P message over the socket. + + This method takes a P2P payload, builds the P2P header and adds + the message to the send buffer to be sent over the socket.""" if self.state != "connected" and not pushbuf: raise IOError('Not connected, no pushbuf') self._log_message("send", message) @@ -353,11 +229,11 @@ class NodeConn(asyncore.dispatcher): self.sendbuf = tmsg else: self.sendbuf += tmsg - self.last_sent = time.time() # Class utility methods def _log_message(self, direction, msg): + """Logs a message being sent or received over the connection.""" if direction == "send": log_message = "Send message to " elif direction == "receive": @@ -368,6 +244,152 @@ class NodeConn(asyncore.dispatcher): logger.debug(log_message) +class P2PInterface(P2PConnection): + """A high-level P2P interface class for communicating with a Bitcoin node. + + This class provides high-level callbacks for processing P2P message + payloads, as well as convenience methods for interacting with the + node over P2P. + + Individual testcases should subclass this and override the on_* methods + if they want to alter message handling behaviour.""" + def __init__(self): + super().__init__() + + # Track number of messages of each type received and the most recent + # message of each type + self.message_count = defaultdict(int) + self.last_message = {} + + # A count of the number of ping messages we've sent to the node + self.ping_counter = 1 + + # The network services received from the peer + self.nServices = 0 + + def peer_connect(self, *args, services=NODE_NETWORK|NODE_WITNESS, send_version=True, **kwargs): + super().peer_connect(*args, **kwargs) + + if send_version: + # Send a version msg + vt = msg_version() + vt.nServices = services + vt.addrTo.ip = self.dstaddr + vt.addrTo.port = self.dstport + vt.addrFrom.ip = "0.0.0.0" + vt.addrFrom.port = 0 + self.send_message(vt, True) + + # Message receiving methods + + def on_message(self, message): + """Receive message and dispatch message to appropriate callback. + + We keep a count of how many of each message type has been received + and the most recent message of each type.""" + with mininode_lock: + try: + command = message.command.decode('ascii') + self.message_count[command] += 1 + self.last_message[command] = message + getattr(self, 'on_' + command)(message) + except: + print("ERROR delivering %s (%s)" % (repr(message), sys.exc_info()[0])) + raise + + # Callback methods. Can be overridden by subclasses in individual test + # cases to provide custom message handling behaviour. + + def on_open(self): + pass + + def on_close(self): + pass + + def on_addr(self, message): pass + def on_block(self, message): pass + def on_blocktxn(self, message): pass + def on_cmpctblock(self, message): pass + def on_feefilter(self, message): pass + def on_getaddr(self, message): pass + def on_getblocks(self, message): pass + def on_getblocktxn(self, message): pass + def on_getdata(self, message): pass + def on_getheaders(self, message): pass + def on_headers(self, message): pass + def on_mempool(self, message): pass + def on_pong(self, message): pass + def on_reject(self, message): pass + def on_sendcmpct(self, message): pass + def on_sendheaders(self, message): pass + def on_tx(self, message): pass + + def on_inv(self, message): + want = msg_getdata() + for i in message.inv: + if i.type != 0: + want.inv.append(i) + if len(want.inv): + self.send_message(want) + + def on_ping(self, message): + self.send_message(msg_pong(message.nonce)) + + def on_verack(self, message): + self.verack_received = True + + def on_version(self, message): + assert message.nVersion >= MIN_VERSION_SUPPORTED, "Version {} received. Test framework only supports versions greater than {}".format(message.nVersion, MIN_VERSION_SUPPORTED) + self.send_message(msg_verack()) + self.nServices = message.nServices + + # Connection helper methods + + def wait_for_disconnect(self, timeout=60): + test_function = lambda: self.state != "connected" + wait_until(test_function, timeout=timeout, lock=mininode_lock) + + # Message receiving helper methods + + def wait_for_block(self, blockhash, timeout=60): + test_function = lambda: self.last_message.get("block") and self.last_message["block"].block.rehash() == blockhash + wait_until(test_function, timeout=timeout, lock=mininode_lock) + + def wait_for_getdata(self, timeout=60): + test_function = lambda: self.last_message.get("getdata") + wait_until(test_function, timeout=timeout, lock=mininode_lock) + + def wait_for_getheaders(self, timeout=60): + test_function = lambda: self.last_message.get("getheaders") + wait_until(test_function, timeout=timeout, lock=mininode_lock) + + def wait_for_inv(self, expected_inv, timeout=60): + """Waits for an INV message and checks that the first inv object in the message was as expected.""" + if len(expected_inv) > 1: + raise NotImplementedError("wait_for_inv() will only verify the first inv object") + test_function = lambda: self.last_message.get("inv") and \ + self.last_message["inv"].inv[0].type == expected_inv[0].type and \ + self.last_message["inv"].inv[0].hash == expected_inv[0].hash + wait_until(test_function, timeout=timeout, lock=mininode_lock) + + def wait_for_verack(self, timeout=60): + test_function = lambda: self.message_count["verack"] + wait_until(test_function, timeout=timeout, lock=mininode_lock) + + # Message sending helper functions + + def send_and_ping(self, message): + self.send_message(message) + self.sync_with_ping() + + # Sync up with the node + def sync_with_ping(self, timeout=60): + self.send_message(msg_ping(nonce=self.ping_counter)) + test_function = lambda: self.last_message.get("pong") and self.last_message["pong"].nonce == self.ping_counter + wait_until(test_function, timeout=timeout, lock=mininode_lock) + self.ping_counter += 1 + + # Keep our own socket map for asyncore, so that we can track disconnects # ourselves (to workaround an issue with closing an asyncore socket when # using select) @@ -375,13 +397,16 @@ mininode_socket_map = dict() # One lock for synchronizing all data access between the networking thread (see # NetworkThread below) and the thread running the test logic. For simplicity, -# NodeConn acquires this lock whenever delivering a message to a NodeConnCB, +# P2PConnection acquires this lock whenever delivering a message to a P2PInterface, # and whenever adding anything to the send buffer (in send_message()). This # lock should be acquired in the thread running the test logic to synchronize -# access to any data shared with the NodeConnCB or NodeConn. -mininode_lock = RLock() +# access to any data shared with the P2PInterface or P2PConnection. +mininode_lock = threading.RLock() + +class NetworkThread(threading.Thread): + def __init__(self): + super().__init__(name="NetworkThread") -class NetworkThread(Thread): def run(self): while mininode_socket_map: # We check for whether to disconnect outside of the asyncore @@ -394,3 +419,24 @@ class NetworkThread(Thread): [obj.handle_close() for obj in disconnected] asyncore.loop(0.1, use_poll=True, map=mininode_socket_map, count=1) logger.debug("Network thread closing") + +def network_thread_start(): + """Start the network thread.""" + # Only one network thread may run at a time + assert not network_thread_running() + + NetworkThread().start() + +def network_thread_running(): + """Return whether the network thread is running.""" + return any([thread.name == "NetworkThread" for thread in threading.enumerate()]) + +def network_thread_join(timeout=10): + """Wait timeout seconds for the network thread to terminate. + + Throw if the network thread doesn't terminate in timeout seconds.""" + network_threads = [thread for thread in threading.enumerate() if thread.name == "NetworkThread"] + assert len(network_threads) <= 1 + for thread in network_threads: + thread.join(timeout) + assert not thread.is_alive() diff --git a/test/functional/test_framework/netutil.py b/test/functional/test_framework/netutil.py index e5d415788f..96fe283347 100644 --- a/test/functional/test_framework/netutil.py +++ b/test/functional/test_framework/netutil.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2014-2016 The Bitcoin Core developers +# Copyright (c) 2014-2017 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Linux network utilities. diff --git a/test/functional/test_framework/script.py b/test/functional/test_framework/script.py index a4c046bd3d..dae8a4e569 100644 --- a/test/functional/test_framework/script.py +++ b/test/functional/test_framework/script.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2015-2016 The Bitcoin Core developers +# Copyright (c) 2015-2017 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Functionality to build scripts, as well as SignatureHash(). @@ -641,7 +641,7 @@ def SignatureHash(script, txTo, inIdx, hashtype): txtmp.vin = [] txtmp.vin.append(tmp) - s = txtmp.serialize() + s = txtmp.serialize_without_witness() s += struct.pack(b"<I", hashtype) hash = hash256(s) diff --git a/test/functional/test_framework/siphash.py b/test/functional/test_framework/siphash.py index f68ecad36b..6ffc982cea 100644 --- a/test/functional/test_framework/siphash.py +++ b/test/functional/test_framework/siphash.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2016 The Bitcoin Core developers +# Copyright (c) 2016-2017 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Specialized SipHash-2-4 implementations. diff --git a/test/functional/test_framework/socks5.py b/test/functional/test_framework/socks5.py index 7b40c47fbf..4721809a3b 100644 --- a/test/functional/test_framework/socks5.py +++ b/test/functional/test_framework/socks5.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2015-2016 The Bitcoin Core developers +# Copyright (c) 2015-2017 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Dummy Socks5 server for testing.""" diff --git a/test/functional/test_framework/test_framework.py b/test/functional/test_framework/test_framework.py index 8df50474f3..f8d66def64 100755 --- a/test/functional/test_framework/test_framework.py +++ b/test/functional/test_framework/test_framework.py @@ -1,10 +1,9 @@ #!/usr/bin/env python3 -# Copyright (c) 2014-2016 The Bitcoin Core developers +# Copyright (c) 2014-2017 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Base class for RPC testing.""" -from collections import deque from enum import Enum import logging import optparse @@ -14,7 +13,6 @@ import shutil import sys import tempfile import time -import traceback from .authproxy import JSONRPCException from . import coverage @@ -64,6 +62,7 @@ class BitcoinTestFramework(): self.setup_clean_chain = False self.nodes = [] self.mocktime = 0 + self.supports_cli = False self.set_test_params() assert hasattr(self, "num_nodes"), "Test must set self.num_nodes in set_test_params()" @@ -93,6 +92,8 @@ class BitcoinTestFramework(): help="Location of the test framework config file") parser.add_option("--pdbonfailure", dest="pdbonfailure", default=False, action="store_true", help="Attach a python debugger if test fails") + parser.add_option("--usecli", dest="usecli", default=False, action="store_true", + help="use bitcoin-cli instead of RPC for all commands") self.add_options(parser) (self.options, self.args) = parser.parse_args() @@ -115,6 +116,8 @@ class BitcoinTestFramework(): success = TestStatus.FAILED try: + if self.options.usecli and not self.supports_cli: + raise SkipTest("--usecli specified but test does not support using CLI") self.setup_chain() self.setup_network() self.run_test() @@ -149,32 +152,19 @@ class BitcoinTestFramework(): shutil.rmtree(self.options.tmpdir) else: self.log.warning("Not cleaning up dir %s" % self.options.tmpdir) - if os.getenv("PYTHON_DEBUG", ""): - # Dump the end of the debug logs, to aid in debugging rare - # travis failures. - import glob - filenames = [self.options.tmpdir + "/test_framework.log"] - filenames += glob.glob(self.options.tmpdir + "/node*/regtest/debug.log") - MAX_LINES_TO_PRINT = 1000 - for fn in filenames: - try: - with open(fn, 'r') as f: - print("From", fn, ":") - print("".join(deque(f, MAX_LINES_TO_PRINT))) - except OSError: - print("Opening file %s failed." % fn) - traceback.print_exc() if success == TestStatus.PASSED: self.log.info("Tests successful") - sys.exit(TEST_EXIT_PASSED) + exit_code = TEST_EXIT_PASSED elif success == TestStatus.SKIPPED: self.log.info("Test skipped") - sys.exit(TEST_EXIT_SKIPPED) + exit_code = TEST_EXIT_SKIPPED else: self.log.error("Test failed. Test logging available at %s/test_framework.log", self.options.tmpdir) - logging.shutdown() - sys.exit(TEST_EXIT_FAILED) + self.log.error("Hint: Call {} '{}' to consolidate all logs".format(os.path.normpath(os.path.dirname(os.path.realpath(__file__)) + "/../combine_logs.py"), self.options.tmpdir)) + exit_code = TEST_EXIT_FAILED + logging.shutdown() + sys.exit(exit_code) # Methods to override in subclass test scripts. def set_test_params(self): @@ -228,20 +218,20 @@ class BitcoinTestFramework(): assert_equal(len(extra_args), num_nodes) assert_equal(len(binary), num_nodes) for i in range(num_nodes): - self.nodes.append(TestNode(i, self.options.tmpdir, extra_args[i], rpchost, timewait=timewait, binary=binary[i], stderr=None, mocktime=self.mocktime, coverage_dir=self.options.coveragedir)) + self.nodes.append(TestNode(i, self.options.tmpdir, extra_args[i], rpchost, timewait=timewait, binary=binary[i], stderr=None, mocktime=self.mocktime, coverage_dir=self.options.coveragedir, use_cli=self.options.usecli)) - def start_node(self, i, extra_args=None, stderr=None): + def start_node(self, i, *args, **kwargs): """Start a bitcoind""" node = self.nodes[i] - node.start(extra_args, stderr) + node.start(*args, **kwargs) node.wait_for_rpc_connection() if self.options.coveragedir is not None: coverage.write_all_rpc_commands(self.options.coveragedir, node.rpc) - def start_nodes(self, extra_args=None): + def start_nodes(self, extra_args=None, *args, **kwargs): """Start multiple bitcoinds""" if extra_args is None: @@ -249,7 +239,7 @@ class BitcoinTestFramework(): assert_equal(len(extra_args), self.num_nodes) try: for i, node in enumerate(self.nodes): - node.start(extra_args[i]) + node.start(extra_args[i], *args, **kwargs) for node in self.nodes: node.wait_for_rpc_connection() except: @@ -281,10 +271,10 @@ class BitcoinTestFramework(): self.stop_node(i) self.start_node(i, extra_args) - def assert_start_raises_init_error(self, i, extra_args=None, expected_msg=None): + def assert_start_raises_init_error(self, i, extra_args=None, expected_msg=None, *args, **kwargs): with tempfile.SpooledTemporaryFile(max_size=2**16) as log_stderr: try: - self.start_node(i, extra_args, stderr=log_stderr) + self.start_node(i, extra_args, stderr=log_stderr, *args, **kwargs) self.stop_node(i) except Exception as e: assert 'bitcoind exited' in str(e) # node must have shutdown @@ -432,7 +422,7 @@ class BitcoinTestFramework(): self.disable_mocktime() for i in range(MAX_NODES): os.remove(log_filename(self.options.cachedir, i, "debug.log")) - os.remove(log_filename(self.options.cachedir, i, "db.log")) + os.remove(log_filename(self.options.cachedir, i, "wallets/db.log")) os.remove(log_filename(self.options.cachedir, i, "peers.dat")) os.remove(log_filename(self.options.cachedir, i, "fee_estimates.dat")) diff --git a/test/functional/test_framework/test_node.py b/test/functional/test_framework/test_node.py index 34b458482a..1054e6d028 100755 --- a/test/functional/test_framework/test_node.py +++ b/test/functional/test_framework/test_node.py @@ -10,11 +10,11 @@ import http.client import json import logging import os +import re import subprocess import time from .authproxy import JSONRPCException -from .mininode import NodeConn from .util import ( assert_equal, get_rpc_proxy, @@ -23,6 +23,9 @@ from .util import ( p2p_port, ) +# For Python 3.4 compatibility +JSONDecodeError = getattr(json, "JSONDecodeError", ValueError) + BITCOIND_PROC_WAIT_TIMEOUT = 60 class TestNode(): @@ -39,7 +42,7 @@ class TestNode(): To make things easier for the test writer, any unrecognised messages will be dispatched to the RPC connection.""" - def __init__(self, i, dirname, extra_args, rpchost, timewait, binary, stderr, mocktime, coverage_dir): + def __init__(self, i, dirname, extra_args, rpchost, timewait, binary, stderr, mocktime, coverage_dir, use_cli=False): self.index = i self.datadir = os.path.join(dirname, "node" + str(i)) self.rpchost = rpchost @@ -59,6 +62,7 @@ class TestNode(): self.args = [self.binary, "-datadir=" + self.datadir, "-server", "-keypool=1", "-discover=0", "-rest", "-logtimemicros", "-debug", "-debugexclude=libevent", "-debugexclude=leveldb", "-mocktime=" + str(mocktime), "-uacomment=testnode%d" % i] self.cli = TestNodeCLI(os.getenv("BITCOINCLI", "bitcoin-cli"), self.datadir) + self.use_cli = use_cli self.running = False self.process = None @@ -70,17 +74,20 @@ class TestNode(): self.p2ps = [] def __getattr__(self, name): - """Dispatches any unrecognised messages to the RPC connection.""" - assert self.rpc_connected and self.rpc is not None, "Error: no RPC connection" - return getattr(self.rpc, name) + """Dispatches any unrecognised messages to the RPC connection or a CLI instance.""" + if self.use_cli: + return getattr(self.cli, name) + else: + assert self.rpc_connected and self.rpc is not None, "Error: no RPC connection" + return getattr(self.rpc, name) - def start(self, extra_args=None, stderr=None): + def start(self, extra_args=None, stderr=None, *args, **kwargs): """Start the node.""" if extra_args is None: extra_args = self.extra_args if stderr is None: stderr = self.stderr - self.process = subprocess.Popen(self.args + extra_args, stderr=stderr) + self.process = subprocess.Popen(self.args + extra_args, stderr=stderr, *args, **kwargs) self.running = True self.log.debug("bitcoind started, waiting for RPC to come up") @@ -111,10 +118,13 @@ class TestNode(): raise AssertionError("Unable to connect to bitcoind") def get_wallet_rpc(self, wallet_name): - assert self.rpc_connected - assert self.rpc - wallet_path = "wallet/%s" % wallet_name - return self.rpc / wallet_path + if self.use_cli: + return self.cli("-rpcwallet={}".format(wallet_name)) + else: + assert self.rpc_connected + assert self.rpc + wallet_path = "wallet/%s" % wallet_name + return self.rpc / wallet_path def stop_node(self): """Stop the node.""" @@ -158,7 +168,7 @@ class TestNode(): self.encryptwallet(passphrase) self.wait_until_stopped() - def add_p2p_connection(self, p2p_conn, **kwargs): + def add_p2p_connection(self, p2p_conn, *args, **kwargs): """Add a p2p connection to the node. This method adds the p2p connection to the self.p2ps list and also @@ -167,9 +177,9 @@ class TestNode(): kwargs['dstport'] = p2p_port(self.index) if 'dstaddr' not in kwargs: kwargs['dstaddr'] = '127.0.0.1' + + p2p_conn.peer_connect(*args, **kwargs) self.p2ps.append(p2p_conn) - kwargs.update({'callback': p2p_conn}) - p2p_conn.add_connection(NodeConn(**kwargs)) return p2p_conn @@ -185,46 +195,73 @@ class TestNode(): def disconnect_p2ps(self): """Close all p2p connections to the node.""" for p in self.p2ps: - # Connection could have already been closed by other end. - if p.connection is not None: - p.connection.disconnect_node() - self.p2ps = [] + p.peer_disconnect() + del self.p2ps[:] + +class TestNodeCLIAttr: + def __init__(self, cli, command): + self.cli = cli + self.command = command + + def __call__(self, *args, **kwargs): + return self.cli.send_cli(self.command, *args, **kwargs) + def get_request(self, *args, **kwargs): + return lambda: self(*args, **kwargs) class TestNodeCLI(): """Interface to bitcoin-cli for an individual node""" def __init__(self, binary, datadir): - self.args = [] + self.options = [] self.binary = binary self.datadir = datadir self.input = None + self.log = logging.getLogger('TestFramework.bitcoincli') - def __call__(self, *args, input=None): - # TestNodeCLI is callable with bitcoin-cli command-line args - self.args = [str(arg) for arg in args] - self.input = input - return self + def __call__(self, *options, input=None): + # TestNodeCLI is callable with bitcoin-cli command-line options + cli = TestNodeCLI(self.binary, self.datadir) + cli.options = [str(o) for o in options] + cli.input = input + return cli def __getattr__(self, command): - def dispatcher(*args, **kwargs): - return self.send_cli(command, *args, **kwargs) - return dispatcher - - def send_cli(self, command, *args, **kwargs): + return TestNodeCLIAttr(self, command) + + def batch(self, requests): + results = [] + for request in requests: + try: + results.append(dict(result=request())) + except JSONRPCException as e: + results.append(dict(error=e)) + return results + + def send_cli(self, command=None, *args, **kwargs): """Run bitcoin-cli command. Deserializes returned string as python object.""" pos_args = [str(arg) for arg in args] named_args = [str(key) + "=" + str(value) for (key, value) in kwargs.items()] assert not (pos_args and named_args), "Cannot use positional arguments and named arguments in the same bitcoin-cli call" - p_args = [self.binary, "-datadir=" + self.datadir] + self.args + p_args = [self.binary, "-datadir=" + self.datadir] + self.options if named_args: p_args += ["-named"] - p_args += [command] + pos_args + named_args + if command is not None: + p_args += [command] + p_args += pos_args + named_args + self.log.debug("Running bitcoin-cli command: %s" % command) process = subprocess.Popen(p_args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True) cli_stdout, cli_stderr = process.communicate(input=self.input) returncode = process.poll() if returncode: + match = re.match(r'error code: ([-0-9]+)\nerror message:\n(.*)', cli_stderr) + if match: + code, message = match.groups() + raise JSONRPCException(dict(code=int(code), message=message)) # Ignore cli_stdout, raise with cli_stderr raise subprocess.CalledProcessError(returncode, self.binary, output=cli_stderr) - return json.loads(cli_stdout, parse_float=decimal.Decimal) + try: + return json.loads(cli_stdout, parse_float=decimal.Decimal) + except JSONDecodeError: + return cli_stdout.rstrip("\n") diff --git a/test/functional/test_framework/util.py b/test/functional/test_framework/util.py index 102c903018..7fdc171332 100644 --- a/test/functional/test_framework/util.py +++ b/test/functional/test_framework/util.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2014-2016 The Bitcoin Core developers +# Copyright (c) 2014-2017 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Helpful routines for regression testing.""" @@ -390,7 +390,7 @@ def sync_chain(rpc_connections, *, wait=1, timeout=60): timeout -= wait raise AssertionError("Chain sync failed: Best block hashes don't match") -def sync_mempools(rpc_connections, *, wait=1, timeout=60): +def sync_mempools(rpc_connections, *, wait=1, timeout=60, flush_scheduler=True): """ Wait until everybody has the same transactions in their memory pools @@ -402,6 +402,9 @@ def sync_mempools(rpc_connections, *, wait=1, timeout=60): if set(rpc_connections[i].getrawmempool()) == pool: num_match = num_match + 1 if num_match == len(rpc_connections): + if flush_scheduler: + for r in rpc_connections: + r.syncwithvalidationinterfacequeue() return time.sleep(wait) timeout -= wait diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py index ca36426a0a..98944685e1 100755 --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2014-2016 The Bitcoin Core developers +# Copyright (c) 2014-2017 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 regression test suite. @@ -15,6 +15,7 @@ For a description of arguments recognized by test scripts, see """ import argparse +from collections import deque import configparser import datetime import os @@ -54,106 +55,114 @@ TEST_EXIT_SKIPPED = 77 BASE_SCRIPTS= [ # Scripts that are run by the travis build process. # Longest test should go first, to favor running tests in parallel - 'wallet-hd.py', - 'walletbackup.py', + 'wallet_hd.py', + 'wallet_backup.py', # vv Tests less than 5m vv - 'p2p-fullblocktest.py', - 'fundrawtransaction.py', - 'p2p-compactblocks.py', - 'segwit.py', + 'feature_block.py', + 'rpc_fundrawtransaction.py', + 'p2p_compactblocks.py', + 'feature_segwit.py', # vv Tests less than 2m vv - 'wallet.py', - 'wallet-accounts.py', - 'p2p-segwit.py', - 'wallet-dump.py', - 'listtransactions.py', + 'wallet_basic.py', + 'wallet_accounts.py', + 'p2p_segwit.py', + 'wallet_dump.py', + 'rpc_listtransactions.py', # vv Tests less than 60s vv - 'sendheaders.py', - 'zapwallettxes.py', - 'importmulti.py', + 'p2p_sendheaders.py', + 'wallet_zapwallettxes.py', + 'wallet_importmulti.py', 'mempool_limit.py', - 'merkle_blocks.py', - 'receivedby.py', - 'abandonconflict.py', - 'bip68-112-113-p2p.py', - 'rawtransactions.py', - 'reindex.py', + 'rpc_txoutproof.py', + 'wallet_listreceivedby.py', + 'wallet_abandonconflict.py', + 'feature_csv_activation.py', + 'rpc_rawtransaction.py', + 'wallet_address_types.py', + 'feature_reindex.py', # vv Tests less than 30s vv - 'keypool-topup.py', - 'zmq_test.py', - 'bitcoin_cli.py', - 'mempool_resurrect_test.py', - 'txn_doublespend.py --mineblock', - 'txn_clone.py', - 'getchaintips.py', - 'rest.py', - 'mempool_spendcoinbase.py', + 'wallet_keypool_topup.py', + 'interface_zmq.py', + 'interface_bitcoin_cli.py', + 'mempool_resurrect.py', + 'wallet_txn_doublespend.py --mineblock', + 'wallet_txn_clone.py', + 'wallet_txn_clone.py --segwit', + 'rpc_getchaintips.py', + 'interface_rest.py', + 'mempool_spend_coinbase.py', 'mempool_reorg.py', 'mempool_persist.py', - 'multiwallet.py', - 'httpbasics.py', - 'multi_rpc.py', - 'proxy_test.py', - 'signrawtransactions.py', - 'disconnect_ban.py', - 'decodescript.py', - 'blockchain.py', - 'deprecated_rpc.py', - 'disablewallet.py', - 'net.py', - 'keypool.py', - 'p2p-mempool.py', - 'prioritise_transaction.py', - 'invalidblockrequest.py', - 'invalidtxrequest.py', - 'p2p-versionbits-warning.py', - 'preciousblock.py', - 'importprunedfunds.py', - 'signmessages.py', - 'nulldummy.py', - 'import-rescan.py', - 'mining.py', - 'bumpfee.py', - 'rpcnamedargs.py', - 'listsinceblock.py', - 'p2p-leaktests.py', - 'wallet-encryption.py', - 'bipdersig-p2p.py', - 'bip65-cltv-p2p.py', - 'uptime.py', - 'resendwallettransactions.py', - 'minchainwork.py', - 'p2p-fingerprint.py', - 'uacomment.py', - 'p2p-acceptblock.py', + 'wallet_multiwallet.py', + 'wallet_multiwallet.py --usecli', + 'interface_http.py', + 'rpc_users.py', + 'feature_proxy.py', + 'rpc_signrawtransaction.py', + 'p2p_disconnect_ban.py', + 'rpc_decodescript.py', + 'rpc_blockchain.py', + 'rpc_deprecated.py', + 'wallet_disable.py', + 'rpc_net.py', + 'wallet_keypool.py', + 'p2p_mempool.py', + 'mining_prioritisetransaction.py', + 'p2p_invalid_block.py', + 'p2p_invalid_tx.py', + 'feature_versionbits_warning.py', + 'rpc_preciousblock.py', + 'wallet_importprunedfunds.py', + 'rpc_signmessage.py', + 'feature_nulldummy.py', + 'wallet_import_rescan.py', + 'mining_basic.py', + 'wallet_bumpfee.py', + 'rpc_named_arguments.py', + 'wallet_listsinceblock.py', + 'p2p_leak.py', + 'wallet_encryption.py', + 'feature_dersig.py', + 'feature_cltv.py', + 'rpc_uptime.py', + 'wallet_resendwallettransactions.py', + 'feature_minchainwork.py', + 'p2p_fingerprint.py', + 'feature_uacomment.py', + 'p2p_unrequested_blocks.py', + 'feature_logging.py', + 'p2p_node_network_limited.py', + 'feature_config_args.py', + # Don't append tests at the end to avoid merge conflicts + # Put them in a random line within the section that fits their approximate run-time ] EXTENDED_SCRIPTS = [ # These tests are not run by the travis build process. # Longest test should go first, to favor running tests in parallel - 'pruning.py', + 'feature_pruning.py', # vv Tests less than 20m vv - 'smartfees.py', + 'feature_fee_estimation.py', # vv Tests less than 5m vv - 'maxuploadtarget.py', + 'feature_maxuploadtarget.py', 'mempool_packages.py', - 'dbcrash.py', + 'feature_dbcrash.py', # vv Tests less than 2m vv - 'bip68-sequence.py', - 'getblocktemplate_longpoll.py', - 'p2p-timeouts.py', + 'feature_bip68_sequence.py', + 'mining_getblocktemplate_longpoll.py', + 'p2p_timeouts.py', # vv Tests less than 60s vv - 'bip9-softforks.py', - 'p2p-feefilter.py', - 'rpcbind_test.py', + 'feature_bip9_softforks.py', + 'p2p_feefilter.py', + 'rpc_bind.py', # vv Tests less than 30s vv - 'assumevalid.py', + 'feature_assumevalid.py', 'example_test.py', - 'txn_doublespend.py', - 'txn_clone.py --mineblock', - 'notifications.py', - 'invalidateblock.py', - 'replace-by-fee.py', + 'wallet_txn_doublespend.py', + 'wallet_txn_clone.py --mineblock', + 'feature_notifications.py', + 'rpc_invalidateblock.py', + 'feature_rbf.py', ] # Place EXTENDED_SCRIPTS first since it has the 3 longest running tests @@ -174,6 +183,7 @@ def main(): epilog=''' Help text and arguments for individual test script:''', formatter_class=argparse.RawTextHelpFormatter) + parser.add_argument('--combinedlogslen', '-c', type=int, default=0, help='print a combined log (of length n lines) from all test nodes and test framework to the console on failure.') parser.add_argument('--coverage', action='store_true', help='generate a basic coverage report for the RPC interface') parser.add_argument('--exclude', '-x', help='specify a comma-separated-list of scripts to exclude.') parser.add_argument('--extended', action='store_true', help='run the extended test suite in addition to the basic tests') @@ -262,13 +272,14 @@ def main(): sys.exit(0) check_script_list(config["environment"]["SRCDIR"]) + check_script_prefixes() if not args.keepcache: shutil.rmtree("%s/test/cache" % config["environment"]["BUILDDIR"], ignore_errors=True) - run_tests(test_list, config["environment"]["SRCDIR"], config["environment"]["BUILDDIR"], config["environment"]["EXEEXT"], tmpdir, args.jobs, args.coverage, passon_args) + run_tests(test_list, config["environment"]["SRCDIR"], config["environment"]["BUILDDIR"], config["environment"]["EXEEXT"], tmpdir, args.jobs, args.coverage, passon_args, args.combinedlogslen) -def run_tests(test_list, src_dir, build_dir, exeext, tmpdir, jobs=1, enable_coverage=False, args=[]): +def run_tests(test_list, src_dir, build_dir, exeext, tmpdir, jobs=1, enable_coverage=False, args=[], combined_logs_len=0): # Warn if bitcoind is already running (unix only) try: if subprocess.check_output(["pidof", "bitcoind"]) is not None: @@ -300,7 +311,11 @@ def run_tests(test_list, src_dir, build_dir, exeext, tmpdir, jobs=1, enable_cove if len(test_list) > 1 and jobs > 1: # Populate cache - subprocess.check_output([tests_dir + 'create_cache.py'] + flags + ["--tmpdir=%s/cache" % tmpdir]) + try: + subprocess.check_output([tests_dir + 'create_cache.py'] + flags + ["--tmpdir=%s/cache" % tmpdir]) + except subprocess.CalledProcessError as e: + sys.stdout.buffer.write(e.output) + raise #Run Tests job_queue = TestHandler(jobs, tests_dir, tmpdir, test_list, flags) @@ -310,7 +325,7 @@ def run_tests(test_list, src_dir, build_dir, exeext, tmpdir, jobs=1, enable_cove max_len_name = len(max(test_list, key=len)) for _ in range(len(test_list)): - test_result, stdout, stderr = job_queue.get_next() + test_result, testdir, stdout, stderr = job_queue.get_next() test_results.append(test_result) if test_result.status == "Passed": @@ -321,6 +336,14 @@ def run_tests(test_list, src_dir, build_dir, exeext, tmpdir, jobs=1, enable_cove print("\n%s%s%s failed, Duration: %s s\n" % (BOLD[1], test_result.name, BOLD[0], test_result.time)) print(BOLD[1] + 'stdout:\n' + BOLD[0] + stdout + '\n') print(BOLD[1] + 'stderr:\n' + BOLD[0] + stderr + '\n') + if combined_logs_len and os.path.isdir(testdir): + # Print the final `combinedlogslen` lines of the combined logs + print('{}Combine the logs and print the last {} lines ...{}'.format(BOLD[1], combined_logs_len, BOLD[0])) + print('\n============') + print('{}Combined log for {}:{}'.format(BOLD[1], testdir, BOLD[0])) + print('============\n') + combined_logs, _ = subprocess.Popen([os.path.join(tests_dir, 'combine_logs.py'), '-c', testdir], universal_newlines=True, stdout=subprocess.PIPE).communicate() + print("\n".join(deque(combined_logs.splitlines(), combined_logs_len))) print_results(test_results, max_len_name, (int(time.time() - time0))) @@ -385,13 +408,15 @@ class TestHandler: log_stdout = tempfile.SpooledTemporaryFile(max_size=2**16) log_stderr = tempfile.SpooledTemporaryFile(max_size=2**16) test_argv = t.split() - tmpdir = ["--tmpdir=%s/%s_%s" % (self.tmpdir, re.sub(".py$", "", test_argv[0]), portseed)] + testdir = "{}/{}_{}".format(self.tmpdir, re.sub(".py$", "", test_argv[0]), portseed) + tmpdir_arg = ["--tmpdir={}".format(testdir)] self.jobs.append((t, time.time(), - subprocess.Popen([self.tests_dir + test_argv[0]] + test_argv[1:] + self.flags + portseed_arg + tmpdir, + subprocess.Popen([self.tests_dir + test_argv[0]] + test_argv[1:] + self.flags + portseed_arg + tmpdir_arg, universal_newlines=True, stdout=log_stdout, stderr=log_stderr), + testdir, log_stdout, log_stderr)) if not self.jobs: @@ -400,7 +425,7 @@ class TestHandler: # Return first proc that finishes time.sleep(.5) for j in self.jobs: - (name, time0, proc, log_out, log_err) = j + (name, time0, proc, testdir, log_out, log_err) = j if os.getenv('TRAVIS') == 'true' and int(time.time() - time0) > 20 * 60: # In travis, timeout individual tests after 20 minutes (to stop tests hanging and not # providing useful output. @@ -418,7 +443,7 @@ class TestHandler: self.num_running -= 1 self.jobs.remove(j) - return TestResult(name, status, int(time.time() - time0)), stdout, stderr + return TestResult(name, status, int(time.time() - time0)), testdir, stdout, stderr print('.', end='', flush=True) class TestResult(): @@ -446,6 +471,24 @@ class TestResult(): return self.status != "Failed" +def check_script_prefixes(): + """Check that at most a handful of the + test scripts don't start with one of the allowed name prefixes.""" + + # LEEWAY is provided as a transition measure, so that pull-requests + # that introduce new tests that don't conform with the naming + # convention don't immediately cause the tests to fail. + LEEWAY = 10 + + good_prefixes_re = re.compile("(example|feature|interface|mempool|mining|p2p|rpc|wallet)_") + bad_script_names = [script for script in ALL_SCRIPTS if good_prefixes_re.match(script) is None] + + if len(bad_script_names) > 0: + print("INFO: %d tests not meeting naming conventions:" % (len(bad_script_names))) + print(" %s" % ("\n ".join(sorted(bad_script_names)))) + assert len(bad_script_names) <= LEEWAY, "Too many tests not following naming convention! (%d found, maximum: %d)" % (len(bad_script_names), LEEWAY) + + def check_script_list(src_dir): """Check scripts directory. diff --git a/test/functional/abandonconflict.py b/test/functional/wallet_abandonconflict.py index e8dbc86469..14964438af 100755 --- a/test/functional/abandonconflict.py +++ b/test/functional/wallet_abandonconflict.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2014-2016 The Bitcoin Core developers +# Copyright (c) 2014-2017 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test the abandontransaction RPC. diff --git a/test/functional/wallet-accounts.py b/test/functional/wallet_accounts.py index bc1efaee15..ecd1cfc82b 100755 --- a/test/functional/wallet-accounts.py +++ b/test/functional/wallet_accounts.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2016 The Bitcoin Core developers +# Copyright (c) 2016-2017 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 account RPCs. @@ -126,7 +126,7 @@ class WalletAccountsTest(BitcoinTestFramework): addresses = [] for x in range(10): addresses.append(node.getnewaddress()) - multisig_address = node.addmultisigaddress(5, addresses, account.name) + multisig_address = node.addmultisigaddress(5, addresses, account.name)['address'] account.add_address(multisig_address) account.verify(node) node.sendfrom("", multisig_address, 50) diff --git a/test/functional/wallet_address_types.py b/test/functional/wallet_address_types.py new file mode 100755 index 0000000000..38a3425214 --- /dev/null +++ b/test/functional/wallet_address_types.py @@ -0,0 +1,294 @@ +#!/usr/bin/env python3 +# Copyright (c) 2017 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 that the wallet can send and receive using all combinations of address types. + +There are 5 nodes-under-test: + - node0 uses legacy addresses + - node1 uses p2sh/segwit addresses + - node2 uses p2sh/segwit addresses and bech32 addresses for change + - node3 uses bech32 addresses + - node4 uses a p2sh/segwit addresses for change + +node5 exists to generate new blocks. + +## Multisig address test + +Test that adding a multisig address with: + - an uncompressed pubkey always gives a legacy address + - only compressed pubkeys gives the an `-addresstype` address + +## Sending to address types test + +A series of tests, iterating over node0-node4. In each iteration of the test, one node sends: + - 10/101th of its balance to itself (using getrawchangeaddress for single key addresses) + - 20/101th to the next node + - 30/101th to the node after that + - 40/101th to the remaining node + - 1/101th remains as fee+change + +Iterate over each node for single key addresses, and then over each node for +multisig addresses. + +Repeat test, but with explicit address_type parameters passed to getnewaddress +and getrawchangeaddress: + - node0 and node3 send to p2sh. + - node1 sends to bech32. + - node2 sends to legacy. + +As every node sends coins after receiving, this also +verifies that spending coins sent to all these address types works. + +## Change type test + +Test that the nodes generate the correct change address type: + - node0 always uses a legacy change address. + - node1 uses a bech32 addresses for change if any destination address is bech32. + - node2 always uses a bech32 address for change + - node3 always uses a bech32 address for change + - node4 always uses p2sh/segwit output for change. +""" + +from decimal import Decimal +import itertools + +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import ( + assert_equal, + assert_greater_than, + assert_raises_rpc_error, + connect_nodes_bi, + sync_blocks, + sync_mempools, +) + +class AddressTypeTest(BitcoinTestFramework): + def set_test_params(self): + self.num_nodes = 6 + self.extra_args = [ + ["-addresstype=legacy"], + ["-addresstype=p2sh-segwit"], + ["-addresstype=p2sh-segwit", "-changetype=bech32"], + ["-addresstype=bech32"], + ["-changetype=p2sh-segwit"], + [] + ] + + def setup_network(self): + self.setup_nodes() + + # Fully mesh-connect nodes for faster mempool sync + for i, j in itertools.product(range(self.num_nodes), repeat=2): + if i > j: + connect_nodes_bi(self.nodes, i, j) + self.sync_all() + + def get_balances(self, confirmed=True): + """Return a list of confirmed or unconfirmed balances.""" + if confirmed: + return [self.nodes[i].getbalance() for i in range(4)] + else: + return [self.nodes[i].getunconfirmedbalance() for i in range(4)] + + def test_address(self, node, address, multisig, typ): + """Run sanity checks on an address.""" + info = self.nodes[node].validateaddress(address) + assert(info['isvalid']) + if not multisig and typ == 'legacy': + # P2PKH + assert(not info['isscript']) + assert(not info['iswitness']) + assert('pubkey' in info) + elif not multisig and typ == 'p2sh-segwit': + # P2SH-P2WPKH + assert(info['isscript']) + assert(not info['iswitness']) + assert_equal(info['script'], 'witness_v0_keyhash') + assert('pubkey' in info) + elif not multisig and typ == 'bech32': + # P2WPKH + assert(not info['isscript']) + assert(info['iswitness']) + assert_equal(info['witness_version'], 0) + assert_equal(len(info['witness_program']), 40) + assert('pubkey' in info) + elif typ == 'legacy': + # P2SH-multisig + assert(info['isscript']) + assert_equal(info['script'], 'multisig') + assert(not info['iswitness']) + assert('pubkeys' in info) + elif typ == 'p2sh-segwit': + # P2SH-P2WSH-multisig + assert(info['isscript']) + assert_equal(info['script'], 'witness_v0_scripthash') + assert(not info['iswitness']) + assert(info['embedded']['isscript']) + assert_equal(info['embedded']['script'], 'multisig') + assert(info['embedded']['iswitness']) + assert_equal(info['embedded']['witness_version'], 0) + assert_equal(len(info['embedded']['witness_program']), 64) + assert('pubkeys' in info['embedded']) + elif typ == 'bech32': + # P2WSH-multisig + assert(info['isscript']) + assert_equal(info['script'], 'multisig') + assert(info['iswitness']) + assert_equal(info['witness_version'], 0) + assert_equal(len(info['witness_program']), 64) + assert('pubkeys' in info) + else: + # Unknown type + assert(False) + + def test_change_output_type(self, node_sender, destinations, expected_type): + txid = self.nodes[node_sender].sendmany(fromaccount="", amounts=dict.fromkeys(destinations, 0.001)) + raw_tx = self.nodes[node_sender].getrawtransaction(txid) + tx = self.nodes[node_sender].decoderawtransaction(raw_tx) + + # Make sure the transaction has change: + assert_equal(len(tx["vout"]), len(destinations) + 1) + + # Make sure the destinations are included, and remove them: + output_addresses = [vout['scriptPubKey']['addresses'][0] for vout in tx["vout"]] + change_addresses = [d for d in output_addresses if d not in destinations] + assert_equal(len(change_addresses), 1) + + self.log.debug("Check if change address " + change_addresses[0] + " is " + expected_type) + self.test_address(node_sender, change_addresses[0], multisig=False, typ=expected_type) + + def run_test(self): + # Mine 101 blocks on node5 to bring nodes out of IBD and make sure that + # no coinbases are maturing for the nodes-under-test during the test + self.nodes[5].generate(101) + sync_blocks(self.nodes) + + uncompressed_1 = "0496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52da7589379515d4e0a604f8141781e62294721166bf621e73a82cbf2342c858ee" + uncompressed_2 = "047211a824f55b505228e4c3d5194c1fcfaa15a456abdf37f9b9d97a4040afc073dee6c89064984f03385237d92167c13e236446b417ab79a0fcae412ae3316b77" + compressed_1 = "0296b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52" + compressed_2 = "037211a824f55b505228e4c3d5194c1fcfaa15a456abdf37f9b9d97a4040afc073" + + # addmultisigaddress with at least 1 uncompressed key should return a legacy address. + for node in range(4): + self.test_address(node, self.nodes[node].addmultisigaddress(2, [uncompressed_1, uncompressed_2])['address'], True, 'legacy') + self.test_address(node, self.nodes[node].addmultisigaddress(2, [compressed_1, uncompressed_2])['address'], True, 'legacy') + self.test_address(node, self.nodes[node].addmultisigaddress(2, [uncompressed_1, compressed_2])['address'], True, 'legacy') + # addmultisigaddress with all compressed keys should return the appropriate address type (even when the keys are not ours). + self.test_address(0, self.nodes[0].addmultisigaddress(2, [compressed_1, compressed_2])['address'], True, 'legacy') + self.test_address(1, self.nodes[1].addmultisigaddress(2, [compressed_1, compressed_2])['address'], True, 'p2sh-segwit') + self.test_address(2, self.nodes[2].addmultisigaddress(2, [compressed_1, compressed_2])['address'], True, 'p2sh-segwit') + self.test_address(3, self.nodes[3].addmultisigaddress(2, [compressed_1, compressed_2])['address'], True, 'bech32') + + for explicit_type, multisig, from_node in itertools.product([False, True], [False, True], range(4)): + address_type = None + if explicit_type and not multisig: + if from_node == 1: + address_type = 'bech32' + elif from_node == 0 or from_node == 3: + address_type = 'p2sh-segwit' + else: + address_type = 'legacy' + self.log.info("Sending from node {} ({}) with{} multisig using {}".format(from_node, self.extra_args[from_node], "" if multisig else "out", "default" if address_type is None else address_type)) + old_balances = self.get_balances() + self.log.debug("Old balances are {}".format(old_balances)) + to_send = (old_balances[from_node] / 101).quantize(Decimal("0.00000001")) + sends = {} + + self.log.debug("Prepare sends") + for n, to_node in enumerate(range(from_node, from_node + 4)): + to_node %= 4 + change = False + if not multisig: + if from_node == to_node: + # When sending non-multisig to self, use getrawchangeaddress + address = self.nodes[to_node].getrawchangeaddress(address_type=address_type) + change = True + else: + address = self.nodes[to_node].getnewaddress(address_type=address_type) + else: + addr1 = self.nodes[to_node].getnewaddress() + addr2 = self.nodes[to_node].getnewaddress() + address = self.nodes[to_node].addmultisigaddress(2, [addr1, addr2])['address'] + + # Do some sanity checking on the created address + if address_type is not None: + typ = address_type + elif to_node == 0: + typ = 'legacy' + elif to_node == 1 or (to_node == 2 and not change): + typ = 'p2sh-segwit' + else: + typ = 'bech32' + self.test_address(to_node, address, multisig, typ) + + # Output entry + sends[address] = to_send * 10 * (1 + n) + + self.log.debug("Sending: {}".format(sends)) + self.nodes[from_node].sendmany("", sends) + sync_mempools(self.nodes) + + unconf_balances = self.get_balances(False) + self.log.debug("Check unconfirmed balances: {}".format(unconf_balances)) + assert_equal(unconf_balances[from_node], 0) + for n, to_node in enumerate(range(from_node + 1, from_node + 4)): + to_node %= 4 + assert_equal(unconf_balances[to_node], to_send * 10 * (2 + n)) + + # node5 collects fee and block subsidy to keep accounting simple + self.nodes[5].generate(1) + sync_blocks(self.nodes) + + new_balances = self.get_balances() + self.log.debug("Check new balances: {}".format(new_balances)) + # We don't know what fee was set, so we can only check bounds on the balance of the sending node + assert_greater_than(new_balances[from_node], to_send * 10) + assert_greater_than(to_send * 11, new_balances[from_node]) + for n, to_node in enumerate(range(from_node + 1, from_node + 4)): + to_node %= 4 + assert_equal(new_balances[to_node], old_balances[to_node] + to_send * 10 * (2 + n)) + + # Get one p2sh/segwit address from node2 and two bech32 addresses from node3: + to_address_p2sh = self.nodes[2].getnewaddress() + to_address_bech32_1 = self.nodes[3].getnewaddress() + to_address_bech32_2 = self.nodes[3].getnewaddress() + + # Fund node 4: + self.nodes[5].sendtoaddress(self.nodes[4].getnewaddress(), Decimal("1")) + self.nodes[5].generate(1) + sync_blocks(self.nodes) + assert_equal(self.nodes[4].getbalance(), 1) + + self.log.info("Nodes with addresstype=legacy never use a P2WPKH change output") + self.test_change_output_type(0, [to_address_bech32_1], 'legacy') + + self.log.info("Nodes with addresstype=p2sh-segwit only use a P2WPKH change output if any destination address is bech32:") + self.test_change_output_type(1, [to_address_p2sh], 'p2sh-segwit') + self.test_change_output_type(1, [to_address_bech32_1], 'bech32') + self.test_change_output_type(1, [to_address_p2sh, to_address_bech32_1], 'bech32') + self.test_change_output_type(1, [to_address_bech32_1, to_address_bech32_2], 'bech32') + + self.log.info("Nodes with change_type=bech32 always use a P2WPKH change output:") + self.test_change_output_type(2, [to_address_bech32_1], 'bech32') + self.test_change_output_type(2, [to_address_p2sh], 'bech32') + + self.log.info("Nodes with addresstype=bech32 always use a P2WPKH change output (unless changetype is set otherwise):") + self.test_change_output_type(3, [to_address_bech32_1], 'bech32') + self.test_change_output_type(3, [to_address_p2sh], 'bech32') + + self.log.info('getrawchangeaddress defaults to addresstype if -changetype is not set and argument is absent') + self.test_address(3, self.nodes[3].getrawchangeaddress(), multisig=False, typ='bech32') + + self.log.info('getrawchangeaddress fails with invalid changetype argument') + assert_raises_rpc_error(-5, "Unknown address type 'bech23'", self.nodes[3].getrawchangeaddress, 'bech23') + + self.log.info("Nodes with changetype=p2sh-segwit never use a P2WPKH change output") + self.test_change_output_type(4, [to_address_bech32_1], 'p2sh-segwit') + self.test_address(4, self.nodes[4].getrawchangeaddress(), multisig=False, typ='p2sh-segwit') + self.log.info("Except for getrawchangeaddress if specified:") + self.test_address(4, self.nodes[4].getrawchangeaddress(), multisig=False, typ='p2sh-segwit') + self.test_address(4, self.nodes[4].getrawchangeaddress('bech32'), multisig=False, typ='bech32') + +if __name__ == '__main__': + AddressTypeTest().main() diff --git a/test/functional/walletbackup.py b/test/functional/wallet_backup.py index 85a149793e..b4be7debb5 100755 --- a/test/functional/walletbackup.py +++ b/test/functional/wallet_backup.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2014-2016 The Bitcoin Core developers +# Copyright (c) 2014-2017 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test the wallet backup features. @@ -90,9 +90,9 @@ class WalletBackupTest(BitcoinTestFramework): self.stop_node(2) def erase_three(self): - os.remove(self.options.tmpdir + "/node0/regtest/wallet.dat") - os.remove(self.options.tmpdir + "/node1/regtest/wallet.dat") - os.remove(self.options.tmpdir + "/node2/regtest/wallet.dat") + os.remove(self.options.tmpdir + "/node0/regtest/wallets/wallet.dat") + os.remove(self.options.tmpdir + "/node1/regtest/wallets/wallet.dat") + os.remove(self.options.tmpdir + "/node2/regtest/wallets/wallet.dat") def run_test(self): self.log.info("Generating initial blockchain") @@ -154,9 +154,9 @@ class WalletBackupTest(BitcoinTestFramework): shutil.rmtree(self.options.tmpdir + "/node2/regtest/chainstate") # Restore wallets from backup - shutil.copyfile(tmpdir + "/node0/wallet.bak", tmpdir + "/node0/regtest/wallet.dat") - shutil.copyfile(tmpdir + "/node1/wallet.bak", tmpdir + "/node1/regtest/wallet.dat") - shutil.copyfile(tmpdir + "/node2/wallet.bak", tmpdir + "/node2/regtest/wallet.dat") + shutil.copyfile(tmpdir + "/node0/wallet.bak", tmpdir + "/node0/regtest/wallets/wallet.dat") + shutil.copyfile(tmpdir + "/node1/wallet.bak", tmpdir + "/node1/regtest/wallets/wallet.dat") + shutil.copyfile(tmpdir + "/node2/wallet.bak", tmpdir + "/node2/regtest/wallets/wallet.dat") self.log.info("Re-starting nodes") self.start_three() @@ -192,10 +192,10 @@ class WalletBackupTest(BitcoinTestFramework): # Backup to source wallet file must fail sourcePaths = [ - tmpdir + "/node0/regtest/wallet.dat", - tmpdir + "/node0/./regtest/wallet.dat", - tmpdir + "/node0/regtest/", - tmpdir + "/node0/regtest"] + tmpdir + "/node0/regtest/wallets/wallet.dat", + tmpdir + "/node0/./regtest/wallets/wallet.dat", + tmpdir + "/node0/regtest/wallets/", + tmpdir + "/node0/regtest/wallets"] for sourcePath in sourcePaths: assert_raises_rpc_error(-4, "backup failed", self.nodes[0].backupwallet, sourcePath) diff --git a/test/functional/wallet.py b/test/functional/wallet_basic.py index db60df18ed..a90dbc8adf 100755 --- a/test/functional/wallet.py +++ b/test/functional/wallet_basic.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2014-2016 The Bitcoin Core developers +# Copyright (c) 2014-2017 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test the wallet.""" @@ -27,6 +27,9 @@ class WalletTest(BitcoinTestFramework): assert_fee_amount(fee, tx_size, fee_per_byte * 1000) return curr_balance + def get_vsize(self, txn): + return self.nodes[0].decoderawtransaction(txn)['vsize'] + def run_test(self): # Check that there's no UTXO on none of the nodes assert_equal(len(self.nodes[0].listunspent()), 0) @@ -162,7 +165,7 @@ class WalletTest(BitcoinTestFramework): txid = self.nodes[2].sendtoaddress(address, 10, "", "", False) self.nodes[2].generate(1) self.sync_all([self.nodes[0:3]]) - node_2_bal = self.check_fee_amount(self.nodes[2].getbalance(), Decimal('84'), fee_per_byte, count_bytes(self.nodes[2].getrawtransaction(txid))) + node_2_bal = self.check_fee_amount(self.nodes[2].getbalance(), Decimal('84'), fee_per_byte, self.get_vsize(self.nodes[2].getrawtransaction(txid))) assert_equal(self.nodes[0].getbalance(), Decimal('10')) # Send 10 BTC with subtract fee from amount @@ -171,14 +174,14 @@ class WalletTest(BitcoinTestFramework): self.sync_all([self.nodes[0:3]]) node_2_bal -= Decimal('10') assert_equal(self.nodes[2].getbalance(), node_2_bal) - node_0_bal = self.check_fee_amount(self.nodes[0].getbalance(), Decimal('20'), fee_per_byte, count_bytes(self.nodes[2].getrawtransaction(txid))) + node_0_bal = self.check_fee_amount(self.nodes[0].getbalance(), Decimal('20'), fee_per_byte, self.get_vsize(self.nodes[2].getrawtransaction(txid))) # Sendmany 10 BTC txid = self.nodes[2].sendmany('from1', {address: 10}, 0, "", []) self.nodes[2].generate(1) self.sync_all([self.nodes[0:3]]) node_0_bal += Decimal('10') - node_2_bal = self.check_fee_amount(self.nodes[2].getbalance(), node_2_bal - Decimal('10'), fee_per_byte, count_bytes(self.nodes[2].getrawtransaction(txid))) + node_2_bal = self.check_fee_amount(self.nodes[2].getbalance(), node_2_bal - Decimal('10'), fee_per_byte, self.get_vsize(self.nodes[2].getrawtransaction(txid))) assert_equal(self.nodes[0].getbalance(), node_0_bal) # Sendmany 10 BTC with subtract fee from amount @@ -187,7 +190,7 @@ class WalletTest(BitcoinTestFramework): self.sync_all([self.nodes[0:3]]) node_2_bal -= Decimal('10') assert_equal(self.nodes[2].getbalance(), node_2_bal) - node_0_bal = self.check_fee_amount(self.nodes[0].getbalance(), node_0_bal + Decimal('10'), fee_per_byte, count_bytes(self.nodes[2].getrawtransaction(txid))) + node_0_bal = self.check_fee_amount(self.nodes[0].getbalance(), node_0_bal + Decimal('10'), fee_per_byte, self.get_vsize(self.nodes[2].getrawtransaction(txid))) # Test ResendWalletTransactions: # Create a couple of transactions, then start up a fourth diff --git a/test/functional/bumpfee.py b/test/functional/wallet_bumpfee.py index 008e83d5b2..2cd4127854 100755 --- a/test/functional/bumpfee.py +++ b/test/functional/wallet_bumpfee.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2016 The Bitcoin Core developers +# Copyright (c) 2016-2017 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test the bumpfee RPC. @@ -14,7 +14,7 @@ added in the future, they should try to follow the same convention and not make assumptions about execution order. """ -from segwit import send_to_witness +from test_framework.blocktools import send_to_witness from test_framework.test_framework import BitcoinTestFramework from test_framework import blocktools from test_framework.mininode import CTransaction @@ -33,7 +33,7 @@ class BumpFeeTest(BitcoinTestFramework): def set_test_params(self): self.num_nodes = 2 self.setup_clean_chain = True - self.extra_args = [["-prematurewitness", "-walletprematurewitness", "-walletrbf={}".format(i)] + self.extra_args = [["-prematurewitness", "-walletprematurewitness", "-deprecatedrpc=addwitnessaddress", "-walletrbf={}".format(i)] for i in range(self.num_nodes)] def run_test(self): @@ -194,7 +194,7 @@ def test_settxfee(rbf_node, dest_address): requested_feerate = Decimal("0.00025000") rbf_node.settxfee(requested_feerate) bumped_tx = rbf_node.bumpfee(rbfid) - actual_feerate = bumped_tx["fee"] * 1000 / rbf_node.getrawtransaction(bumped_tx["txid"], True)["size"] + actual_feerate = bumped_tx["fee"] * 1000 / rbf_node.getrawtransaction(bumped_tx["txid"], True)["vsize"] # Assert that the difference between the requested feerate and the actual # feerate of the bumped transaction is small. assert_greater_than(Decimal("0.00001000"), abs(requested_feerate - actual_feerate)) @@ -290,6 +290,7 @@ def submit_block_with_tx(node, tx): block.vtx.append(ctx) block.rehash() block.hashMerkleRoot = block.calc_merkle_root() + blocktools.add_witness_commitment(block) block.solve() node.submitblock(bytes_to_hex_str(block.serialize(True))) return block diff --git a/test/functional/disablewallet.py b/test/functional/wallet_disable.py index c75ef9b9f1..b0627d88ac 100755 --- a/test/functional/disablewallet.py +++ b/test/functional/wallet_disable.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2015-2016 The Bitcoin Core developers +# Copyright (c) 2015-2017 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 a node with the -disablewallet option. diff --git a/test/functional/wallet-dump.py b/test/functional/wallet_dump.py index 47de8777a6..77f90ffb81 100755 --- a/test/functional/wallet-dump.py +++ b/test/functional/wallet_dump.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2016 The Bitcoin Core developers +# Copyright (c) 2016-2017 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test the dumpwallet RPC.""" @@ -10,13 +10,14 @@ from test_framework.test_framework import BitcoinTestFramework from test_framework.util import (assert_equal, assert_raises_rpc_error) -def read_dump(file_name, addrs, hd_master_addr_old): +def read_dump(file_name, addrs, script_addrs, hd_master_addr_old): """ Read the given dump, count the addrs that match, count change and reserve. Also check that the old hd_master is inactive """ with open(file_name, encoding='utf8') as inputfile: found_addr = 0 + found_script_addr = 0 found_addr_chg = 0 found_addr_rsv = 0 hd_master_addr_ret = None @@ -38,6 +39,9 @@ def read_dump(file_name, addrs, hd_master_addr_old): # ensure we have generated a new hd master key assert(hd_master_addr_old != addr) hd_master_addr_ret = addr + elif keytype == "script=1": + # scripts don't have keypaths + keypath = None else: keypath = addr_keypath.rstrip().split("hdkeypath=")[1] @@ -52,13 +56,20 @@ def read_dump(file_name, addrs, hd_master_addr_old): elif keytype == "reserve=1": found_addr_rsv += 1 break - return found_addr, found_addr_chg, found_addr_rsv, hd_master_addr_ret + + # count scripts + for script_addr in script_addrs: + if script_addr == addr.rstrip() and keytype == "script=1": + found_script_addr += 1 + break + + return found_addr, found_script_addr, found_addr_chg, found_addr_rsv, hd_master_addr_ret class WalletDumpTest(BitcoinTestFramework): def set_test_params(self): self.num_nodes = 1 - self.extra_args = [["-keypool=90"]] + self.extra_args = [["-keypool=90", "-addresstype=legacy", "-deprecatedrpc=addwitnessaddress"]] def setup_network(self, split=False): # Use 1 minute timeout because the initial getnewaddress RPC can take @@ -81,13 +92,19 @@ class WalletDumpTest(BitcoinTestFramework): # Should be a no-op: self.nodes[0].keypoolrefill() + # Test scripts dump by adding a P2SH witness and a 1-of-1 multisig address + witness_addr = self.nodes[0].addwitnessaddress(addrs[0]["address"], True) + multisig_addr = self.nodes[0].addmultisigaddress(1, [addrs[1]["address"]])["address"] + script_addrs = [witness_addr, multisig_addr] + # dump unencrypted wallet result = self.nodes[0].dumpwallet(tmpdir + "/node0/wallet.unencrypted.dump") assert_equal(result['filename'], os.path.abspath(tmpdir + "/node0/wallet.unencrypted.dump")) - found_addr, found_addr_chg, found_addr_rsv, hd_master_addr_unenc = \ - read_dump(tmpdir + "/node0/wallet.unencrypted.dump", addrs, None) + found_addr, found_script_addr, found_addr_chg, found_addr_rsv, hd_master_addr_unenc = \ + read_dump(tmpdir + "/node0/wallet.unencrypted.dump", addrs, script_addrs, None) assert_equal(found_addr, test_addr_count) # all keys must be in the dump + assert_equal(found_script_addr, 2) # all scripts must be in the dump assert_equal(found_addr_chg, 50) # 50 blocks where mined assert_equal(found_addr_rsv, 90*2) # 90 keys plus 100% internal keys @@ -99,14 +116,29 @@ class WalletDumpTest(BitcoinTestFramework): self.nodes[0].keypoolrefill() self.nodes[0].dumpwallet(tmpdir + "/node0/wallet.encrypted.dump") - found_addr, found_addr_chg, found_addr_rsv, _ = \ - read_dump(tmpdir + "/node0/wallet.encrypted.dump", addrs, hd_master_addr_unenc) + found_addr, found_script_addr, found_addr_chg, found_addr_rsv, _ = \ + read_dump(tmpdir + "/node0/wallet.encrypted.dump", addrs, script_addrs, hd_master_addr_unenc) assert_equal(found_addr, test_addr_count) + assert_equal(found_script_addr, 2) assert_equal(found_addr_chg, 90*2 + 50) # old reserve keys are marked as change now assert_equal(found_addr_rsv, 90*2) # Overwriting should fail assert_raises_rpc_error(-8, "already exists", self.nodes[0].dumpwallet, tmpdir + "/node0/wallet.unencrypted.dump") + # Restart node with new wallet, and test importwallet + self.stop_node(0) + self.start_node(0, ['-wallet=w2']) + + # Make sure the address is not IsMine before import + result = self.nodes[0].validateaddress(multisig_addr) + assert(result['ismine'] == False) + + self.nodes[0].importwallet(os.path.abspath(tmpdir + "/node0/wallet.unencrypted.dump")) + + # Now check IsMine is true + result = self.nodes[0].validateaddress(multisig_addr) + assert(result['ismine'] == True) + if __name__ == '__main__': WalletDumpTest().main () diff --git a/test/functional/wallet-encryption.py b/test/functional/wallet_encryption.py index db62e1e30f..3c927ee484 100755 --- a/test/functional/wallet-encryption.py +++ b/test/functional/wallet_encryption.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2016 The Bitcoin Core developers +# Copyright (c) 2016-2017 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 Wallet encryption""" @@ -10,6 +10,8 @@ from test_framework.test_framework import BitcoinTestFramework from test_framework.util import ( assert_equal, assert_raises_rpc_error, + assert_greater_than, + assert_greater_than_or_equal, ) class WalletEncryptionTest(BitcoinTestFramework): @@ -56,6 +58,23 @@ class WalletEncryptionTest(BitcoinTestFramework): assert_raises_rpc_error(-14, "wallet passphrase entered was incorrect", self.nodes[0].walletpassphrase, passphrase, 10) self.nodes[0].walletpassphrase(passphrase2, 10) assert_equal(privkey, self.nodes[0].dumpprivkey(address)) + self.nodes[0].walletlock() + + # Test timeout bounds + assert_raises_rpc_error(-8, "Timeout cannot be negative.", self.nodes[0].walletpassphrase, passphrase2, -10) + # Check the timeout + # Check a time less than the limit + expected_time = int(time.time()) + (1 << 30) - 600 + self.nodes[0].walletpassphrase(passphrase2, (1 << 30) - 600) + actual_time = self.nodes[0].getwalletinfo()['unlocked_until'] + assert_greater_than_or_equal(actual_time, expected_time) + assert_greater_than(expected_time + 5, actual_time) # 5 second buffer + # Check a time greater than the limit + expected_time = int(time.time()) + (1 << 30) - 1 + self.nodes[0].walletpassphrase(passphrase2, (1 << 33)) + actual_time = self.nodes[0].getwalletinfo()['unlocked_until'] + assert_greater_than_or_equal(actual_time, expected_time) + assert_greater_than(expected_time + 5, actual_time) # 5 second buffer if __name__ == '__main__': WalletEncryptionTest().main() diff --git a/test/functional/wallet-hd.py b/test/functional/wallet_hd.py index 9b6ce68609..9f0e9acb47 100755 --- a/test/functional/wallet-hd.py +++ b/test/functional/wallet_hd.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2016 The Bitcoin Core developers +# Copyright (c) 2016-2017 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 Hierarchical Deterministic wallet function.""" @@ -73,7 +73,7 @@ class WalletHDTest(BitcoinTestFramework): # otherwise node1 would auto-recover all funds in flag the keypool keys as used shutil.rmtree(os.path.join(tmpdir, "node1/regtest/blocks")) shutil.rmtree(os.path.join(tmpdir, "node1/regtest/chainstate")) - shutil.copyfile(os.path.join(tmpdir, "hd.bak"), os.path.join(tmpdir, "node1/regtest/wallet.dat")) + shutil.copyfile(os.path.join(tmpdir, "hd.bak"), os.path.join(tmpdir, "node1/regtest/wallets/wallet.dat")) self.start_node(1) # Assert that derivation is deterministic diff --git a/test/functional/import-rescan.py b/test/functional/wallet_import_rescan.py index 6807fa6696..d193a99d5b 100755 --- a/test/functional/import-rescan.py +++ b/test/functional/wallet_import_rescan.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2014-2016 The Bitcoin Core developers +# Copyright (c) 2014-2017 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 wallet import RPCs. @@ -119,7 +119,7 @@ class ImportRescanTest(BitcoinTestFramework): self.num_nodes = 2 + len(IMPORT_NODES) def setup_network(self): - extra_args = [[] for _ in range(self.num_nodes)] + extra_args = [["-addresstype=legacy"] for _ in range(self.num_nodes)] for i, import_node in enumerate(IMPORT_NODES, 2): if import_node.prune: extra_args[i] += ["-prune=1"] diff --git a/test/functional/importmulti.py b/test/functional/wallet_importmulti.py index a691595f15..be9be83839 100755 --- a/test/functional/importmulti.py +++ b/test/functional/wallet_importmulti.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2014-2016 The Bitcoin Core developers +# Copyright (c) 2014-2017 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test the importmulti RPC.""" @@ -9,6 +9,7 @@ from test_framework.util import * class ImportMultiTest (BitcoinTestFramework): def set_test_params(self): self.num_nodes = 2 + self.extra_args = [["-addresstype=legacy"], ["-addresstype=legacy"]] self.setup_clean_chain = True def setup_network(self): @@ -227,7 +228,7 @@ class ImportMultiTest (BitcoinTestFramework): sig_address_1 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress()) sig_address_2 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress()) sig_address_3 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress()) - multi_sig_script = self.nodes[0].createmultisig(2, [sig_address_1['address'], sig_address_2['address'], sig_address_3['pubkey']]) + multi_sig_script = self.nodes[0].createmultisig(2, [sig_address_1['pubkey'], sig_address_2['pubkey'], sig_address_3['pubkey']]) self.nodes[1].generate(100) transactionid = self.nodes[1].sendtoaddress(multi_sig_script['address'], 10.00) self.nodes[1].generate(1) @@ -254,7 +255,7 @@ class ImportMultiTest (BitcoinTestFramework): sig_address_1 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress()) sig_address_2 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress()) sig_address_3 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress()) - multi_sig_script = self.nodes[0].createmultisig(2, [sig_address_1['address'], sig_address_2['address'], sig_address_3['pubkey']]) + multi_sig_script = self.nodes[0].createmultisig(2, [sig_address_1['pubkey'], sig_address_2['pubkey'], sig_address_3['pubkey']]) self.nodes[1].generate(100) transactionid = self.nodes[1].sendtoaddress(multi_sig_script['address'], 10.00) self.nodes[1].generate(1) @@ -281,7 +282,7 @@ class ImportMultiTest (BitcoinTestFramework): sig_address_1 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress()) sig_address_2 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress()) sig_address_3 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress()) - multi_sig_script = self.nodes[0].createmultisig(2, [sig_address_1['address'], sig_address_2['address'], sig_address_3['pubkey']]) + multi_sig_script = self.nodes[0].createmultisig(2, [sig_address_1['pubkey'], sig_address_2['pubkey'], sig_address_3['pubkey']]) self.nodes[1].generate(100) transactionid = self.nodes[1].sendtoaddress(multi_sig_script['address'], 10.00) self.nodes[1].generate(1) @@ -308,7 +309,7 @@ class ImportMultiTest (BitcoinTestFramework): sig_address_1 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress()) sig_address_2 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress()) sig_address_3 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress()) - multi_sig_script = self.nodes[0].createmultisig(2, [sig_address_1['address'], sig_address_2['address'], sig_address_3['pubkey']]) + multi_sig_script = self.nodes[0].createmultisig(2, [sig_address_1['pubkey'], sig_address_2['pubkey'], sig_address_3['pubkey']]) self.nodes[1].generate(100) transactionid = self.nodes[1].sendtoaddress(multi_sig_script['address'], 10.00) self.nodes[1].generate(1) diff --git a/test/functional/importprunedfunds.py b/test/functional/wallet_importprunedfunds.py index 068052409a..6b2919b5ae 100755 --- a/test/functional/importprunedfunds.py +++ b/test/functional/wallet_importprunedfunds.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2014-2016 The Bitcoin Core developers +# Copyright (c) 2014-2017 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test the importprunedfunds and removeprunedfunds RPCs.""" diff --git a/test/functional/keypool.py b/test/functional/wallet_keypool.py index f2701c36bd..45a5eed8ec 100755 --- a/test/functional/keypool.py +++ b/test/functional/wallet_keypool.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2014-2016 The Bitcoin Core developers +# Copyright (c) 2014-2017 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test the wallet keypool and interaction with wallet encryption/locking.""" diff --git a/test/functional/keypool-topup.py b/test/functional/wallet_keypool_topup.py index 160a0f7ae5..e7af3c3987 100755 --- a/test/functional/keypool-topup.py +++ b/test/functional/wallet_keypool_topup.py @@ -33,7 +33,7 @@ class KeypoolRestoreTest(BitcoinTestFramework): self.stop_node(1) - shutil.copyfile(self.tmpdir + "/node1/regtest/wallet.dat", self.tmpdir + "/wallet.bak") + shutil.copyfile(self.tmpdir + "/node1/regtest/wallets/wallet.dat", self.tmpdir + "/wallet.bak") self.start_node(1, self.extra_args[1]) connect_nodes_bi(self.nodes, 0, 1) @@ -56,7 +56,7 @@ class KeypoolRestoreTest(BitcoinTestFramework): self.stop_node(1) - shutil.copyfile(self.tmpdir + "/wallet.bak", self.tmpdir + "/node1/regtest/wallet.dat") + shutil.copyfile(self.tmpdir + "/wallet.bak", self.tmpdir + "/node1/regtest/wallets/wallet.dat") self.log.info("Verify keypool is restored and balance is correct") diff --git a/test/functional/receivedby.py b/test/functional/wallet_listreceivedby.py index 97da19546f..1f2b3c8aa7 100755 --- a/test/functional/receivedby.py +++ b/test/functional/wallet_listreceivedby.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2014-2016 The Bitcoin Core developers +# Copyright (c) 2014-2017 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test the listreceivedbyaddress RPC.""" diff --git a/test/functional/listsinceblock.py b/test/functional/wallet_listsinceblock.py index 67e7744bf8..67e7744bf8 100755 --- a/test/functional/listsinceblock.py +++ b/test/functional/wallet_listsinceblock.py diff --git a/test/functional/wallet_multiwallet.py b/test/functional/wallet_multiwallet.py new file mode 100755 index 0000000000..b07e451667 --- /dev/null +++ b/test/functional/wallet_multiwallet.py @@ -0,0 +1,133 @@ +#!/usr/bin/env python3 +# Copyright (c) 2017 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 multiwallet. + +Verify that a bitcoind node can load multiple wallet files +""" +import os +import shutil + +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import assert_equal, assert_raises_rpc_error + +class MultiWalletTest(BitcoinTestFramework): + def set_test_params(self): + self.setup_clean_chain = True + self.num_nodes = 2 + self.extra_args = [['-wallet=w1', '-wallet=w2', '-wallet=w3', '-wallet=w'], []] + self.supports_cli = True + + def run_test(self): + node = self.nodes[0] + + data_dir = lambda *p: os.path.join(node.datadir, 'regtest', *p) + wallet_dir = lambda *p: data_dir('wallets', *p) + wallet = lambda name: node.get_wallet_rpc(name) + + assert_equal(set(node.listwallets()), {"w1", "w2", "w3", "w"}) + + self.stop_nodes() + + self.assert_start_raises_init_error(0, ['-walletdir=wallets'], 'Error: Specified -walletdir "wallets" does not exist') + self.assert_start_raises_init_error(0, ['-walletdir=wallets'], 'Error: Specified -walletdir "wallets" is a relative path', cwd=data_dir()) + self.assert_start_raises_init_error(0, ['-walletdir=debug.log'], 'Error: Specified -walletdir "debug.log" is not a directory', cwd=data_dir()) + + # should not initialize if there are duplicate wallets + self.assert_start_raises_init_error(0, ['-wallet=w1', '-wallet=w1'], 'Error loading wallet w1. Duplicate -wallet filename specified.') + + # should not initialize if wallet file is a directory + os.mkdir(wallet_dir('w11')) + self.assert_start_raises_init_error(0, ['-wallet=w11'], 'Error loading wallet w11. -wallet filename must be a regular file.') + + # should not initialize if one wallet is a copy of another + shutil.copyfile(wallet_dir('w2'), wallet_dir('w22')) + self.assert_start_raises_init_error(0, ['-wallet=w2', '-wallet=w22'], 'duplicates fileid') + + # should not initialize if wallet file is a symlink + os.symlink(wallet_dir('w1'), wallet_dir('w12')) + self.assert_start_raises_init_error(0, ['-wallet=w12'], 'Error loading wallet w12. -wallet filename must be a regular file.') + + # should not initialize if the specified walletdir does not exist + self.assert_start_raises_init_error(0, ['-walletdir=bad'], 'Error: Specified -walletdir "bad" does not exist') + # should not initialize if the specified walletdir is not a directory + not_a_dir = wallet_dir('notadir') + open(not_a_dir, 'a').close() + self.assert_start_raises_init_error(0, ['-walletdir=' + not_a_dir], 'Error: Specified -walletdir "' + not_a_dir + '" is not a directory') + + # if wallets/ doesn't exist, datadir should be the default wallet dir + wallet_dir2 = data_dir('walletdir') + os.rename(wallet_dir(), wallet_dir2) + self.start_node(0, ['-wallet=w4', '-wallet=w5']) + assert_equal(set(node.listwallets()), {"w4", "w5"}) + w5 = wallet("w5") + w5.generate(1) + + # now if wallets/ exists again, but the rootdir is specified as the walletdir, w4 and w5 should still be loaded + os.rename(wallet_dir2, wallet_dir()) + self.restart_node(0, ['-wallet=w4', '-wallet=w5', '-walletdir=' + data_dir()]) + assert_equal(set(node.listwallets()), {"w4", "w5"}) + w5 = wallet("w5") + w5_info = w5.getwalletinfo() + assert_equal(w5_info['immature_balance'], 50) + + competing_wallet_dir = os.path.join(self.options.tmpdir, 'competing_walletdir') + os.mkdir(competing_wallet_dir) + self.restart_node(0, ['-walletdir='+competing_wallet_dir]) + self.assert_start_raises_init_error(1, ['-walletdir='+competing_wallet_dir], 'Error initializing wallet database environment') + + self.restart_node(0, self.extra_args[0]) + + w1 = wallet("w1") + w2 = wallet("w2") + w3 = wallet("w3") + w4 = wallet("w") + wallet_bad = wallet("bad") + + w1.generate(1) + + # accessing invalid wallet fails + assert_raises_rpc_error(-18, "Requested wallet does not exist or is not loaded", wallet_bad.getwalletinfo) + + # accessing wallet RPC without using wallet endpoint fails + assert_raises_rpc_error(-19, "Wallet file not specified", node.getwalletinfo) + + # check w1 wallet balance + w1_info = w1.getwalletinfo() + assert_equal(w1_info['immature_balance'], 50) + w1_name = w1_info['walletname'] + assert_equal(w1_name, "w1") + + # check w2 wallet balance + w2_info = w2.getwalletinfo() + assert_equal(w2_info['immature_balance'], 0) + w2_name = w2_info['walletname'] + assert_equal(w2_name, "w2") + + w3_name = w3.getwalletinfo()['walletname'] + assert_equal(w3_name, "w3") + + w4_name = w4.getwalletinfo()['walletname'] + assert_equal(w4_name, "w") + + w1.generate(101) + assert_equal(w1.getbalance(), 100) + assert_equal(w2.getbalance(), 0) + assert_equal(w3.getbalance(), 0) + assert_equal(w4.getbalance(), 0) + + w1.sendtoaddress(w2.getnewaddress(), 1) + w1.sendtoaddress(w3.getnewaddress(), 2) + w1.sendtoaddress(w4.getnewaddress(), 3) + w1.generate(1) + assert_equal(w2.getbalance(), 1) + assert_equal(w3.getbalance(), 2) + assert_equal(w4.getbalance(), 3) + + batch = w1.batch([w1.getblockchaininfo.get_request(), w1.getwalletinfo.get_request()]) + assert_equal(batch[0]["result"]["chain"], "regtest") + assert_equal(batch[1]["result"]["walletname"], "w1") + +if __name__ == '__main__': + MultiWalletTest().main() diff --git a/test/functional/resendwallettransactions.py b/test/functional/wallet_resendwallettransactions.py index d959bb4c38..d959bb4c38 100755 --- a/test/functional/resendwallettransactions.py +++ b/test/functional/wallet_resendwallettransactions.py diff --git a/test/functional/txn_clone.py b/test/functional/wallet_txn_clone.py index 740bb2d4c5..ce26d6e0ee 100755 --- a/test/functional/txn_clone.py +++ b/test/functional/wallet_txn_clone.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2014-2016 The Bitcoin Core developers +# Copyright (c) 2014-2017 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test the wallet accounts properly when there are cloned transactions with malleated scriptsigs.""" @@ -14,6 +14,8 @@ class TxnMallTest(BitcoinTestFramework): def add_options(self, parser): parser.add_option("--mineblock", dest="mine_block", default=False, action="store_true", help="Test double-spend of 1-confirmed transaction") + parser.add_option("--segwit", dest="segwit", default=False, action="store_true", + help="Test behaviour with SegWit txn (which should fail") def setup_network(self): # Start with split network: @@ -22,6 +24,11 @@ class TxnMallTest(BitcoinTestFramework): disconnect_nodes(self.nodes[2], 1) def run_test(self): + if self.options.segwit: + output_type="p2sh-segwit" + else: + output_type="legacy" + # All nodes should start with 1,250 BTC: starting_balance = 1250 for i in range(4): @@ -31,11 +38,11 @@ class TxnMallTest(BitcoinTestFramework): # Assign coins to foo and bar accounts: self.nodes[0].settxfee(.001) - node0_address_foo = self.nodes[0].getnewaddress("foo") + node0_address_foo = self.nodes[0].getnewaddress("foo", output_type) fund_foo_txid = self.nodes[0].sendfrom("", node0_address_foo, 1219) fund_foo_tx = self.nodes[0].gettransaction(fund_foo_txid) - node0_address_bar = self.nodes[0].getnewaddress("bar") + node0_address_bar = self.nodes[0].getnewaddress("bar", output_type) fund_bar_txid = self.nodes[0].sendfrom("", node0_address_bar, 29) fund_bar_tx = self.nodes[0].gettransaction(fund_bar_txid) @@ -106,6 +113,10 @@ class TxnMallTest(BitcoinTestFramework): # Send clone and its parent to miner self.nodes[2].sendrawtransaction(fund_foo_tx["hex"]) txid1_clone = self.nodes[2].sendrawtransaction(tx1_clone["hex"]) + if self.options.segwit: + assert_equal(txid1, txid1_clone) + return + # ... mine a block... self.nodes[2].generate(1) diff --git a/test/functional/txn_doublespend.py b/test/functional/wallet_txn_doublespend.py index 69629ef951..01129f3817 100755 --- a/test/functional/txn_doublespend.py +++ b/test/functional/wallet_txn_doublespend.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2014-2016 The Bitcoin Core developers +# Copyright (c) 2014-2017 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test the wallet accounts properly when there is a double-spend conflict.""" diff --git a/test/functional/zapwallettxes.py b/test/functional/wallet_zapwallettxes.py index 8cd622dc8e..87f44b2737 100755 --- a/test/functional/zapwallettxes.py +++ b/test/functional/wallet_zapwallettxes.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2014-2016 The Bitcoin Core developers +# Copyright (c) 2014-2017 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test the zapwallettxes functionality. @@ -10,7 +10,7 @@ transactions are still available. - restart node 0 with zapwallettxes and persistmempool, and verify that both the confirmed and the unconfirmed transactions are still available. -- restart node 0 with just zapwallettxed and verify that the confirmed +- restart node 0 with just zapwallettxes and verify that the confirmed transactions are still available, but that the unconfirmed transaction has been zapped. """ @@ -59,6 +59,7 @@ class ZapWalletTXesTest (BitcoinTestFramework): self.start_node(0, ["-persistmempool=1", "-zapwallettxes=2"]) wait_until(lambda: self.nodes[0].getmempoolinfo()['size'] == 1, timeout=3) + self.nodes[0].syncwithvalidationinterfacequeue() # Flush mempool to wallet assert_equal(self.nodes[0].gettransaction(txid1)['txid'], txid1) assert_equal(self.nodes[0].gettransaction(txid2)['txid'], txid2) diff --git a/test/util/bitcoin-util-test.py b/test/util/bitcoin-util-test.py index ef34955d90..64e826ad0b 100755 --- a/test/util/bitcoin-util-test.py +++ b/test/util/bitcoin-util-test.py @@ -48,7 +48,7 @@ def main(): def bctester(testDir, input_basename, buildenv): """ Loads and parses the input file, runs all tests and reports results""" - input_filename = testDir + "/" + input_basename + input_filename = os.path.join(testDir, input_basename) raw_data = open(input_filename).read() input_data = json.loads(raw_data) @@ -77,7 +77,7 @@ def bctest(testDir, testObj, buildenv): are not as expected. Error is caught by bctester() and reported. """ # Get the exec names and arguments - execprog = buildenv["BUILDDIR"] + "/src/" + testObj['exec'] + buildenv["EXEEXT"] + execprog = os.path.join(buildenv["BUILDDIR"], "src", testObj["exec"] + buildenv["EXEEXT"]) execargs = testObj['args'] execrun = [execprog] + execargs @@ -85,24 +85,28 @@ def bctest(testDir, testObj, buildenv): stdinCfg = None inputData = None if "input" in testObj: - filename = testDir + "/" + testObj['input'] + filename = os.path.join(testDir, testObj["input"]) inputData = open(filename).read() stdinCfg = subprocess.PIPE # Read the expected output data (if there is any) outputFn = None outputData = None + outputType = None if "output_cmp" in testObj: outputFn = testObj['output_cmp'] outputType = os.path.splitext(outputFn)[1][1:] # output type from file extension (determines how to compare) try: - outputData = open(testDir + "/" + outputFn).read() + outputData = open(os.path.join(testDir, outputFn)).read() except: logging.error("Output file " + outputFn + " can not be opened") raise if not outputData: logging.error("Output data missing for " + outputFn) raise Exception + if not outputType: + logging.error("Output file %s does not have a file extension" % outputFn) + raise Exception # Run the test proc = subprocess.Popen(execrun, stdin=stdinCfg, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True) |