diff options
199 files changed, 997 insertions, 582 deletions
diff --git a/.appveyor.yml b/.appveyor.yml index 8dad9c4f9d..66958b75e7 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -61,5 +61,5 @@ test_script: - ps: src\bench_bitcoin.exe -evals=1 -scaling=0 - ps: python test\util\bitcoin-util-test.py - cmd: python test\util\rpcauth-test.py -- cmd: python test\functional\test_runner.py --force --quiet --combinedlogslen=4000 +- cmd: python test\functional\test_runner.py --ci --force --quiet --combinedlogslen=4000 deploy: off diff --git a/.travis.yml b/.travis.yml index 647d117733..6c300d70e3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -34,7 +34,7 @@ install: before_script: - set -o errexit; source .travis/test_05_before_script.sh script: - - set -o errexit; source .travis/test_06_script.sh + - if [ $SECONDS -gt 1200 ]; then set +o errexit; echo "Travis early exit to cache current state"; false; else set -o errexit; source .travis/test_06_script.sh; fi after_script: - echo $TRAVIS_COMMIT_RANGE - echo $TRAVIS_COMMIT_LOG @@ -57,8 +57,7 @@ jobs: - stage: test env: >- HOST=arm-linux-gnueabihf - PACKAGES="g++-arm-linux-gnueabihf" - DEP_OPTS="NO_QT=1" + PACKAGES="python3 g++-arm-linux-gnueabihf" RUN_UNIT_TESTS=false RUN_FUNCTIONAL_TESTS=false GOAL="install" @@ -70,24 +69,21 @@ jobs: env: >- HOST=i686-w64-mingw32 DPKG_ADD_ARCH="i386" - DEP_OPTS="NO_QT=1" PACKAGES="python3 nsis g++-mingw-w64-i686 wine-binfmt wine32" - GOAL="install" - BITCOIN_CONFIG="--enable-reduce-exports" + GOAL="deploy" + BITCOIN_CONFIG="--enable-reduce-exports --disable-gui-tests" # Win64 - stage: test env: >- HOST=x86_64-w64-mingw32 - DEP_OPTS="NO_QT=1" PACKAGES="python3 nsis g++-mingw-w64-x86-64 wine-binfmt wine64" - GOAL="install" - BITCOIN_CONFIG="--enable-reduce-exports" + GOAL="deploy" + BITCOIN_CONFIG="--enable-reduce-exports --disable-gui-tests" # 32-bit + dash - stage: test env: >- HOST=i686-pc-linux-gnu PACKAGES="g++-multilib python3-zmq" - DEP_OPTS="NO_QT=1" GOAL="install" BITCOIN_CONFIG="--enable-zmq --enable-glibc-back-compat --enable-reduce-exports LDFLAGS=-static-libstdc++" CONFIG_SHELL="/bin/dash" @@ -99,6 +95,15 @@ jobs: DEP_OPTS="NO_QT=1 NO_UPNP=1 DEBUG=1 ALLOW_HOST_PACKAGES=1" GOAL="install" BITCOIN_CONFIG="--enable-zmq --with-gui=qt5 --enable-glibc-back-compat --enable-reduce-exports --enable-debug CXXFLAGS=\"-g0 -O2\"" +# x86_64 Linux (xenial, no depends, only system libs) + - stage: test + env: >- + HOST=x86_64-unknown-linux-gnu + DOCKER_NAME_TAG=ubuntu:16.04 + PACKAGES="python3-zmq qtbase5-dev qttools5-dev-tools libssl-dev libevent-dev bsdmainutils libboost-system-dev libboost-filesystem-dev libboost-chrono-dev libboost-test-dev libboost-thread-dev libdb5.3++-dev libminiupnpc-dev libzmq3-dev libprotobuf-dev protobuf-compiler libqrencode-dev" + NO_DEPENDS=1 + GOAL="install" + BITCOIN_CONFIG="--enable-zmq --with-incompatible-bdb --enable-glibc-back-compat --enable-reduce-exports --with-gui=qt5 CPPFLAGS=-DDEBUG_LOCKORDER" # x86_64 Linux (no depends, only system libs) - stage: test env: >- @@ -133,5 +138,5 @@ jobs: OSX_SDK=10.11 RUN_UNIT_TESTS=false RUN_FUNCTIONAL_TESTS=false - GOAL="all deploy" + GOAL="deploy" BITCOIN_CONFIG="--enable-gui --enable-reduce-exports --enable-werror" diff --git a/.travis/test_06_script.sh b/.travis/test_06_script.sh index 59cc110db5..528d106aaf 100755 --- a/.travis/test_06_script.sh +++ b/.travis/test_06_script.sh @@ -62,6 +62,6 @@ fi if [ "$RUN_FUNCTIONAL_TESTS" = "true" ]; then BEGIN_FOLD functional-tests - DOCKER_EXEC test/functional/test_runner.py --combinedlogslen=4000 --coverage --quiet --failfast ${extended} + DOCKER_EXEC test/functional/test_runner.py --ci --combinedlogslen=4000 --coverage --quiet --failfast ${extended} END_FOLD fi diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3d5dc3221b..08b2fa609e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -67,6 +67,8 @@ If a particular commit references another issue, please add the reference. For example: `refs #1234` or `fixes #4321`. Using the `fixes` or `closes` keywords will cause the corresponding issue to be closed when the pull request is merged. +Commit messages should never contain any `@` mentions. + Please refer to the [Git manual](https://git-scm.com/doc) for more information about Git. @@ -135,6 +137,10 @@ before it will be merged. The basic squashing workflow is shown below. # Save and quit. git push -f # (force push to GitHub) +Please update the resulting commit message if needed, it should read as a +coherent message. In most cases this means that you should not just list the +interim commits. + If you have problems with squashing (or other workflows with `git`), you can alternatively enable "Allow edits from maintainers" in the right GitHub sidebar and ask for help in the pull request. diff --git a/build_msvc/libbitcoinconsensus/libbitcoinconsensus.vcxproj b/build_msvc/libbitcoinconsensus/libbitcoinconsensus.vcxproj index 0be7e7e430..2c6c0a8b7c 100644 --- a/build_msvc/libbitcoinconsensus/libbitcoinconsensus.vcxproj +++ b/build_msvc/libbitcoinconsensus/libbitcoinconsensus.vcxproj @@ -40,7 +40,7 @@ <ClCompile Include="..\..\src\script\script.cpp" /> <ClCompile Include="..\..\src\script\script_error.cpp" /> <ClCompile Include="..\..\src\uint256.cpp" /> - <ClCompile Include="..\..\src\utilstrencodings.cpp" /> + <ClCompile Include="..\..\src\util\strencodings.cpp" /> </ItemGroup> <ItemGroup> <None Include="packages.config" /> diff --git a/contrib/macdeploy/custom_dsstore.py b/contrib/macdeploy/custom_dsstore.py index 6fa134972a..c29f83a91e 100755 --- a/contrib/macdeploy/custom_dsstore.py +++ b/contrib/macdeploy/custom_dsstore.py @@ -13,7 +13,7 @@ package_name_ns = sys.argv[2] ds = DSStore.open(output_file, 'w+') ds['.']['bwsp'] = { 'ShowStatusBar': False, - 'WindowBounds': b'{{300, 280}, {500, 343}}', + 'WindowBounds': '{{300, 280}, {500, 343}}', 'ContainerShowSidebar': False, 'SidebarWidth': 0, 'ShowTabView': False, diff --git a/depends/builders/darwin.mk b/depends/builders/darwin.mk index 27f550ab03..c7671c1548 100644 --- a/depends/builders/darwin.mk +++ b/depends/builders/darwin.mk @@ -1,13 +1,13 @@ -build_darwin_CC: = $(shell xcrun -f clang) -build_darwin_CXX: = $(shell xcrun -f clang++) -build_darwin_AR: = $(shell xcrun -f ar) -build_darwin_RANLIB: = $(shell xcrun -f ranlib) -build_darwin_STRIP: = $(shell xcrun -f strip) -build_darwin_OTOOL: = $(shell xcrun -f otool) -build_darwin_NM: = $(shell xcrun -f nm) +build_darwin_CC:=$(shell xcrun -f clang) +build_darwin_CXX:=$(shell xcrun -f clang++) +build_darwin_AR:=$(shell xcrun -f ar) +build_darwin_RANLIB:=$(shell xcrun -f ranlib) +build_darwin_STRIP:=$(shell xcrun -f strip) +build_darwin_OTOOL:=$(shell xcrun -f otool) +build_darwin_NM:=$(shell xcrun -f nm) build_darwin_INSTALL_NAME_TOOL:=$(shell xcrun -f install_name_tool) -build_darwin_SHA256SUM = shasum -a 256 -build_darwin_DOWNLOAD = curl --location --fail --connect-timeout $(DOWNLOAD_CONNECT_TIMEOUT) --retry $(DOWNLOAD_RETRIES) -o +build_darwin_SHA256SUM=shasum -a 256 +build_darwin_DOWNLOAD=curl --location --fail --connect-timeout $(DOWNLOAD_CONNECT_TIMEOUT) --retry $(DOWNLOAD_RETRIES) -o #darwin host on darwin builder. overrides darwin host preferences. darwin_CC=$(shell xcrun -f clang) -mmacosx-version-min=$(OSX_MIN_VERSION) diff --git a/doc/JSON-RPC-interface.md b/doc/JSON-RPC-interface.md new file mode 100644 index 0000000000..59df541567 --- /dev/null +++ b/doc/JSON-RPC-interface.md @@ -0,0 +1,38 @@ +# JSON-RPC Interface + +The headless daemon `bitcoind` has the JSON-RPC API enabled by default, the GUI +`bitcoin-qt` has it disabled by default. This can be changed with the `-server` +option. In the GUI it is possible to execute RPC methods in the Debug Console +Dialog. + +## RPC consistency guarantees + +State that can be queried via RPCs is guaranteed to be at least up-to-date with +the chain state immediately prior to the call's execution. However, the state +returned by RPCs that reflect the mempool may not be up-to-date with the +current mempool state. + +### Transaction Pool + +The mempool state returned via an RPC is consistent with itself and with the +chain state at the time of the call. Thus, the mempool state only encompasses +transactions that are considered mine-able by the node at the time of the RPC. + +The mempool state returned via an RPC reflects all effects of mempool and chain +state related RPCs that returned prior to this call. + +### Wallet + +The wallet state returned via an RPC is consistent with itself and with the +chain state at the time of the call. + +Wallet RPCs will return the latest chain state consistent with prior non-wallet +RPCs. The effects of all blocks (and transactions in blocks) at the time of the +call is reflected in the state of all wallet transactions. For example, if a +block contains transactions that conflicted with mempool transactions, the +wallet would reflect the removal of these mempool transactions in the state. + +However, the wallet may not be up-to-date with the current state of the mempool +or the state of the mempool by an RPC that returned before this RPC. For +example, a wallet transaction that was BIP-125-replaced in the mempool prior to +this RPC may not yet be reflected as such in this RPC response. diff --git a/doc/README.md b/doc/README.md index acee6d0c80..344b1be5c4 100644 --- a/doc/README.md +++ b/doc/README.md @@ -56,6 +56,7 @@ The Bitcoin repo's [root README](/README.md) contains relevant information on th - [Translation Process](translation_process.md) - [Translation Strings Policy](translation_strings_policy.md) - [Travis CI](travis-ci.md) +- [JSON-RPC Interface](JSON-RPC-interface.md) - [Unauthenticated REST Interface](REST-interface.md) - [Shared Libraries](shared-libraries.md) - [BIPS](bips.md) diff --git a/doc/REST-interface.md b/doc/REST-interface.md index 7010edfcd3..44df698382 100644 --- a/doc/REST-interface.md +++ b/doc/REST-interface.md @@ -6,6 +6,12 @@ The REST API can be enabled with the `-rest` option. The interface runs on the same port as the JSON-RPC interface, by default port 8332 for mainnet, port 18332 for testnet, and port 18443 for regtest. +REST Interface consistency guarantees +------------------------------------- + +The [same guarantees as for the RPC Interface](/doc/JSON-RPC-interface.md#rpc-consistency-guarantees) +apply. + Supported API ------------- diff --git a/doc/build-freebsd.md b/doc/build-freebsd.md index 48746ce0c2..70f5dfc882 100644 --- a/doc/build-freebsd.md +++ b/doc/build-freebsd.md @@ -14,6 +14,12 @@ You will need the following dependencies, which can be installed as root via pkg pkg install autoconf automake boost-libs git gmake libevent libtool openssl pkgconf ``` +In order to run the test suite (recommended), you will need to have Python 3 installed: + +``` +pkg install python3 +``` + For the wallet (optional): ``` ./contrib/install_db4.sh `pwd` @@ -29,17 +35,29 @@ git clone https://github.com/bitcoin/bitcoin ## Building Bitcoin Core -**Important**: Use `gmake` (the non-GNU `make` will exit with an error). +**Important**: Use `gmake` (the non-GNU `make` will exit with an error): ``` ./autogen.sh ./configure # to build with wallet OR ./configure --disable-wallet # to build without wallet +``` + +followed by either: +``` gmake ``` +to build without testing, or + +``` +gmake check +``` + +to also run the test suite (recommended, if Python 3 is installed). + *Note on debugging*: The version of `gdb` installed by default is [ancient and considered harmful](https://wiki.freebsd.org/GdbRetirement). It is not suitable for debugging a multi-threaded C++ program, not even for getting backtraces. Please install the package `gdb` and use the versioned gdb command (e.g. `gdb7111`). diff --git a/doc/build-openbsd.md b/doc/build-openbsd.md index 63288acf16..48ac0525b9 100644 --- a/doc/build-openbsd.md +++ b/doc/build-openbsd.md @@ -36,7 +36,7 @@ BerkeleyDB is only necessary for the wallet functionality. To skip this, pass 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=cc CXX=c++ @@ -94,7 +94,7 @@ 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, +This is, 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: diff --git a/doc/build-osx.md b/doc/build-osx.md index 1fa01d0d6e..7be21f7921 100644 --- a/doc/build-osx.md +++ b/doc/build-osx.md @@ -20,7 +20,7 @@ Dependencies See [dependencies.md](dependencies.md) for a complete overview. -If you want to build the disk image with `make deploy` (.dmg / optional), you need RSVG +If you want to build the disk image with `make deploy` (.dmg / optional), you need RSVG: brew install librsvg @@ -28,7 +28,7 @@ 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) -like so +like so: ```shell ./contrib/install_db4.sh . @@ -36,12 +36,12 @@ like so from the root of the repository. -**Note**: You only need Berkeley DB if the wallet is enabled (see the section *Disable-Wallet mode* below). +**Note**: You only need Berkeley DB if the wallet is enabled (see [*Disable-wallet mode*](/doc/build-osx.md#disable-wallet-mode)). Build Bitcoin Core ------------------------ -1. Clone the Bitcoin Core source code and cd into `bitcoin` +1. Clone the Bitcoin Core source code: git clone https://github.com/bitcoin/bitcoin cd bitcoin @@ -80,13 +80,13 @@ Running Bitcoin Core is now available at `./src/bitcoind` -Before running, it's recommended that you create an RPC configuration file. +Before running, it's recommended that you create an RPC configuration file: echo -e "rpcuser=bitcoinrpc\nrpcpassword=$(xxd -l 16 -p /dev/urandom)" > "/Users/${USER}/Library/Application Support/Bitcoin/bitcoin.conf" chmod 600 "/Users/${USER}/Library/Application Support/Bitcoin/bitcoin.conf" -The first time you run bitcoind, it will start downloading the blockchain. This process could take several hours. +The first time you run bitcoind, it will start downloading the blockchain. This process could take many hours, or even days on slower than average systems. You can monitor the download process by looking at the debug.log file: diff --git a/doc/build-unix.md b/doc/build-unix.md index 87dade42a3..522e3069ce 100644 --- a/doc/build-unix.md +++ b/doc/build-unix.md @@ -6,8 +6,8 @@ Some notes on how to build Bitcoin Core in Unix. Note --------------------- -Always use absolute paths to configure and compile Bitcoin Core and the dependencies, -for example, when specifying the path of the dependency: +Always use absolute paths to configure and compile Bitcoin Core and the dependencies. +For example, when specifying the path of the dependency: ../dist/configure --enable-cxx --disable-shared --with-pic --prefix=$BDB_PREFIX @@ -24,7 +24,7 @@ make make install # optional ``` -This will build bitcoin-qt as well if the dependencies are met. +This will build bitcoin-qt as well, if the dependencies are met. Dependencies --------------------- @@ -87,11 +87,12 @@ You can add the repository and install using the following commands: sudo apt-get install libdb4.8-dev libdb4.8++-dev Ubuntu and Debian have their own libdb-dev and libdb++-dev packages, but these will install -BerkeleyDB 5.1 or later, which break binary wallet compatibility with the distributed executables which +BerkeleyDB 5.1 or later. This will break binary wallet compatibility with the distributed executables, which are based on BerkeleyDB 4.8. If you do not care about wallet compatibility, pass `--with-incompatible-bdb` to configure. -See the section "Disable-wallet mode" to build Bitcoin Core without wallet. +To build Bitcoin Core without wallet, see [*Disable-wallet mode*](/doc/build-unix.md#disable-wallet-mode) + Optional (see --with-miniupnpc and --enable-upnp-default): @@ -161,7 +162,7 @@ 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) -like so +like so: ```shell ./contrib/install_db4.sh `pwd` @@ -169,7 +170,7 @@ like so from the root of the repository. -**Note**: You only need Berkeley DB if the wallet is enabled (see the section *Disable-Wallet mode* below). +**Note**: You only need Berkeley DB if the wallet is enabled (see [*Disable-wallet mode*](/doc/build-unix.md#disable-wallet-mode)). Boost ----- @@ -193,9 +194,7 @@ Hardening Flags: Hardening enables the following features: - -* Position Independent Executable - Build position independent code to take advantage of Address Space Layout Randomization +* _Position Independent Executable_: Build position independent code to take advantage of Address Space Layout Randomization offered by some kernels. Attackers who can cause execution of code at an arbitrary memory location are thwarted if they don't know where anything useful is located. The stack and heap are randomly located by default, but this allows the code section to be @@ -213,8 +212,7 @@ Hardening enables the following features: TYPE ET_DYN -* Non-executable Stack - If the stack is executable then trivial stack-based buffer overflow exploits are possible if +* _Non-executable Stack_: If the stack is executable then trivial stack-based buffer overflow exploits are possible if vulnerable buffers are found. By default, Bitcoin Core should be built with a non-executable stack, but if one of the libraries it uses asks for an executable stack or someone makes a mistake and uses a compiler extension which requires an executable stack, it will silently build an diff --git a/doc/build-windows.md b/doc/build-windows.md index 8c4b79bebc..fc93a0c6e4 100644 --- a/doc/build-windows.md +++ b/doc/build-windows.md @@ -5,15 +5,15 @@ Below are some notes on how to build Bitcoin Core for Windows. The options known to work for building Bitcoin Core on Windows are: -* On Linux using the [Mingw-w64](https://mingw-w64.org/doku.php) cross compiler tool chain. Ubuntu Bionic 18.04 is required +* On Linux, using the [Mingw-w64](https://mingw-w64.org/doku.php) cross compiler tool chain. Ubuntu Bionic 18.04 is required and is the platform used to build the Bitcoin Core Windows release binaries. -* On Windows using [Windows +* On Windows, using [Windows Subsystem for Linux (WSL)](https://msdn.microsoft.com/commandline/wsl/about) and the Mingw-w64 cross compiler tool chain. Other options which may work, but which have not been extensively tested are (please contribute instructions): -* On Windows using a POSIX compatibility layer application such as [cygwin](http://www.cygwin.com/) or [msys2](http://www.msys2.org/). -* On Windows using a native compiler tool chain such as [Visual Studio](https://www.visualstudio.com). +* On Windows, using a POSIX compatibility layer application such as [cygwin](http://www.cygwin.com/) or [msys2](http://www.msys2.org/). +* On Windows, using a native compiler tool chain such as [Visual Studio](https://www.visualstudio.com). Installing Windows Subsystem for Linux --------------------------------------- @@ -69,7 +69,7 @@ See also: [dependencies.md](dependencies.md). ## Building for 64-bit Windows -The first step is to install the mingw-w64 cross-compilation tool chain. +The first step is to install the mingw-w64 cross-compilation tool chain: sudo apt install g++-mingw-w64-x86-64 @@ -81,13 +81,13 @@ Once the toolchain is installed the build steps are common: Note that for WSL the Bitcoin Core source path MUST be somewhere in the default mount file system, for example /usr/src/bitcoin, AND not under /mnt/d/. If this is not the case the dependency autoconf scripts will fail. -This means you cannot use a directory that located directly on the host Windows file system to perform the build. +This means you cannot use a directory that is located directly on the host Windows file system to perform the build. Acquire the source in the usual way: git clone https://github.com/bitcoin/bitcoin.git -Once the source code is ready the build steps are below. +Once the source code is ready the build steps are below: PATH=$(echo "$PATH" | sed -e 's/:\/mnt.*//g') # strip out problematic Windows %PATH% imported var cd depends @@ -142,9 +142,9 @@ way. This will install to `c:\workspace\bitcoin`, for example: Footnotes --------- -<a name="footnote1">1</a>: Starting from Ubuntu Xenial 16.04 both the 32 and 64 bit Mingw-w64 packages install two different +<a name="footnote1">1</a>: Starting from Ubuntu Xenial 16.04, both the 32 and 64 bit Mingw-w64 packages install two different compiler options to allow a choice between either posix or win32 threads. The default option is win32 threads which is the more efficient since it will result in binary code that links directly with the Windows kernel32.lib. Unfortunately, the headers -required to support win32 threads conflict with some of the classes in the C++11 standard library in particular std::mutex. +required to support win32 threads conflict with some of the classes in the C++11 standard library, in particular std::mutex. It's not possible to build the Bitcoin Core code using the win32 version of the Mingw-w64 cross compilers (at least not without modifying headers in the Bitcoin Core source code). diff --git a/doc/developer-notes.md b/doc/developer-notes.md index c86648c5b8..fd5cc78297 100644 --- a/doc/developer-notes.md +++ b/doc/developer-notes.md @@ -69,7 +69,7 @@ tool to clean up patches automatically before submission. - **Symbol naming conventions**. These are preferred in new code, but are not required when doing so would need changes to significant pieces of existing code. - - Variable and namespace names are all lowercase, and may use `_` to + - Variable (including function arguments) and namespace names are all lowercase, and may use `_` to separate words (snake_case). - Class member variables have a `m_` prefix. - Global variables have a `g_` prefix. diff --git a/doc/release-notes-14282.md b/doc/release-notes-14282.md index e6d8e0b70c..900ca04324 100644 --- a/doc/release-notes-14282.md +++ b/doc/release-notes-14282.md @@ -4,3 +4,6 @@ Low-level RPC changes `-usehd` was removed in version 0.16. From that version onwards, all new wallets created are hierarchical deterministic wallets. Version 0.18 makes specifying `-usehd` invalid config. + +`ischange` field of boolean type that shows if an address was used for change +output was added to `getaddressinfo` method response. diff --git a/doc/release-notes-14454.md b/doc/release-notes-14454.md new file mode 100644 index 0000000000..dd2c6c7ced --- /dev/null +++ b/doc/release-notes-14454.md @@ -0,0 +1,6 @@ +Low-level RPC changes +---------------------- + +The `importmulti` RPC has been updated to support P2WSH, P2WPKH, P2SH-P2WPKH, +P2SH-P2WSH. Each request now accepts an additional `witnessscript` to be used +for P2WSH or P2SH-P2WSH. diff --git a/share/qt/Info.plist.in b/share/qt/Info.plist.in index 17b4ee47de..0c0335a1e8 100644 --- a/share/qt/Info.plist.in +++ b/share/qt/Info.plist.in @@ -99,6 +99,9 @@ <key>LSAppNapIsDisabled</key> <string>True</string> + + <key>NSRequiresAquaSystemAppearance</key> + <string>True</string> <key>LSApplicationCategoryType</key> <string>public.app-category.finance</string> diff --git a/src/Makefile.am b/src/Makefile.am index 6141919007..703304cebd 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -183,10 +183,10 @@ BITCOIN_CORE_H = \ txmempool.h \ ui_interface.h \ undo.h \ - util.h \ - utilmemory.h \ - utilmoneystr.h \ - utiltime.h \ + util/system.h \ + util/memory.h \ + util/moneystr.h \ + util/time.h \ validation.h \ validationinterface.h \ versionbits.h \ @@ -377,8 +377,8 @@ libbitcoin_consensus_a_SOURCES = \ tinyformat.h \ uint256.cpp \ uint256.h \ - utilstrencodings.cpp \ - utilstrencodings.h \ + util/strencodings.cpp \ + util/strencodings.h \ version.h # common: shared between bitcoind, and bitcoin-qt and non-server tools @@ -427,10 +427,10 @@ libbitcoin_util_a_SOURCES = \ support/cleanse.cpp \ sync.cpp \ threadinterrupt.cpp \ - util.cpp \ - utilmoneystr.cpp \ - utilstrencodings.cpp \ - utiltime.cpp \ + util/system.cpp \ + util/moneystr.cpp \ + util/strencodings.cpp \ + util/time.cpp \ $(BITCOIN_CORE_H) if GLIBC_BACK_COMPAT diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include index 8d25e83529..3ca2a7451d 100644 --- a/src/Makefile.qt.include +++ b/src/Makefile.qt.include @@ -416,12 +416,13 @@ endif if ENABLE_ZMQ qt_bitcoin_qt_LDADD += $(LIBBITCOIN_ZMQ) $(ZMQ_LIBS) endif +qt_bitcoin_qt_LDADD += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CONSENSUS) $(LIBBITCOIN_CRYPTO) $(LIBUNIVALUE) $(LIBLEVELDB) $(LIBLEVELDB_SSE42) $(LIBMEMENV) \ + $(BOOST_LIBS) $(QT_LIBS) $(QT_DBUS_LIBS) $(QR_LIBS) $(PROTOBUF_LIBS) $(BDB_LIBS) $(MINIUPNPC_LIBS) $(LIBSECP256K1) \ + $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) if ENABLE_BIP70 qt_bitcoin_qt_LDADD += $(SSL_LIBS) endif -qt_bitcoin_qt_LDADD += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CONSENSUS) $(LIBBITCOIN_CRYPTO) $(LIBUNIVALUE) $(LIBLEVELDB) $(LIBLEVELDB_SSE42) $(LIBMEMENV) \ - $(BOOST_LIBS) $(QT_LIBS) $(QT_DBUS_LIBS) $(QR_LIBS) $(PROTOBUF_LIBS) $(BDB_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) $(LIBSECP256K1) \ - $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) +qt_bitcoin_qt_LDADD += $(CRYPTO_LIBS) qt_bitcoin_qt_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(QT_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) qt_bitcoin_qt_LIBTOOLFLAGS = $(AM_LIBTOOLFLAGS) --tag CXX diff --git a/src/addrdb.cpp b/src/addrdb.cpp index 3eae2b5127..1590bce074 100644 --- a/src/addrdb.cpp +++ b/src/addrdb.cpp @@ -12,7 +12,7 @@ #include <random.h> #include <streams.h> #include <tinyformat.h> -#include <util.h> +#include <util/system.h> namespace { diff --git a/src/addrman.h b/src/addrman.h index 6d5780afa8..b97feb6f08 100644 --- a/src/addrman.h +++ b/src/addrman.h @@ -11,7 +11,7 @@ #include <random.h> #include <sync.h> #include <timedata.h> -#include <util.h> +#include <util/system.h> #include <map> #include <set> diff --git a/src/arith_uint256.cpp b/src/arith_uint256.cpp index 791dad7a60..aa66d13102 100644 --- a/src/arith_uint256.cpp +++ b/src/arith_uint256.cpp @@ -6,7 +6,7 @@ #include <arith_uint256.h> #include <uint256.h> -#include <utilstrencodings.h> +#include <util/strencodings.h> #include <crypto/common.h> #include <stdio.h> diff --git a/src/base58.cpp b/src/base58.cpp index 7020c24055..e3d2853399 100644 --- a/src/base58.cpp +++ b/src/base58.cpp @@ -6,6 +6,7 @@ #include <hash.h> #include <uint256.h> +#include <util/strencodings.h> #include <assert.h> #include <string.h> @@ -34,7 +35,7 @@ static const int8_t mapBase58[256] = { bool DecodeBase58(const char* psz, std::vector<unsigned char>& vch) { // Skip leading spaces. - while (*psz && isspace(*psz)) + while (*psz && IsSpace(*psz)) psz++; // Skip and count leading '1's. int zeroes = 0; @@ -48,7 +49,7 @@ bool DecodeBase58(const char* psz, std::vector<unsigned char>& vch) std::vector<unsigned char> b256(size); // Process the characters. static_assert(sizeof(mapBase58)/sizeof(mapBase58[0]) == 256, "mapBase58.size() should be 256"); // guarantee not out of range - while (*psz && !isspace(*psz)) { + while (*psz && !IsSpace(*psz)) { // Decode base58 character int carry = mapBase58[(uint8_t)*psz]; if (carry == -1) // Invalid b58 character @@ -64,7 +65,7 @@ bool DecodeBase58(const char* psz, std::vector<unsigned char>& vch) psz++; } // Skip trailing spaces. - while (isspace(*psz)) + while (IsSpace(*psz)) psz++; if (*psz != 0) return false; diff --git a/src/bench/bech32.cpp b/src/bench/bech32.cpp index 8b80e17391..3c4b453a23 100644 --- a/src/bench/bech32.cpp +++ b/src/bench/bech32.cpp @@ -6,7 +6,7 @@ #include <validation.h> #include <bech32.h> -#include <utilstrencodings.h> +#include <util/strencodings.h> #include <vector> #include <string> diff --git a/src/bench/bench_bitcoin.cpp b/src/bench/bench_bitcoin.cpp index 4fa516cb81..32faba86b4 100644 --- a/src/bench/bench_bitcoin.cpp +++ b/src/bench/bench_bitcoin.cpp @@ -7,8 +7,8 @@ #include <crypto/sha256.h> #include <key.h> #include <random.h> -#include <util.h> -#include <utilstrencodings.h> +#include <util/system.h> +#include <util/strencodings.h> #include <validation.h> #include <memory> diff --git a/src/bench/block_assemble.cpp b/src/bench/block_assemble.cpp index bc99b8cdcd..ac2299374c 100644 --- a/src/bench/block_assemble.cpp +++ b/src/bench/block_assemble.cpp @@ -13,7 +13,7 @@ #include <scheduler.h> #include <txdb.h> #include <txmempool.h> -#include <utiltime.h> +#include <util/time.h> #include <validation.h> #include <validationinterface.h> diff --git a/src/bench/checkqueue.cpp b/src/bench/checkqueue.cpp index 79689f6e0b..6ab542067a 100644 --- a/src/bench/checkqueue.cpp +++ b/src/bench/checkqueue.cpp @@ -3,7 +3,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <bench/bench.h> -#include <util.h> +#include <util/system.h> #include <validation.h> #include <checkqueue.h> #include <prevector.h> diff --git a/src/bench/crypto_hash.cpp b/src/bench/crypto_hash.cpp index 5b0cf27e04..d7499a3767 100644 --- a/src/bench/crypto_hash.cpp +++ b/src/bench/crypto_hash.cpp @@ -9,7 +9,7 @@ #include <hash.h> #include <random.h> #include <uint256.h> -#include <utiltime.h> +#include <util/time.h> #include <crypto/ripemd160.h> #include <crypto/sha1.h> #include <crypto/sha256.h> diff --git a/src/bench/examples.cpp b/src/bench/examples.cpp index 6d95e05ef6..e7ddd5a938 100644 --- a/src/bench/examples.cpp +++ b/src/bench/examples.cpp @@ -4,7 +4,7 @@ #include <bench/bench.h> #include <validation.h> -#include <utiltime.h> +#include <util/time.h> // Sanity test: this should loop ten times, and // min/max/average should be close to 100ms. diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp index f466505114..dc1b46faf1 100644 --- a/src/bitcoin-cli.cpp +++ b/src/bitcoin-cli.cpp @@ -12,8 +12,8 @@ #include <fs.h> #include <rpc/client.h> #include <rpc/protocol.h> -#include <util.h> -#include <utilstrencodings.h> +#include <util/system.h> +#include <util/strencodings.h> #include <memory> #include <stdio.h> diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp index 6d86581ac6..bdc064b9fb 100644 --- a/src/bitcoin-tx.cpp +++ b/src/bitcoin-tx.cpp @@ -18,9 +18,9 @@ #include <script/script.h> #include <script/sign.h> #include <univalue.h> -#include <util.h> -#include <utilmoneystr.h> -#include <utilstrencodings.h> +#include <util/system.h> +#include <util/moneystr.h> +#include <util/strencodings.h> #include <memory> #include <stdio.h> diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp index 18fcd9bc2a..c6e2a7c20a 100644 --- a/src/bitcoind.cpp +++ b/src/bitcoind.cpp @@ -15,10 +15,10 @@ #include <init.h> #include <noui.h> #include <shutdown.h> -#include <util.h> +#include <util/system.h> #include <httpserver.h> #include <httprpc.h> -#include <utilstrencodings.h> +#include <util/strencodings.h> #include <walletinitinterface.h> #include <stdio.h> diff --git a/src/blockencodings.cpp b/src/blockencodings.cpp index 4c57965bec..a06bced11b 100644 --- a/src/blockencodings.cpp +++ b/src/blockencodings.cpp @@ -11,7 +11,7 @@ #include <streams.h> #include <txmempool.h> #include <validation.h> -#include <util.h> +#include <util/system.h> #include <unordered_map> diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 0574e2395e..4ce1b53880 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -8,8 +8,8 @@ #include <chainparamsseeds.h> #include <consensus/merkle.h> #include <tinyformat.h> -#include <util.h> -#include <utilstrencodings.h> +#include <util/system.h> +#include <util/strencodings.h> #include <versionbitsinfo.h> #include <assert.h> diff --git a/src/chainparamsbase.cpp b/src/chainparamsbase.cpp index 870640e77d..f0559a319a 100644 --- a/src/chainparamsbase.cpp +++ b/src/chainparamsbase.cpp @@ -6,8 +6,8 @@ #include <chainparamsbase.h> #include <tinyformat.h> -#include <util.h> -#include <utilmemory.h> +#include <util/system.h> +#include <util/memory.h> #include <assert.h> diff --git a/src/consensus/merkle.cpp b/src/consensus/merkle.cpp index 2a87a936b1..b47d9774ca 100644 --- a/src/consensus/merkle.cpp +++ b/src/consensus/merkle.cpp @@ -4,7 +4,7 @@ #include <consensus/merkle.h> #include <hash.h> -#include <utilstrencodings.h> +#include <util/strencodings.h> /* WARNING! If you're reading this because you're learning about crypto and/or designing a new system that will use merkle trees, keep in mind diff --git a/src/consensus/tx_verify.cpp b/src/consensus/tx_verify.cpp index 0628ec1d47..b17a8bb31d 100644 --- a/src/consensus/tx_verify.cpp +++ b/src/consensus/tx_verify.cpp @@ -12,7 +12,7 @@ // TODO remove the following dependencies #include <chain.h> #include <coins.h> -#include <utilmoneystr.h> +#include <util/moneystr.h> bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64_t nBlockTime) { diff --git a/src/core_read.cpp b/src/core_read.cpp index 301f99bc1c..3b82b2853c 100644 --- a/src/core_read.cpp +++ b/src/core_read.cpp @@ -11,8 +11,8 @@ #include <serialize.h> #include <streams.h> #include <univalue.h> -#include <util.h> -#include <utilstrencodings.h> +#include <util/system.h> +#include <util/strencodings.h> #include <version.h> #include <boost/algorithm/string/classification.hpp> diff --git a/src/core_write.cpp b/src/core_write.cpp index b86490716f..765a170307 100644 --- a/src/core_write.cpp +++ b/src/core_write.cpp @@ -12,9 +12,9 @@ #include <serialize.h> #include <streams.h> #include <univalue.h> -#include <util.h> -#include <utilmoneystr.h> -#include <utilstrencodings.h> +#include <util/system.h> +#include <util/moneystr.h> +#include <util/strencodings.h> UniValue ValueFromAmount(const CAmount& amount) { diff --git a/src/dbwrapper.h b/src/dbwrapper.h index 52f9efe17c..416f5e8399 100644 --- a/src/dbwrapper.h +++ b/src/dbwrapper.h @@ -9,8 +9,8 @@ #include <fs.h> #include <serialize.h> #include <streams.h> -#include <util.h> -#include <utilstrencodings.h> +#include <util/system.h> +#include <util/strencodings.h> #include <version.h> #include <leveldb/db.h> diff --git a/src/dummywallet.cpp b/src/dummywallet.cpp index 3eb77354c1..2a9b297029 100644 --- a/src/dummywallet.cpp +++ b/src/dummywallet.cpp @@ -3,7 +3,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <stdio.h> -#include <util.h> +#include <util/system.h> #include <walletinitinterface.h> class CWallet; diff --git a/src/httprpc.cpp b/src/httprpc.cpp index 4064251c71..fcf760a4c6 100644 --- a/src/httprpc.cpp +++ b/src/httprpc.cpp @@ -11,8 +11,8 @@ #include <rpc/server.h> #include <random.h> #include <sync.h> -#include <util.h> -#include <utilstrencodings.h> +#include <util/system.h> +#include <util/strencodings.h> #include <ui_interface.h> #include <walletinitinterface.h> #include <crypto/hmac_sha256.h> diff --git a/src/httpserver.cpp b/src/httpserver.cpp index c29f7a4375..dcb9e0ccd2 100644 --- a/src/httpserver.cpp +++ b/src/httpserver.cpp @@ -6,8 +6,8 @@ #include <chainparamsbase.h> #include <compat.h> -#include <util.h> -#include <utilstrencodings.h> +#include <util/system.h> +#include <util/strencodings.h> #include <netbase.h> #include <rpc/protocol.h> // For HTTP status codes #include <sync.h> diff --git a/src/index/base.cpp b/src/index/base.cpp index 42c6b0373d..4d4a7e1502 100644 --- a/src/index/base.cpp +++ b/src/index/base.cpp @@ -7,7 +7,7 @@ #include <shutdown.h> #include <tinyformat.h> #include <ui_interface.h> -#include <util.h> +#include <util/system.h> #include <validation.h> #include <warnings.h> diff --git a/src/index/txindex.cpp b/src/index/txindex.cpp index f606c8993c..ba1c44765f 100644 --- a/src/index/txindex.cpp +++ b/src/index/txindex.cpp @@ -5,7 +5,7 @@ #include <index/txindex.h> #include <shutdown.h> #include <ui_interface.h> -#include <util.h> +#include <util/system.h> #include <validation.h> #include <boost/thread.hpp> diff --git a/src/init.cpp b/src/init.cpp index f9efaf7dc1..90dfeb3604 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -41,8 +41,8 @@ #include <txmempool.h> #include <torcontrol.h> #include <ui_interface.h> -#include <util.h> -#include <utilmoneystr.h> +#include <util/system.h> +#include <util/moneystr.h> #include <validationinterface.h> #include <warnings.h> #include <walletinitinterface.h> diff --git a/src/init.h b/src/init.h index c58ba5cfd3..b106353d08 100644 --- a/src/init.h +++ b/src/init.h @@ -8,7 +8,7 @@ #include <memory> #include <string> -#include <util.h> +#include <util/system.h> class CScheduler; class CWallet; diff --git a/src/interfaces/handler.cpp b/src/interfaces/handler.cpp index ddf9b342d8..92601fc4e9 100644 --- a/src/interfaces/handler.cpp +++ b/src/interfaces/handler.cpp @@ -4,7 +4,7 @@ #include <interfaces/handler.h> -#include <utilmemory.h> +#include <util/memory.h> #include <boost/signals2/connection.hpp> #include <utility> diff --git a/src/interfaces/node.cpp b/src/interfaces/node.cpp index 2b19e11f08..490c456e6e 100644 --- a/src/interfaces/node.cpp +++ b/src/interfaces/node.cpp @@ -25,7 +25,7 @@ #include <sync.h> #include <txmempool.h> #include <ui_interface.h> -#include <util.h> +#include <util/system.h> #include <validation.h> #include <warnings.h> diff --git a/src/interfaces/wallet.cpp b/src/interfaces/wallet.cpp index 84079fdc3c..14c6bd0330 100644 --- a/src/interfaces/wallet.cpp +++ b/src/interfaces/wallet.cpp @@ -290,8 +290,7 @@ public: } bool tryGetTxStatus(const uint256& txid, interfaces::WalletTxStatus& tx_status, - int& num_blocks, - int64_t& adjusted_time) override + int& num_blocks) override { TRY_LOCK(::cs_main, locked_chain); if (!locked_chain) { @@ -306,7 +305,6 @@ public: return false; } num_blocks = ::chainActive.Height(); - adjusted_time = GetAdjustedTime(); tx_status = MakeWalletTxStatus(mi->second); return true; } @@ -314,14 +312,12 @@ public: WalletTxStatus& tx_status, WalletOrderForm& order_form, bool& in_mempool, - int& num_blocks, - int64_t& adjusted_time) override + int& num_blocks) override { LOCK2(::cs_main, m_wallet.cs_wallet); auto mi = m_wallet.mapWallet.find(txid); if (mi != m_wallet.mapWallet.end()) { num_blocks = ::chainActive.Height(); - adjusted_time = GetAdjustedTime(); in_mempool = mi->second.InMempool(); order_form = mi->second.vOrderForm; tx_status = MakeWalletTxStatus(mi->second); diff --git a/src/interfaces/wallet.h b/src/interfaces/wallet.h index 7aa91f37e1..c79b9afce3 100644 --- a/src/interfaces/wallet.h +++ b/src/interfaces/wallet.h @@ -178,16 +178,14 @@ public: //! Try to get updated status for a particular transaction, if possible without blocking. virtual bool tryGetTxStatus(const uint256& txid, WalletTxStatus& tx_status, - int& num_blocks, - int64_t& adjusted_time) = 0; + int& num_blocks) = 0; //! Get transaction details. virtual WalletTx getWalletTxDetails(const uint256& txid, WalletTxStatus& tx_status, WalletOrderForm& order_form, bool& in_mempool, - int& num_blocks, - int64_t& adjusted_time) = 0; + int& num_blocks) = 0; //! Get balances. virtual WalletBalances getBalances() = 0; diff --git a/src/key_io.cpp b/src/key_io.cpp index c6a541cdb1..282385f50d 100644 --- a/src/key_io.cpp +++ b/src/key_io.cpp @@ -7,7 +7,7 @@ #include <base58.h> #include <bech32.h> #include <script/script.h> -#include <utilstrencodings.h> +#include <util/strencodings.h> #include <boost/variant/apply_visitor.hpp> #include <boost/variant/static_visitor.hpp> diff --git a/src/keystore.cpp b/src/keystore.cpp index b2012a04bb..148979cf35 100644 --- a/src/keystore.cpp +++ b/src/keystore.cpp @@ -5,7 +5,7 @@ #include <keystore.h> -#include <util.h> +#include <util/system.h> void CBasicKeyStore::ImplicitlyLearnRelatedKeyScripts(const CPubKey& pubkey) { diff --git a/src/logging.cpp b/src/logging.cpp index 0ae4f8121e..77dc2d0939 100644 --- a/src/logging.cpp +++ b/src/logging.cpp @@ -4,7 +4,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <logging.h> -#include <utiltime.h> +#include <util/time.h> const char * const DEFAULT_DEBUGLOGFILE = "debug.log"; diff --git a/src/merkleblock.cpp b/src/merkleblock.cpp index 7bbc45d38a..0c37bab1f8 100644 --- a/src/merkleblock.cpp +++ b/src/merkleblock.cpp @@ -7,7 +7,7 @@ #include <hash.h> #include <consensus/consensus.h> -#include <utilstrencodings.h> +#include <util/strencodings.h> CMerkleBlock::CMerkleBlock(const CBlock& block, CBloomFilter* filter, const std::set<uint256>* txids) diff --git a/src/miner.cpp b/src/miner.cpp index 6d35f9ac37..feb86cab66 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -21,8 +21,8 @@ #include <primitives/transaction.h> #include <script/standard.h> #include <timedata.h> -#include <util.h> -#include <utilmoneystr.h> +#include <util/system.h> +#include <util/moneystr.h> #include <validationinterface.h> #include <algorithm> diff --git a/src/net.cpp b/src/net.cpp index c8d3efceed..65a308780a 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -18,7 +18,7 @@ #include <netbase.h> #include <scheduler.h> #include <ui_interface.h> -#include <utilstrencodings.h> +#include <util/strencodings.h> #ifdef WIN32 #include <string.h> diff --git a/src/net_processing.cpp b/src/net_processing.cpp index a1b6e021ae..f37312d155 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -25,9 +25,9 @@ #include <tinyformat.h> #include <txmempool.h> #include <ui_interface.h> -#include <util.h> -#include <utilmoneystr.h> -#include <utilstrencodings.h> +#include <util/system.h> +#include <util/moneystr.h> +#include <util/strencodings.h> #include <memory> diff --git a/src/netaddress.cpp b/src/netaddress.cpp index 778c2700f9..e1af4eff62 100644 --- a/src/netaddress.cpp +++ b/src/netaddress.cpp @@ -5,7 +5,7 @@ #include <netaddress.h> #include <hash.h> -#include <utilstrencodings.h> +#include <util/strencodings.h> #include <tinyformat.h> static const unsigned char pchIPv4[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff }; diff --git a/src/netbase.cpp b/src/netbase.cpp index 04d5eb12c8..6a750d5141 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -10,8 +10,8 @@ #include <uint256.h> #include <random.h> #include <tinyformat.h> -#include <util.h> -#include <utilstrencodings.h> +#include <util/system.h> +#include <util/strencodings.h> #include <atomic> diff --git a/src/noui.cpp b/src/noui.cpp index df4bfabb66..c7d8fee0ba 100644 --- a/src/noui.cpp +++ b/src/noui.cpp @@ -6,7 +6,7 @@ #include <noui.h> #include <ui_interface.h> -#include <util.h> +#include <util/system.h> #include <cstdio> #include <stdint.h> diff --git a/src/policy/fees.cpp b/src/policy/fees.cpp index aee6fbee1a..3afe6fe1b7 100644 --- a/src/policy/fees.cpp +++ b/src/policy/fees.cpp @@ -10,7 +10,7 @@ #include <primitives/transaction.h> #include <streams.h> #include <txmempool.h> -#include <util.h> +#include <util/system.h> static constexpr double INF_FEERATE = 1e99; diff --git a/src/policy/policy.cpp b/src/policy/policy.cpp index ac1b75edb4..d4cc538492 100644 --- a/src/policy/policy.cpp +++ b/src/policy/policy.cpp @@ -11,8 +11,8 @@ #include <validation.h> #include <coins.h> #include <tinyformat.h> -#include <util.h> -#include <utilstrencodings.h> +#include <util/system.h> +#include <util/strencodings.h> CAmount GetDustThreshold(const CTxOut& txout, const CFeeRate& dustRelayFeeIn) diff --git a/src/primitives/block.cpp b/src/primitives/block.cpp index fb95a66bde..a0c2e3f125 100644 --- a/src/primitives/block.cpp +++ b/src/primitives/block.cpp @@ -7,7 +7,7 @@ #include <hash.h> #include <tinyformat.h> -#include <utilstrencodings.h> +#include <util/strencodings.h> #include <crypto/common.h> uint256 CBlockHeader::GetHash() const diff --git a/src/primitives/transaction.cpp b/src/primitives/transaction.cpp index bdb470470e..28c145f71d 100644 --- a/src/primitives/transaction.cpp +++ b/src/primitives/transaction.cpp @@ -7,7 +7,7 @@ #include <hash.h> #include <tinyformat.h> -#include <utilstrencodings.h> +#include <util/strencodings.h> std::string COutPoint::ToString() const { diff --git a/src/protocol.cpp b/src/protocol.cpp index b4fc9def1f..bdf236c2c7 100644 --- a/src/protocol.cpp +++ b/src/protocol.cpp @@ -5,8 +5,8 @@ #include <protocol.h> -#include <util.h> -#include <utilstrencodings.h> +#include <util/system.h> +#include <util/strencodings.h> #ifndef WIN32 # include <arpa/inet.h> diff --git a/src/qt/bantablemodel.cpp b/src/qt/bantablemodel.cpp index 97348aad2b..dcfe3dcc57 100644 --- a/src/qt/bantablemodel.cpp +++ b/src/qt/bantablemodel.cpp @@ -10,7 +10,7 @@ #include <interfaces/node.h> #include <sync.h> -#include <utiltime.h> +#include <util/time.h> #include <QDebug> #include <QList> diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp index c0f9b3d5d3..7508f596e6 100644 --- a/src/qt/bitcoin.cpp +++ b/src/qt/bitcoin.cpp @@ -32,7 +32,7 @@ #include <rpc/server.h> #include <ui_interface.h> #include <uint256.h> -#include <util.h> +#include <util/system.h> #include <warnings.h> #include <walletinitinterface.h> diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index 311841017f..072334ebb0 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -33,7 +33,7 @@ #include <interfaces/node.h> #include <noui.h> #include <ui_interface.h> -#include <util.h> +#include <util/system.h> #include <iostream> diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index 183444efab..75012b279c 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -20,7 +20,7 @@ #include <netbase.h> #include <txmempool.h> #include <ui_interface.h> -#include <util.h> +#include <util/system.h> #include <warnings.h> #include <stdint.h> diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp index 5f6af61a70..a68140ccf9 100644 --- a/src/qt/guiutil.cpp +++ b/src/qt/guiutil.cpp @@ -18,7 +18,7 @@ #include <protocol.h> #include <script/script.h> #include <script/standard.h> -#include <util.h> +#include <util/system.h> #ifdef WIN32 #ifdef _WIN32_WINNT diff --git a/src/qt/intro.cpp b/src/qt/intro.cpp index b19cc17a4d..0b61b05318 100644 --- a/src/qt/intro.cpp +++ b/src/qt/intro.cpp @@ -13,7 +13,7 @@ #include <qt/guiutil.h> #include <interfaces/node.h> -#include <util.h> +#include <util/system.h> #include <QFileDialog> #include <QSettings> diff --git a/src/qt/paymentrequestplus.cpp b/src/qt/paymentrequestplus.cpp index a989988c45..b962ab1ef2 100644 --- a/src/qt/paymentrequestplus.cpp +++ b/src/qt/paymentrequestplus.cpp @@ -9,7 +9,7 @@ #include <qt/paymentrequestplus.h> -#include <util.h> +#include <util/system.h> #include <stdexcept> diff --git a/src/qt/paymentserver.cpp b/src/qt/paymentserver.cpp index 3f118e37f1..8148986b51 100644 --- a/src/qt/paymentserver.cpp +++ b/src/qt/paymentserver.cpp @@ -17,7 +17,7 @@ #include <policy/policy.h> #include <key_io.h> #include <ui_interface.h> -#include <util.h> +#include <util/system.h> #include <wallet/wallet.h> #include <cstdlib> diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index c004c783f2..606f1d2910 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -18,7 +18,7 @@ #include <netbase.h> #include <rpc/server.h> #include <rpc/client.h> -#include <util.h> +#include <util/system.h> #include <openssl/crypto.h> diff --git a/src/qt/splashscreen.cpp b/src/qt/splashscreen.cpp index 1eff4f6b65..b6235e91f7 100644 --- a/src/qt/splashscreen.cpp +++ b/src/qt/splashscreen.cpp @@ -15,7 +15,7 @@ #include <interfaces/node.h> #include <interfaces/wallet.h> #include <ui_interface.h> -#include <util.h> +#include <util/system.h> #include <version.h> #include <QApplication> diff --git a/src/qt/test/paymentservertests.cpp b/src/qt/test/paymentservertests.cpp index 5384b9e8b0..94907595f5 100644 --- a/src/qt/test/paymentservertests.cpp +++ b/src/qt/test/paymentservertests.cpp @@ -13,8 +13,8 @@ #include <random.h> #include <script/script.h> #include <script/standard.h> -#include <util.h> -#include <utilstrencodings.h> +#include <util/system.h> +#include <util/strencodings.h> #include <openssl/x509.h> #include <openssl/x509_vfy.h> diff --git a/src/qt/test/rpcnestedtests.cpp b/src/qt/test/rpcnestedtests.cpp index 2e321c1ba1..ed453336da 100644 --- a/src/qt/test/rpcnestedtests.cpp +++ b/src/qt/test/rpcnestedtests.cpp @@ -14,7 +14,7 @@ #include <qt/rpcconsole.h> #include <test/test_bitcoin.h> #include <univalue.h> -#include <util.h> +#include <util/system.h> #include <QDir> #include <QtGlobal> diff --git a/src/qt/test/test_main.cpp b/src/qt/test/test_main.cpp index 28df4ebf26..b6523604fd 100644 --- a/src/qt/test/test_main.cpp +++ b/src/qt/test/test_main.cpp @@ -8,7 +8,7 @@ #include <chainparams.h> #include <qt/test/rpcnestedtests.h> -#include <util.h> +#include <util/system.h> #include <qt/test/uritests.h> #include <qt/test/compattests.h> diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp index 3c5617bfa8..0d070d9e87 100644 --- a/src/qt/transactiondesc.cpp +++ b/src/qt/transactiondesc.cpp @@ -19,7 +19,7 @@ #include <validation.h> #include <script/script.h> #include <timedata.h> -#include <util.h> +#include <util/system.h> #include <wallet/db.h> #include <wallet/wallet.h> #include <policy/policy.h> @@ -27,7 +27,7 @@ #include <stdint.h> #include <string> -QString TransactionDesc::FormatTxStatus(const interfaces::WalletTx& wtx, const interfaces::WalletTxStatus& status, bool inMempool, int numBlocks, int64_t adjustedTime) +QString TransactionDesc::FormatTxStatus(const interfaces::WalletTx& wtx, const interfaces::WalletTxStatus& status, bool inMempool, int numBlocks) { if (!status.is_final) { @@ -53,11 +53,10 @@ QString TransactionDesc::FormatTxStatus(const interfaces::WalletTx& wtx, const i QString TransactionDesc::toHTML(interfaces::Node& node, interfaces::Wallet& wallet, TransactionRecord *rec, int unit) { int numBlocks; - int64_t adjustedTime; interfaces::WalletTxStatus status; interfaces::WalletOrderForm orderForm; bool inMempool; - interfaces::WalletTx wtx = wallet.getWalletTxDetails(rec->hash, status, orderForm, inMempool, numBlocks, adjustedTime); + interfaces::WalletTx wtx = wallet.getWalletTxDetails(rec->hash, status, orderForm, inMempool, numBlocks); QString strHTML; @@ -69,7 +68,7 @@ QString TransactionDesc::toHTML(interfaces::Node& node, interfaces::Wallet& wall CAmount nDebit = wtx.debit; CAmount nNet = nCredit - nDebit; - strHTML += "<b>" + tr("Status") + ":</b> " + FormatTxStatus(wtx, status, inMempool, numBlocks, adjustedTime); + strHTML += "<b>" + tr("Status") + ":</b> " + FormatTxStatus(wtx, status, inMempool, numBlocks); strHTML += "<br>"; strHTML += "<b>" + tr("Date") + ":</b> " + (nTime ? GUIUtil::dateTimeStr(nTime) : "") + "<br>"; diff --git a/src/qt/transactiondesc.h b/src/qt/transactiondesc.h index 80eca7b97c..cf955a433c 100644 --- a/src/qt/transactiondesc.h +++ b/src/qt/transactiondesc.h @@ -29,7 +29,7 @@ public: private: TransactionDesc() {} - static QString FormatTxStatus(const interfaces::WalletTx& wtx, const interfaces::WalletTxStatus& status, bool inMempool, int numBlocks, int64_t adjustedTime); + static QString FormatTxStatus(const interfaces::WalletTx& wtx, const interfaces::WalletTxStatus& status, bool inMempool, int numBlocks); }; #endif // BITCOIN_QT_TRANSACTIONDESC_H diff --git a/src/qt/transactionrecord.cpp b/src/qt/transactionrecord.cpp index d1a7527ac7..d88cfe52ed 100644 --- a/src/qt/transactionrecord.cpp +++ b/src/qt/transactionrecord.cpp @@ -158,7 +158,7 @@ QList<TransactionRecord> TransactionRecord::decomposeTransaction(const interface return parts; } -void TransactionRecord::updateStatus(const interfaces::WalletTxStatus& wtx, int numBlocks, int64_t adjustedTime) +void TransactionRecord::updateStatus(const interfaces::WalletTxStatus& wtx, int numBlocks) { // Determine transaction status diff --git a/src/qt/transactionrecord.h b/src/qt/transactionrecord.h index e187309d3f..470f70e2ab 100644 --- a/src/qt/transactionrecord.h +++ b/src/qt/transactionrecord.h @@ -138,7 +138,7 @@ public: /** Update status from core wallet tx. */ - void updateStatus(const interfaces::WalletTxStatus& wtx, int numBlocks, int64_t adjustedTime); + void updateStatus(const interfaces::WalletTxStatus& wtx, int numBlocks); /** Return whether a status update is needed. */ diff --git a/src/qt/transactiontablemodel.cpp b/src/qt/transactiontablemodel.cpp index b4be068904..1983c3bc92 100644 --- a/src/qt/transactiontablemodel.cpp +++ b/src/qt/transactiontablemodel.cpp @@ -18,7 +18,7 @@ #include <interfaces/node.h> #include <sync.h> #include <uint256.h> -#include <util.h> +#include <util/system.h> #include <validation.h> #include <QColor> @@ -193,9 +193,8 @@ public: // simply re-use the cached status. interfaces::WalletTxStatus wtx; int numBlocks; - int64_t adjustedTime; - if (wallet.tryGetTxStatus(rec->hash, wtx, numBlocks, adjustedTime) && rec->statusUpdateNeeded(numBlocks)) { - rec->updateStatus(wtx, numBlocks, adjustedTime); + if (wallet.tryGetTxStatus(rec->hash, wtx, numBlocks) && rec->statusUpdateNeeded(numBlocks)) { + rec->updateStatus(wtx, numBlocks); } return rec; } diff --git a/src/qt/utilitydialog.cpp b/src/qt/utilitydialog.cpp index faeed87ec4..ebf7bad795 100644 --- a/src/qt/utilitydialog.cpp +++ b/src/qt/utilitydialog.cpp @@ -22,7 +22,7 @@ #include <clientversion.h> #include <init.h> #include <interfaces/node.h> -#include <util.h> +#include <util/system.h> #include <stdio.h> diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index 71b2d321e2..353da0c9b4 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -20,7 +20,7 @@ #include <interfaces/node.h> #include <key_io.h> #include <ui_interface.h> -#include <util.h> // for GetBoolArg +#include <util/system.h> // for GetBoolArg #include <wallet/coincontrol.h> #include <wallet/wallet.h> diff --git a/src/qt/winshutdownmonitor.cpp b/src/qt/winshutdownmonitor.cpp index d732326b33..08cae76add 100644 --- a/src/qt/winshutdownmonitor.cpp +++ b/src/qt/winshutdownmonitor.cpp @@ -6,7 +6,7 @@ #if defined(Q_OS_WIN) #include <shutdown.h> -#include <util.h> +#include <util/system.h> #include <windows.h> diff --git a/src/random.cpp b/src/random.cpp index 503d5b3636..a34c70e1d5 100644 --- a/src/random.cpp +++ b/src/random.cpp @@ -13,7 +13,7 @@ #endif #include <logging.h> // for LogPrint() #include <sync.h> // for WAIT_LOCK -#include <utiltime.h> // for GetTime() +#include <util/time.h> // for GetTime() #include <stdlib.h> #include <chrono> @@ -35,7 +35,7 @@ #include <sys/random.h> #endif #ifdef HAVE_SYSCTL_ARND -#include <utilstrencodings.h> // for ARRAYLEN +#include <util/strencodings.h> // for ARRAYLEN #include <sys/sysctl.h> #endif diff --git a/src/rest.cpp b/src/rest.cpp index 1850c0b7a6..6c7e0384cb 100644 --- a/src/rest.cpp +++ b/src/rest.cpp @@ -16,7 +16,7 @@ #include <streams.h> #include <sync.h> #include <txmempool.h> -#include <utilstrencodings.h> +#include <util/strencodings.h> #include <version.h> #include <boost/algorithm/string.hpp> diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index ff71b19250..92f6f0fe11 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -26,8 +26,8 @@ #include <sync.h> #include <txdb.h> #include <txmempool.h> -#include <util.h> -#include <utilstrencodings.h> +#include <util/system.h> +#include <util/strencodings.h> #include <hash.h> #include <validationinterface.h> #include <versionbitsinfo.h> @@ -1798,6 +1798,10 @@ static UniValue getblockstats(const JSONRPCRequest& request) const bool do_calculate_weight = do_all || SetHasKeys(stats, "total_weight", "avgfeerate", "swtotal_weight", "avgfeerate", "feerate_percentiles", "minfeerate", "maxfeerate"); const bool do_calculate_sw = do_all || SetHasKeys(stats, "swtxs", "swtotal_size", "swtotal_weight"); + if (loop_inputs && !g_txindex) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "One or more of the selected stats requires -txindex enabled"); + } + CAmount maxfee = 0; CAmount maxfeerate = 0; CAmount minfee = MAX_MONEY; @@ -1861,10 +1865,6 @@ static UniValue getblockstats(const JSONRPCRequest& request) } if (loop_inputs) { - - if (!g_txindex) { - throw JSONRPCError(RPC_INVALID_PARAMETER, "One or more of the selected stats requires -txindex enabled"); - } CAmount tx_total_in = 0; for (const CTxIn& in : tx->vin) { CTransactionRef tx_in; diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp index a550f693e6..2b99808c07 100644 --- a/src/rpc/client.cpp +++ b/src/rpc/client.cpp @@ -5,7 +5,7 @@ #include <rpc/client.h> #include <rpc/protocol.h> -#include <util.h> +#include <util/system.h> #include <set> #include <stdint.h> diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 25cfc69da9..58b54c66de 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -20,8 +20,8 @@ #include <rpc/server.h> #include <shutdown.h> #include <txmempool.h> -#include <util.h> -#include <utilstrencodings.h> +#include <util/system.h> +#include <util/strencodings.h> #include <validation.h> #include <validationinterface.h> #include <versionbitsinfo.h> diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index 6a66998d37..cebf12bb34 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -17,8 +17,8 @@ #include <rpc/server.h> #include <rpc/util.h> #include <timedata.h> -#include <util.h> -#include <utilstrencodings.h> +#include <util/system.h> +#include <util/strencodings.h> #include <warnings.h> #include <stdint.h> @@ -446,7 +446,7 @@ static const CRPCCommand commands[] = { "control", "getmemoryinfo", &getmemoryinfo, {"mode"} }, { "control", "logging", &logging, {"include", "exclude"}}, { "util", "validateaddress", &validateaddress, {"address"} }, - { "util", "createmultisig", &createmultisig, {"nrequired","keys"} }, + { "util", "createmultisig", &createmultisig, {"nrequired","keys","address_type"} }, { "util", "verifymessage", &verifymessage, {"address","signature","message"} }, { "util", "signmessagewithprivkey", &signmessagewithprivkey, {"privkey","message"} }, diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index 846d90cd0a..4d893bb838 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -16,8 +16,8 @@ #include <sync.h> #include <timedata.h> #include <ui_interface.h> -#include <util.h> -#include <utilstrencodings.h> +#include <util/system.h> +#include <util/strencodings.h> #include <version.h> #include <warnings.h> diff --git a/src/rpc/protocol.cpp b/src/rpc/protocol.cpp index ee178f34ce..23999b305a 100644 --- a/src/rpc/protocol.cpp +++ b/src/rpc/protocol.cpp @@ -7,9 +7,9 @@ #include <random.h> #include <tinyformat.h> -#include <util.h> -#include <utilstrencodings.h> -#include <utiltime.h> +#include <util/system.h> +#include <util/strencodings.h> +#include <util/time.h> #include <version.h> /** diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index a2d990b51d..0f87646b08 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -26,7 +26,7 @@ #include <script/standard.h> #include <txmempool.h> #include <uint256.h> -#include <utilstrencodings.h> +#include <util/strencodings.h> #include <future> #include <stdint.h> diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index 60bf3c28c0..78abd7b610 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -11,8 +11,8 @@ #include <shutdown.h> #include <sync.h> #include <ui_interface.h> -#include <util.h> -#include <utilstrencodings.h> +#include <util/system.h> +#include <util/strencodings.h> #include <boost/bind.hpp> #include <boost/signals2/signal.hpp> diff --git a/src/rpc/util.cpp b/src/rpc/util.cpp index ba414bf3f5..8a66191a6a 100644 --- a/src/rpc/util.cpp +++ b/src/rpc/util.cpp @@ -7,7 +7,7 @@ #include <rpc/protocol.h> #include <rpc/util.h> #include <tinyformat.h> -#include <utilstrencodings.h> +#include <util/strencodings.h> // Converts a hex string to a public key if possible CPubKey HexToPubKey(const std::string& hex_in) diff --git a/src/script/descriptor.cpp b/src/script/descriptor.cpp index 478797e958..90c4ddcc11 100644 --- a/src/script/descriptor.cpp +++ b/src/script/descriptor.cpp @@ -10,8 +10,8 @@ #include <script/standard.h> #include <span.h> -#include <util.h> -#include <utilstrencodings.h> +#include <util/system.h> +#include <util/strencodings.h> #include <memory> #include <string> diff --git a/src/script/script.cpp b/src/script/script.cpp index 9bdf3ed808..982aa241e7 100644 --- a/src/script/script.cpp +++ b/src/script/script.cpp @@ -6,7 +6,7 @@ #include <script/script.h> #include <tinyformat.h> -#include <utilstrencodings.h> +#include <util/strencodings.h> const char* GetOpName(opcodetype opcode) { diff --git a/src/script/sigcache.cpp b/src/script/sigcache.cpp index 68f0542294..94005cf6f3 100644 --- a/src/script/sigcache.cpp +++ b/src/script/sigcache.cpp @@ -9,7 +9,7 @@ #include <pubkey.h> #include <random.h> #include <uint256.h> -#include <util.h> +#include <util/system.h> #include <cuckoocache.h> #include <boost/thread.hpp> diff --git a/src/script/sign.cpp b/src/script/sign.cpp index c721b20ced..89cc7c808c 100644 --- a/src/script/sign.cpp +++ b/src/script/sign.cpp @@ -280,6 +280,11 @@ bool SignPSBTInput(const SigningProvider& provider, const CMutableTransaction& t if (require_witness_sig && !sigdata.witness) return false; input.FromSignatureData(sigdata); + if (sigdata.witness) { + assert(!utxo.IsNull()); + input.witness_utxo = utxo; + } + // If both UTXO types are present, drop the unnecessary one. if (input.non_witness_utxo && !input.witness_utxo.IsNull()) { if (sigdata.witness) { diff --git a/src/script/sign.h b/src/script/sign.h index 689501269d..d47aada17d 100644 --- a/src/script/sign.h +++ b/src/script/sign.h @@ -302,6 +302,7 @@ struct PSBTInput template <typename Stream> inline void Unserialize(Stream& s) { // Read loop + bool found_sep = false; while(!s.empty()) { // Read std::vector<unsigned char> key; @@ -309,7 +310,10 @@ struct PSBTInput // the key is empty if that was actually a separator byte // This is a special case for key lengths 0 as those are not allowed (except for separator) - if (key.empty()) return; + if (key.empty()) { + found_sep = true; + break; + } // First byte of key is the type unsigned char type = key[0]; @@ -424,6 +428,10 @@ struct PSBTInput break; } } + + if (!found_sep) { + throw std::ios_base::failure("Separator is missing at the end of an input map"); + } } template <typename Stream> @@ -477,6 +485,7 @@ struct PSBTOutput template <typename Stream> inline void Unserialize(Stream& s) { // Read loop + bool found_sep = false; while(!s.empty()) { // Read std::vector<unsigned char> key; @@ -484,7 +493,10 @@ struct PSBTOutput // the key is empty if that was actually a separator byte // This is a special case for key lengths 0 as those are not allowed (except for separator) - if (key.empty()) return; + if (key.empty()) { + found_sep = true; + break; + } // First byte of key is the type unsigned char type = key[0]; @@ -529,6 +541,10 @@ struct PSBTOutput } } } + + if (!found_sep) { + throw std::ios_base::failure("Separator is missing at the end of an output map"); + } } template <typename Stream> @@ -604,6 +620,7 @@ struct PartiallySignedTransaction } // Read global data + bool found_sep = false; while(!s.empty()) { // Read std::vector<unsigned char> key; @@ -611,7 +628,10 @@ struct PartiallySignedTransaction // the key is empty if that was actually a separator byte // This is a special case for key lengths 0 as those are not allowed (except for separator) - if (key.empty()) break; + if (key.empty()) { + found_sep = true; + break; + } // First byte of key is the type unsigned char type = key[0]; @@ -651,6 +671,10 @@ struct PartiallySignedTransaction } } + if (!found_sep) { + throw std::ios_base::failure("Separator is missing at the end of the global map"); + } + // Make sure that we got an unsigned tx if (!tx) { throw std::ios_base::failure("No unsigned transcation was provided"); diff --git a/src/script/standard.cpp b/src/script/standard.cpp index 08ba1b1e0f..31bfd04b0f 100644 --- a/src/script/standard.cpp +++ b/src/script/standard.cpp @@ -8,8 +8,8 @@ #include <crypto/sha256.h> #include <pubkey.h> #include <script/script.h> -#include <util.h> -#include <utilstrencodings.h> +#include <util/system.h> +#include <util/strencodings.h> typedef std::vector<unsigned char> valtype; diff --git a/src/sync.cpp b/src/sync.cpp index c9aa98dcd6..30811f5f89 100644 --- a/src/sync.cpp +++ b/src/sync.cpp @@ -5,7 +5,7 @@ #include <sync.h> #include <logging.h> -#include <utilstrencodings.h> +#include <util/strencodings.h> #include <stdio.h> diff --git a/src/test/allocator_tests.cpp b/src/test/allocator_tests.cpp index c72c062b81..5a108dcdad 100644 --- a/src/test/allocator_tests.cpp +++ b/src/test/allocator_tests.cpp @@ -2,7 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include <util.h> +#include <util/system.h> #include <support/allocators/secure.h> #include <test/test_bitcoin.h> diff --git a/src/test/base32_tests.cpp b/src/test/base32_tests.cpp index 6b06d2e1b6..32af843bf6 100644 --- a/src/test/base32_tests.cpp +++ b/src/test/base32_tests.cpp @@ -2,7 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include <utilstrencodings.h> +#include <util/strencodings.h> #include <test/test_bitcoin.h> #include <boost/test/unit_test.hpp> diff --git a/src/test/base58_tests.cpp b/src/test/base58_tests.cpp index 5fc4abaf3d..f8f9b3c1a7 100644 --- a/src/test/base58_tests.cpp +++ b/src/test/base58_tests.cpp @@ -6,7 +6,7 @@ #include <base58.h> #include <test/test_bitcoin.h> -#include <utilstrencodings.h> +#include <util/strencodings.h> #include <univalue.h> diff --git a/src/test/base64_tests.cpp b/src/test/base64_tests.cpp index daceea262c..0abbb682a7 100644 --- a/src/test/base64_tests.cpp +++ b/src/test/base64_tests.cpp @@ -2,7 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include <utilstrencodings.h> +#include <util/strencodings.h> #include <test/test_bitcoin.h> #include <boost/test/unit_test.hpp> diff --git a/src/test/bip32_tests.cpp b/src/test/bip32_tests.cpp index 2cdbaca7ba..c9951f4b7e 100644 --- a/src/test/bip32_tests.cpp +++ b/src/test/bip32_tests.cpp @@ -7,8 +7,8 @@ #include <key.h> #include <key_io.h> #include <uint256.h> -#include <util.h> -#include <utilstrencodings.h> +#include <util/system.h> +#include <util/strencodings.h> #include <test/test_bitcoin.h> #include <string> diff --git a/src/test/blockfilter_tests.cpp b/src/test/blockfilter_tests.cpp index 4941ebd483..2144202b8d 100644 --- a/src/test/blockfilter_tests.cpp +++ b/src/test/blockfilter_tests.cpp @@ -10,7 +10,7 @@ #include <serialize.h> #include <streams.h> #include <univalue.h> -#include <utilstrencodings.h> +#include <util/strencodings.h> #include <boost/test/unit_test.hpp> diff --git a/src/test/bloom_tests.cpp b/src/test/bloom_tests.cpp index 8a8e8bfdc3..c900bee199 100644 --- a/src/test/bloom_tests.cpp +++ b/src/test/bloom_tests.cpp @@ -13,8 +13,8 @@ #include <serialize.h> #include <streams.h> #include <uint256.h> -#include <util.h> -#include <utilstrencodings.h> +#include <util/system.h> +#include <util/strencodings.h> #include <test/test_bitcoin.h> #include <vector> diff --git a/src/test/checkqueue_tests.cpp b/src/test/checkqueue_tests.cpp index f4b416c4ca..a757e06a9d 100644 --- a/src/test/checkqueue_tests.cpp +++ b/src/test/checkqueue_tests.cpp @@ -2,8 +2,8 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include <util.h> -#include <utiltime.h> +#include <util/system.h> +#include <util/time.h> #include <validation.h> #include <test/test_bitcoin.h> diff --git a/src/test/coins_tests.cpp b/src/test/coins_tests.cpp index 6f4b5ecd26..521312f1b7 100644 --- a/src/test/coins_tests.cpp +++ b/src/test/coins_tests.cpp @@ -6,7 +6,7 @@ #include <script/standard.h> #include <uint256.h> #include <undo.h> -#include <utilstrencodings.h> +#include <util/strencodings.h> #include <test/test_bitcoin.h> #include <validation.h> #include <consensus/validation.h> diff --git a/src/test/compress_tests.cpp b/src/test/compress_tests.cpp index a4e99d438f..e686c05165 100644 --- a/src/test/compress_tests.cpp +++ b/src/test/compress_tests.cpp @@ -3,7 +3,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <compressor.h> -#include <util.h> +#include <util/system.h> #include <test/test_bitcoin.h> #include <stdint.h> diff --git a/src/test/crypto_tests.cpp b/src/test/crypto_tests.cpp index 713e3e2ded..f3fd83a0cc 100644 --- a/src/test/crypto_tests.cpp +++ b/src/test/crypto_tests.cpp @@ -11,7 +11,7 @@ #include <crypto/hmac_sha256.h> #include <crypto/hmac_sha512.h> #include <random.h> -#include <utilstrencodings.h> +#include <util/strencodings.h> #include <test/test_bitcoin.h> #include <vector> diff --git a/src/test/denialofservice_tests.cpp b/src/test/denialofservice_tests.cpp index 52bbe96b96..97cf5ed345 100644 --- a/src/test/denialofservice_tests.cpp +++ b/src/test/denialofservice_tests.cpp @@ -11,7 +11,7 @@ #include <pow.h> #include <script/sign.h> #include <serialize.h> -#include <util.h> +#include <util/system.h> #include <validation.h> #include <test/test_bitcoin.h> diff --git a/src/test/descriptor_tests.cpp b/src/test/descriptor_tests.cpp index f3083bab4a..57e4b067c0 100644 --- a/src/test/descriptor_tests.cpp +++ b/src/test/descriptor_tests.cpp @@ -9,7 +9,7 @@ #include <test/test_bitcoin.h> #include <boost/test/unit_test.hpp> #include <script/descriptor.h> -#include <utilstrencodings.h> +#include <util/strencodings.h> namespace { diff --git a/src/test/getarg_tests.cpp b/src/test/getarg_tests.cpp index 7592330b10..0432ede3e0 100644 --- a/src/test/getarg_tests.cpp +++ b/src/test/getarg_tests.cpp @@ -2,7 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include <util.h> +#include <util/system.h> #include <test/test_bitcoin.h> #include <string> diff --git a/src/test/hash_tests.cpp b/src/test/hash_tests.cpp index 6ed0209895..fd3a6b0dec 100644 --- a/src/test/hash_tests.cpp +++ b/src/test/hash_tests.cpp @@ -3,7 +3,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <hash.h> -#include <utilstrencodings.h> +#include <util/strencodings.h> #include <test/test_bitcoin.h> #include <vector> diff --git a/src/test/key_io_tests.cpp b/src/test/key_io_tests.cpp index a0c10d8ddd..5db62f4bba 100644 --- a/src/test/key_io_tests.cpp +++ b/src/test/key_io_tests.cpp @@ -8,7 +8,7 @@ #include <key.h> #include <key_io.h> #include <script/script.h> -#include <utilstrencodings.h> +#include <util/strencodings.h> #include <test/test_bitcoin.h> #include <boost/test/unit_test.hpp> diff --git a/src/test/key_properties.cpp b/src/test/key_properties.cpp index 14e3c85359..c564b4eab8 100644 --- a/src/test/key_properties.cpp +++ b/src/test/key_properties.cpp @@ -6,8 +6,8 @@ #include <base58.h> #include <script/script.h> #include <uint256.h> -#include <util.h> -#include <utilstrencodings.h> +#include <util/system.h> +#include <util/strencodings.h> #include <test/test_bitcoin.h> #include <string> #include <vector> diff --git a/src/test/key_tests.cpp b/src/test/key_tests.cpp index 61db70decb..91cafd05d9 100644 --- a/src/test/key_tests.cpp +++ b/src/test/key_tests.cpp @@ -7,8 +7,8 @@ #include <key_io.h> #include <script/script.h> #include <uint256.h> -#include <util.h> -#include <utilstrencodings.h> +#include <util/system.h> +#include <util/strencodings.h> #include <test/test_bitcoin.h> #include <string> diff --git a/src/test/mempool_tests.cpp b/src/test/mempool_tests.cpp index 0e15464fd9..db38c9623c 100644 --- a/src/test/mempool_tests.cpp +++ b/src/test/mempool_tests.cpp @@ -4,7 +4,7 @@ #include <policy/policy.h> #include <txmempool.h> -#include <util.h> +#include <util/system.h> #include <test/test_bitcoin.h> diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp index 3eb8aa14fd..a7074a5e43 100644 --- a/src/test/miner_tests.cpp +++ b/src/test/miner_tests.cpp @@ -15,8 +15,8 @@ #include <script/standard.h> #include <txmempool.h> #include <uint256.h> -#include <util.h> -#include <utilstrencodings.h> +#include <util/system.h> +#include <util/strencodings.h> #include <test/test_bitcoin.h> @@ -92,8 +92,8 @@ static CBlockIndex CreateBlockIndex(int nHeight) static bool TestSequenceLocks(const CTransaction &tx, int flags) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { - LOCK(mempool.cs); - return CheckSequenceLocks(tx, flags); + LOCK(::mempool.cs); + return CheckSequenceLocks(::mempool, tx, flags); } // Test suite for ancestor feerate transaction selection. diff --git a/src/test/net_tests.cpp b/src/test/net_tests.cpp index 35a143957e..213afed730 100644 --- a/src/test/net_tests.cpp +++ b/src/test/net_tests.cpp @@ -11,7 +11,7 @@ #include <net.h> #include <netbase.h> #include <chainparams.h> -#include <util.h> +#include <util/system.h> #include <memory> diff --git a/src/test/netbase_tests.cpp b/src/test/netbase_tests.cpp index 8072eb922d..0d557cff13 100644 --- a/src/test/netbase_tests.cpp +++ b/src/test/netbase_tests.cpp @@ -4,7 +4,7 @@ #include <netbase.h> #include <test/test_bitcoin.h> -#include <utilstrencodings.h> +#include <util/strencodings.h> #include <string> diff --git a/src/test/policyestimator_tests.cpp b/src/test/policyestimator_tests.cpp index 2022ed6659..51668cbe64 100644 --- a/src/test/policyestimator_tests.cpp +++ b/src/test/policyestimator_tests.cpp @@ -6,7 +6,7 @@ #include <policy/fees.h> #include <txmempool.h> #include <uint256.h> -#include <util.h> +#include <util/system.h> #include <test/test_bitcoin.h> diff --git a/src/test/pow_tests.cpp b/src/test/pow_tests.cpp index 1ac9adc740..f788c34e05 100644 --- a/src/test/pow_tests.cpp +++ b/src/test/pow_tests.cpp @@ -6,7 +6,7 @@ #include <chainparams.h> #include <pow.h> #include <random.h> -#include <util.h> +#include <util/system.h> #include <test/test_bitcoin.h> #include <boost/test/unit_test.hpp> diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp index 7fbf37e7fb..1c70fdcce6 100644 --- a/src/test/script_tests.cpp +++ b/src/test/script_tests.cpp @@ -10,8 +10,8 @@ #include <script/script.h> #include <script/script_error.h> #include <script/sign.h> -#include <util.h> -#include <utilstrencodings.h> +#include <util/system.h> +#include <util/strencodings.h> #include <test/test_bitcoin.h> #include <rpc/server.h> diff --git a/src/test/sighash_tests.cpp b/src/test/sighash_tests.cpp index e6905457bb..c329844341 100644 --- a/src/test/sighash_tests.cpp +++ b/src/test/sighash_tests.cpp @@ -11,8 +11,8 @@ #include <serialize.h> #include <streams.h> #include <test/test_bitcoin.h> -#include <util.h> -#include <utilstrencodings.h> +#include <util/system.h> +#include <util/strencodings.h> #include <version.h> #include <iostream> diff --git a/src/test/skiplist_tests.cpp b/src/test/skiplist_tests.cpp index c0754618fb..552bd1ab03 100644 --- a/src/test/skiplist_tests.cpp +++ b/src/test/skiplist_tests.cpp @@ -3,7 +3,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <chain.h> -#include <util.h> +#include <util/system.h> #include <test/test_bitcoin.h> #include <vector> diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp index c527ad448c..9978c71661 100644 --- a/src/test/transaction_tests.cpp +++ b/src/test/transaction_tests.cpp @@ -19,7 +19,7 @@ #include <script/sign.h> #include <script/script_error.h> #include <script/standard.h> -#include <utilstrencodings.h> +#include <util/strencodings.h> #include <map> #include <string> diff --git a/src/test/txindex_tests.cpp b/src/test/txindex_tests.cpp index 2a160b9988..43e025c58f 100644 --- a/src/test/txindex_tests.cpp +++ b/src/test/txindex_tests.cpp @@ -5,8 +5,8 @@ #include <index/txindex.h> #include <script/standard.h> #include <test/test_bitcoin.h> -#include <util.h> -#include <utiltime.h> +#include <util/system.h> +#include <util/time.h> #include <validation.h> #include <boost/test/unit_test.hpp> diff --git a/src/test/txvalidationcache_tests.cpp b/src/test/txvalidationcache_tests.cpp index 2bf835a756..506a60d173 100644 --- a/src/test/txvalidationcache_tests.cpp +++ b/src/test/txvalidationcache_tests.cpp @@ -12,7 +12,7 @@ #include <script/standard.h> #include <script/sign.h> #include <test/test_bitcoin.h> -#include <utiltime.h> +#include <util/time.h> #include <core_io.h> #include <keystore.h> #include <policy/policy.h> diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp index c74eb7531a..ff19b12a9c 100644 --- a/src/test/util_tests.cpp +++ b/src/test/util_tests.cpp @@ -2,13 +2,13 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include <util.h> +#include <util/system.h> #include <clientversion.h> #include <primitives/transaction.h> #include <sync.h> -#include <utilstrencodings.h> -#include <utilmoneystr.h> +#include <util/strencodings.h> +#include <util/moneystr.h> #include <test/test_bitcoin.h> #include <stdint.h> diff --git a/src/timedata.cpp b/src/timedata.cpp index 291111feb2..9c022c9ad1 100644 --- a/src/timedata.cpp +++ b/src/timedata.cpp @@ -11,8 +11,8 @@ #include <netaddress.h> #include <sync.h> #include <ui_interface.h> -#include <util.h> -#include <utilstrencodings.h> +#include <util/system.h> +#include <util/strencodings.h> #include <warnings.h> diff --git a/src/torcontrol.cpp b/src/torcontrol.cpp index c88f61f1ec..229cc7d553 100644 --- a/src/torcontrol.cpp +++ b/src/torcontrol.cpp @@ -4,10 +4,10 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <torcontrol.h> -#include <utilstrencodings.h> +#include <util/strencodings.h> #include <netbase.h> #include <net.h> -#include <util.h> +#include <util/system.h> #include <crypto/hmac_sha256.h> #include <vector> diff --git a/src/txdb.cpp b/src/txdb.cpp index cbea550739..8447352c54 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -11,7 +11,7 @@ #include <pow.h> #include <shutdown.h> #include <uint256.h> -#include <util.h> +#include <util/system.h> #include <ui_interface.h> #include <stdint.h> diff --git a/src/txmempool.cpp b/src/txmempool.cpp index 3ad93342c4..68f47d5cce 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -14,9 +14,9 @@ #include <reverse_iterator.h> #include <streams.h> #include <timedata.h> -#include <util.h> -#include <utilmoneystr.h> -#include <utiltime.h> +#include <util/system.h> +#include <util/moneystr.h> +#include <util/time.h> CTxMemPoolEntry::CTxMemPoolEntry(const CTransactionRef& _tx, const CAmount& _nFee, int64_t _nTime, unsigned int _entryHeight, @@ -498,7 +498,7 @@ void CTxMemPool::removeForReorg(const CCoinsViewCache *pcoins, unsigned int nMem const CTransaction& tx = it->GetTx(); LockPoints lp = it->GetLockPoints(); bool validLP = TestLockPointValidity(&lp); - if (!CheckFinalTx(tx, flags) || !CheckSequenceLocks(tx, flags, &lp, validLP)) { + if (!CheckFinalTx(tx, flags) || !CheckSequenceLocks(*this, tx, flags, &lp, validLP)) { // Note if CheckSequenceLocks fails the LockPoints may still be invalid // So it's critical that we remove the tx and not depend on the LockPoints. txToRemove.insert(it); diff --git a/src/ui_interface.cpp b/src/ui_interface.cpp index 22b4768059..947d7e2308 100644 --- a/src/ui_interface.cpp +++ b/src/ui_interface.cpp @@ -3,7 +3,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <ui_interface.h> -#include <util.h> +#include <util/system.h> #include <boost/signals2/last_value.hpp> #include <boost/signals2/signal.hpp> diff --git a/src/uint256.cpp b/src/uint256.cpp index e513dc1de7..d9da668036 100644 --- a/src/uint256.cpp +++ b/src/uint256.cpp @@ -5,7 +5,7 @@ #include <uint256.h> -#include <utilstrencodings.h> +#include <util/strencodings.h> #include <stdio.h> #include <string.h> @@ -29,7 +29,7 @@ void base_blob<BITS>::SetHex(const char* psz) memset(data, 0, sizeof(data)); // skip leading spaces - while (isspace(*psz)) + while (IsSpace(*psz)) psz++; // skip 0x diff --git a/src/utilmemory.h b/src/util/memory.h index e71fe92284..15ecf8f80d 100644 --- a/src/utilmemory.h +++ b/src/util/memory.h @@ -3,8 +3,8 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#ifndef BITCOIN_UTILMEMORY_H -#define BITCOIN_UTILMEMORY_H +#ifndef BITCOIN_UTIL_MEMORY_H +#define BITCOIN_UTIL_MEMORY_H #include <memory> #include <utility> diff --git a/src/utilmoneystr.cpp b/src/util/moneystr.cpp index 326ef9b27a..4c4de7b729 100644 --- a/src/utilmoneystr.cpp +++ b/src/util/moneystr.cpp @@ -3,11 +3,11 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include <utilmoneystr.h> +#include <util/moneystr.h> #include <primitives/transaction.h> #include <tinyformat.h> -#include <utilstrencodings.h> +#include <util/strencodings.h> std::string FormatMoney(const CAmount& n) { @@ -41,7 +41,7 @@ bool ParseMoney(const char* pszIn, CAmount& nRet) std::string strWhole; int64_t nUnits = 0; const char* p = pszIn; - while (isspace(*p)) + while (IsSpace(*p)) p++; for (; *p; p++) { @@ -56,14 +56,14 @@ bool ParseMoney(const char* pszIn, CAmount& nRet) } break; } - if (isspace(*p)) + if (IsSpace(*p)) break; if (!isdigit(*p)) return false; strWhole.insert(strWhole.end(), *p); } for (; *p; p++) - if (!isspace(*p)) + if (!IsSpace(*p)) return false; if (strWhole.size() > 10) // guard against 63 bit overflow return false; diff --git a/src/utilmoneystr.h b/src/util/moneystr.h index 67579adb77..9133f46d5d 100644 --- a/src/utilmoneystr.h +++ b/src/util/moneystr.h @@ -6,8 +6,8 @@ /** * Money parsing/formatting utilities. */ -#ifndef BITCOIN_UTILMONEYSTR_H -#define BITCOIN_UTILMONEYSTR_H +#ifndef BITCOIN_UTIL_MONEYSTR_H +#define BITCOIN_UTIL_MONEYSTR_H #include <stdint.h> #include <string> @@ -21,4 +21,4 @@ std::string FormatMoney(const CAmount& n); bool ParseMoney(const std::string& str, CAmount& nRet); bool ParseMoney(const char* pszIn, CAmount& nRet); -#endif // BITCOIN_UTILMONEYSTR_H +#endif // BITCOIN_UTIL_MONEYSTR_H diff --git a/src/utilstrencodings.cpp b/src/util/strencodings.cpp index 4940267bae..5b8520030b 100644 --- a/src/utilstrencodings.cpp +++ b/src/util/strencodings.cpp @@ -3,7 +3,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include <utilstrencodings.h> +#include <util/strencodings.h> #include <tinyformat.h> @@ -85,7 +85,7 @@ std::vector<unsigned char> ParseHex(const char* psz) std::vector<unsigned char> vch; while (true) { - while (isspace(*psz)) + while (IsSpace(*psz)) psz++; signed char c = HexDigit(*psz++); if (c == (signed char)-1) @@ -266,7 +266,7 @@ static bool ParsePrechecks(const std::string& str) { if (str.empty()) // No empty string allowed return false; - if (str.size() >= 1 && (isspace(str[0]) || isspace(str[str.size()-1]))) // No padding allowed + if (str.size() >= 1 && (IsSpace(str[0]) || IsSpace(str[str.size()-1]))) // No padding allowed return false; if (str.size() != strlen(str.c_str())) // No embedded NUL characters allowed return false; diff --git a/src/utilstrencodings.h b/src/util/strencodings.h index 846a3917a2..132071c61e 100644 --- a/src/utilstrencodings.h +++ b/src/util/strencodings.h @@ -6,8 +6,8 @@ /** * Utilities for converting data from/to strings. */ -#ifndef BITCOIN_UTILSTRENCODINGS_H -#define BITCOIN_UTILSTRENCODINGS_H +#ifndef BITCOIN_UTIL_STRENCODINGS_H +#define BITCOIN_UTIL_STRENCODINGS_H #include <stdint.h> #include <string> @@ -72,6 +72,21 @@ constexpr bool IsDigit(char c) } /** + * Tests if the given character is a whitespace character. The whitespace characters + * are: space, form-feed ('\f'), newline ('\n'), carriage return ('\r'), horizontal + * tab ('\t'), and vertical tab ('\v'). + * + * This function is locale independent. Under the C locale this function gives the + * same result as std::isspace. + * + * @param[in] c character to test + * @return true if the argument is a whitespace character; otherwise false + */ +constexpr inline bool IsSpace(char c) noexcept { + return c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v'; +} + +/** * Convert string to signed 32-bit integer with strict parse error feedback. * @returns true if the entire string could be parsed as valid integer, * false if not the entire string could be parsed or when overflow or underflow occurred. @@ -230,4 +245,4 @@ constexpr unsigned char ToUpper(unsigned char c) */ std::string Capitalize(std::string str); -#endif // BITCOIN_UTILSTRENCODINGS_H +#endif // BITCOIN_UTIL_STRENCODINGS_H diff --git a/src/util.cpp b/src/util/system.cpp index 6479b9b9ce..4f5dd2d6e9 100644 --- a/src/util.cpp +++ b/src/util/system.cpp @@ -3,12 +3,12 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include <util.h> +#include <util/system.h> #include <chainparamsbase.h> #include <random.h> #include <serialize.h> -#include <utilstrencodings.h> +#include <util/strencodings.h> #include <stdarg.h> diff --git a/src/util.h b/src/util/system.h index fa6d2cd489..5634b8dd61 100644 --- a/src/util.h +++ b/src/util/system.h @@ -7,8 +7,8 @@ * Server/client environment: argument handling, config file parsing, * thread wrappers, startup time */ -#ifndef BITCOIN_UTIL_H -#define BITCOIN_UTIL_H +#ifndef BITCOIN_UTIL_SYSTEM_H +#define BITCOIN_UTIL_SYSTEM_H #if defined(HAVE_CONFIG_H) #include <config/bitcoin-config.h> @@ -19,8 +19,8 @@ #include <logging.h> #include <sync.h> #include <tinyformat.h> -#include <utilmemory.h> -#include <utiltime.h> +#include <util/memory.h> +#include <util/time.h> #include <atomic> #include <exception> @@ -379,4 +379,4 @@ private: } // namespace util -#endif // BITCOIN_UTIL_H +#endif // BITCOIN_UTIL_SYSTEM_H diff --git a/src/utiltime.cpp b/src/util/time.cpp index 908791da48..83a7937d8f 100644 --- a/src/utiltime.cpp +++ b/src/util/time.cpp @@ -7,7 +7,7 @@ #include <config/bitcoin-config.h> #endif -#include <utiltime.h> +#include <util/time.h> #include <atomic> #include <boost/date_time/posix_time/posix_time.hpp> diff --git a/src/utiltime.h b/src/util/time.h index c3e3da3014..f2e2747434 100644 --- a/src/utiltime.h +++ b/src/util/time.h @@ -3,8 +3,8 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#ifndef BITCOIN_UTILTIME_H -#define BITCOIN_UTILTIME_H +#ifndef BITCOIN_UTIL_TIME_H +#define BITCOIN_UTIL_TIME_H #include <stdint.h> #include <string> @@ -35,4 +35,4 @@ std::string FormatISO8601DateTime(int64_t nTime); std::string FormatISO8601Date(int64_t nTime); std::string FormatISO8601Time(int64_t nTime); -#endif // BITCOIN_UTILTIME_H +#endif // BITCOIN_UTIL_TIME_H diff --git a/src/validation.cpp b/src/validation.cpp index 29804c5e10..241957878e 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -35,9 +35,9 @@ #include <txmempool.h> #include <ui_interface.h> #include <undo.h> -#include <util.h> -#include <utilmoneystr.h> -#include <utilstrencodings.h> +#include <util/system.h> +#include <util/moneystr.h> +#include <util/strencodings.h> #include <validationinterface.h> #include <warnings.h> @@ -361,10 +361,10 @@ bool TestLockPointValidity(const LockPoints* lp) return true; } -bool CheckSequenceLocks(const CTransaction &tx, int flags, LockPoints* lp, bool useExistingLockPoints) +bool CheckSequenceLocks(const CTxMemPool& pool, const CTransaction& tx, int flags, LockPoints* lp, bool useExistingLockPoints) { AssertLockHeld(cs_main); - AssertLockHeld(mempool.cs); + AssertLockHeld(pool.cs); CBlockIndex* tip = chainActive.Tip(); assert(tip != nullptr); @@ -387,7 +387,7 @@ bool CheckSequenceLocks(const CTransaction &tx, int flags, LockPoints* lp, bool } else { // pcoinsTip contains the UTXO set for chainActive.Tip() - CCoinsViewMemPool viewMemPool(pcoinsTip.get(), mempool); + CCoinsViewMemPool viewMemPool(pcoinsTip.get(), pool); std::vector<int> prevheights; prevheights.resize(tx.vin.size()); for (size_t txinIndex = 0; txinIndex < tx.vin.size(); txinIndex++) { @@ -679,7 +679,7 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool // be mined yet. // Must keep pool.cs for this unless we change CheckSequenceLocks to take a // CoinsViewCache instead of create its own - if (!CheckSequenceLocks(tx, STANDARD_LOCKTIME_VERIFY_FLAGS, &lp)) + if (!CheckSequenceLocks(pool, tx, STANDARD_LOCKTIME_VERIFY_FLAGS, &lp)) return state.DoS(0, false, REJECT_NONSTANDARD, "non-BIP68-final"); CAmount nFees = 0; diff --git a/src/validation.h b/src/validation.h index dbd827633b..3e98ebc866 100644 --- a/src/validation.h +++ b/src/validation.h @@ -347,7 +347,7 @@ bool TestLockPointValidity(const LockPoints* lp) EXCLUSIVE_LOCKS_REQUIRED(cs_mai * * See consensus/consensus.h for flag definitions. */ -bool CheckSequenceLocks(const CTransaction &tx, int flags, LockPoints* lp = nullptr, bool useExistingLockPoints = false) EXCLUSIVE_LOCKS_REQUIRED(cs_main); +bool CheckSequenceLocks(const CTxMemPool& pool, const CTransaction& tx, int flags, LockPoints* lp = nullptr, bool useExistingLockPoints = false) EXCLUSIVE_LOCKS_REQUIRED(cs_main); /** * Closure representing one script verification diff --git a/src/validationinterface.cpp b/src/validationinterface.cpp index e25eca2368..214a9ffba9 100644 --- a/src/validationinterface.cpp +++ b/src/validationinterface.cpp @@ -8,7 +8,7 @@ #include <primitives/block.h> #include <scheduler.h> #include <txmempool.h> -#include <util.h> +#include <util/system.h> #include <validation.h> #include <list> diff --git a/src/wallet/coincontrol.cpp b/src/wallet/coincontrol.cpp index 645981faa4..87d2c4f06e 100644 --- a/src/wallet/coincontrol.cpp +++ b/src/wallet/coincontrol.cpp @@ -4,7 +4,7 @@ #include <wallet/coincontrol.h> -#include <util.h> +#include <util/system.h> void CCoinControl::SetNull() { diff --git a/src/wallet/coinselection.cpp b/src/wallet/coinselection.cpp index fdeb89553b..5e955b8495 100644 --- a/src/wallet/coinselection.cpp +++ b/src/wallet/coinselection.cpp @@ -4,8 +4,8 @@ #include <wallet/coinselection.h> -#include <util.h> -#include <utilmoneystr.h> +#include <util/system.h> +#include <util/moneystr.h> #include <boost/optional.hpp> diff --git a/src/wallet/crypter.cpp b/src/wallet/crypter.cpp index 729e4e39b0..de320b4e9e 100644 --- a/src/wallet/crypter.cpp +++ b/src/wallet/crypter.cpp @@ -8,7 +8,7 @@ #include <crypto/sha512.h> #include <script/script.h> #include <script/standard.h> -#include <util.h> +#include <util/system.h> #include <string> #include <vector> diff --git a/src/wallet/db.cpp b/src/wallet/db.cpp index 25880f3529..74787eb5d2 100644 --- a/src/wallet/db.cpp +++ b/src/wallet/db.cpp @@ -8,7 +8,7 @@ #include <addrman.h> #include <hash.h> #include <protocol.h> -#include <utilstrencodings.h> +#include <util/strencodings.h> #include <wallet/walletutil.h> #include <stdint.h> diff --git a/src/wallet/db.h b/src/wallet/db.h index 68a59607ae..8f96483a18 100644 --- a/src/wallet/db.h +++ b/src/wallet/db.h @@ -11,7 +11,7 @@ #include <serialize.h> #include <streams.h> #include <sync.h> -#include <util.h> +#include <util/system.h> #include <version.h> #include <atomic> diff --git a/src/wallet/feebumper.cpp b/src/wallet/feebumper.cpp index 677bf74b5d..5eb70cd7a5 100644 --- a/src/wallet/feebumper.cpp +++ b/src/wallet/feebumper.cpp @@ -12,8 +12,8 @@ #include <policy/rbf.h> #include <validation.h> //for mempool access #include <txmempool.h> -#include <utilmoneystr.h> -#include <util.h> +#include <util/moneystr.h> +#include <util/system.h> #include <net.h> //! Check whether transaction has descendant in wallet or mempool, or has been diff --git a/src/wallet/fees.cpp b/src/wallet/fees.cpp index d620e25f2b..9e2984ff05 100644 --- a/src/wallet/fees.cpp +++ b/src/wallet/fees.cpp @@ -7,7 +7,7 @@ #include <policy/policy.h> #include <txmempool.h> -#include <util.h> +#include <util/system.h> #include <validation.h> #include <wallet/coincontrol.h> #include <wallet/wallet.h> diff --git a/src/wallet/init.cpp b/src/wallet/init.cpp index ad22fe4a58..220780c96c 100644 --- a/src/wallet/init.cpp +++ b/src/wallet/init.cpp @@ -8,8 +8,8 @@ #include <net.h> #include <scheduler.h> #include <outputtype.h> -#include <util.h> -#include <utilmoneystr.h> +#include <util/system.h> +#include <util/moneystr.h> #include <validation.h> #include <walletinitinterface.h> #include <wallet/rpcwallet.h> diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index 92457c4644..2a4cf0147e 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -9,8 +9,8 @@ #include <script/script.h> #include <script/standard.h> #include <sync.h> -#include <util.h> -#include <utiltime.h> +#include <util/system.h> +#include <util/time.h> #include <wallet/wallet.h> #include <merkleblock.h> #include <core_io.h> @@ -808,29 +808,24 @@ UniValue dumpwallet(const JSONRPCRequest& request) static UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, const int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet) { try { - bool success = false; - - // Required fields. + // First ensure scriptPubKey has either a script or JSON with "address" string const UniValue& scriptPubKey = data["scriptPubKey"]; - - // Should have script or JSON with "address". - if (!(scriptPubKey.getType() == UniValue::VOBJ && scriptPubKey.exists("address")) && !(scriptPubKey.getType() == UniValue::VSTR)) { - throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid scriptPubKey"); + bool isScript = scriptPubKey.getType() == UniValue::VSTR; + if (!isScript && !(scriptPubKey.getType() == UniValue::VOBJ && scriptPubKey.exists("address"))) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "scriptPubKey must be string with script or JSON with address string"); } + const std::string& output = isScript ? scriptPubKey.get_str() : scriptPubKey["address"].get_str(); // Optional fields. const std::string& strRedeemScript = data.exists("redeemscript") ? data["redeemscript"].get_str() : ""; + const std::string& witness_script_hex = data.exists("witnessscript") ? data["witnessscript"].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 std::string& label = data.exists("label") && !internal ? data["label"].get_str() : ""; - - bool isScript = scriptPubKey.getType() == UniValue::VSTR; - bool isP2SH = strRedeemScript.length() > 0; - const std::string& output = isScript ? scriptPubKey.get_str() : scriptPubKey["address"].get_str(); + const std::string& label = data.exists("label") ? data["label"].get_str() : ""; - // Parse the output. + // Generate the script and destination for the scriptPubKey provided CScript script; CTxDestination dest; @@ -854,35 +849,38 @@ static UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, con // Watchonly and private keys if (watchOnly && keys.size()) { - throw JSONRPCError(RPC_INVALID_PARAMETER, "Incompatibility found between watchonly and keys"); + throw JSONRPCError(RPC_INVALID_PARAMETER, "Watch-only addresses should not include private keys"); } - // Internal + Label + // Internal addresses should not have a label if (internal && data.exists("label")) { - throw JSONRPCError(RPC_INVALID_PARAMETER, "Incompatibility found between internal and label"); + throw JSONRPCError(RPC_INVALID_PARAMETER, "Internal addresses should not have a label"); } - // Keys / PubKeys size check. - if (!isP2SH && (keys.size() > 1 || pubKeys.size() > 1)) { // Address / scriptPubKey - throw JSONRPCError(RPC_INVALID_PARAMETER, "More than private key given for one address"); + // Force users to provide the witness script in its field rather than redeemscript + if (!strRedeemScript.empty() && script.IsPayToWitnessScriptHash()) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "P2WSH addresses have an empty redeemscript. Please provide the witnessscript instead."); } - // Invalid P2SH redeemScript - if (isP2SH && !IsHex(strRedeemScript)) { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid redeem script"); - } - - // Process. // + CScript scriptpubkey_script = script; + CTxDestination scriptpubkey_dest = dest; + bool allow_p2wpkh = true; // P2SH - if (isP2SH) { + if (!strRedeemScript.empty() && script.IsPayToScriptHash()) { + // Check the redeemScript is valid + if (!IsHex(strRedeemScript)) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid redeem script: must be hex string"); + } + // Import redeem script. std::vector<unsigned char> vData(ParseHex(strRedeemScript)); CScript redeemScript = CScript(vData.begin(), vData.end()); + CScriptID redeem_id(redeemScript); - // Invalid P2SH address - if (!script.IsPayToScriptHash()) { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid P2SH address / script"); + // Check that the redeemScript and scriptPubKey match + if (GetScriptForDestination(redeem_id) != script) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "The redeemScript does not match the scriptPubKey"); } pwallet->MarkDirty(); @@ -891,103 +889,83 @@ static UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, con throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet"); } - CScriptID redeem_id(redeemScript); if (!pwallet->HaveCScript(redeem_id) && !pwallet->AddCScript(redeemScript)) { throw JSONRPCError(RPC_WALLET_ERROR, "Error adding p2sh redeemScript to wallet"); } - CScript redeemDestination = GetScriptForDestination(redeem_id); + // Now set script to the redeemScript so we parse the inner script as P2WSH or P2WPKH below + script = redeemScript; + ExtractDestination(script, dest); + } - if (::IsMine(*pwallet, redeemDestination) == ISMINE_SPENDABLE) { - throw JSONRPCError(RPC_WALLET_ERROR, "The wallet already contains the private key for this address or script"); + // (P2SH-)P2WSH + if (!witness_script_hex.empty() && script.IsPayToWitnessScriptHash()) { + if (!IsHex(witness_script_hex)) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid witness script: must be hex string"); } - pwallet->MarkDirty(); + // Generate the scripts + std::vector<unsigned char> witness_script_parsed(ParseHex(witness_script_hex)); + CScript witness_script = CScript(witness_script_parsed.begin(), witness_script_parsed.end()); + CScriptID witness_id(witness_script); - if (!pwallet->AddWatchOnly(redeemDestination, timestamp)) { - throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet"); + // Check that the witnessScript and scriptPubKey match + if (GetScriptForDestination(WitnessV0ScriptHash(witness_script)) != script) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "The witnessScript does not match the scriptPubKey or redeemScript"); } - // add to address book or update label - if (IsValidDestination(dest)) { - pwallet->SetAddressBook(dest, label, "receive"); + // Add the witness script as watch only only if it is not for P2SH-P2WSH + if (!scriptpubkey_script.IsPayToScriptHash() && !pwallet->AddWatchOnly(witness_script, timestamp)) { + throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet"); } - // Import private keys. - if (keys.size()) { - for (size_t i = 0; i < keys.size(); i++) { - const std::string& privkey = keys[i].get_str(); - - CKey key = DecodeSecret(privkey); - - if (!key.IsValid()) { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key encoding"); - } - - CPubKey pubkey = key.GetPubKey(); - assert(key.VerifyPubKey(pubkey)); - - CKeyID vchAddress = pubkey.GetID(); - pwallet->MarkDirty(); - pwallet->SetAddressBook(vchAddress, label, "receive"); - - if (pwallet->HaveKey(vchAddress)) { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Already have this key"); - } - - pwallet->mapKeyMetadata[vchAddress].nCreateTime = timestamp; + if (!pwallet->HaveCScript(witness_id) && !pwallet->AddCScript(witness_script)) { + throw JSONRPCError(RPC_WALLET_ERROR, "Error adding p2wsh witnessScript to wallet"); + } - if (!pwallet->AddKeyPubKey(key, pubkey)) { - throw JSONRPCError(RPC_WALLET_ERROR, "Error adding key to wallet"); - } + // Now set script to the witnessScript so we parse the inner script as P2PK or P2PKH below + script = witness_script; + ExtractDestination(script, dest); + allow_p2wpkh = false; // P2WPKH cannot be embedded in P2WSH + } - pwallet->UpdateTimeFirstKey(timestamp); - } + // (P2SH-)P2PK/P2PKH/P2WPKH + if (dest.type() == typeid(CKeyID) || dest.type() == typeid(WitnessV0KeyHash)) { + if (!allow_p2wpkh && dest.type() == typeid(WitnessV0KeyHash)) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "P2WPKH cannot be embedded in P2WSH"); } - - success = true; - } else { - // Import public keys. - if (pubKeys.size() && keys.size() == 0) { + if (keys.size() > 1 || pubKeys.size() > 1) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "More than one key given for one single-key address"); + } + CPubKey pubkey; + if (keys.size()) { + pubkey = DecodeSecret(keys[0].get_str()).GetPubKey(); + } + if (pubKeys.size()) { const std::string& strPubKey = pubKeys[0].get_str(); - if (!IsHex(strPubKey)) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Pubkey must be a hex string"); } - - std::vector<unsigned char> vData(ParseHex(strPubKey)); - CPubKey pubKey(vData.begin(), vData.end()); - - if (!pubKey.IsFullyValid()) { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Pubkey is not a valid public key"); - } - - CTxDestination pubkey_dest = pubKey.GetID(); - - // Consistency check. - if (!(pubkey_dest == dest)) { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Consistency check failed"); - } - - CScript pubKeyScript = GetScriptForDestination(pubkey_dest); - - if (::IsMine(*pwallet, pubKeyScript) == ISMINE_SPENDABLE) { - throw JSONRPCError(RPC_WALLET_ERROR, "The wallet already contains the private key for this address or script"); + std::vector<unsigned char> vData(ParseHex(pubKeys[0].get_str())); + CPubKey pubkey_temp(vData.begin(), vData.end()); + if (pubkey.size() && pubkey_temp != pubkey) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Private key does not match public key for address"); } - - pwallet->MarkDirty(); - - if (!pwallet->AddWatchOnly(pubKeyScript, timestamp)) { - throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet"); + pubkey = pubkey_temp; + } + if (pubkey.size() > 0) { + if (!pubkey.IsFullyValid()) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Pubkey is not a valid public key"); } - // add to address book or update label - if (IsValidDestination(pubkey_dest)) { - pwallet->SetAddressBook(pubkey_dest, label, "receive"); + // Check the key corresponds to the destination given + std::vector<CTxDestination> destinations = GetAllDestinationsForKey(pubkey); + if (std::find(destinations.begin(), destinations.end(), dest) == destinations.end()) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Key does not match address destination"); } - // TODO Is this necessary? - CScript scriptRawPubKey = GetScriptForRawPubKey(pubKey); + // This is necessary to force the wallet to import the pubKey + CScript scriptRawPubKey = GetScriptForRawPubKey(pubkey); if (::IsMine(*pwallet, scriptRawPubKey) == ISMINE_SPENDABLE) { throw JSONRPCError(RPC_WALLET_ERROR, "The wallet already contains the private key for this address or script"); @@ -998,73 +976,61 @@ static UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, con if (!pwallet->AddWatchOnly(scriptRawPubKey, timestamp)) { throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet"); } - - success = true; } + } - // Import private keys. - if (keys.size()) { - const std::string& strPrivkey = keys[0].get_str(); - - // Checks. - CKey key = DecodeSecret(strPrivkey); - - if (!key.IsValid()) { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key encoding"); - } - - CPubKey pubKey = key.GetPubKey(); - assert(key.VerifyPubKey(pubKey)); - - CTxDestination pubkey_dest = pubKey.GetID(); + // Import the address + if (::IsMine(*pwallet, scriptpubkey_script) == ISMINE_SPENDABLE) { + throw JSONRPCError(RPC_WALLET_ERROR, "The wallet already contains the private key for this address or script"); + } - // Consistency check. - if (!(pubkey_dest == dest)) { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Consistency check failed"); - } + pwallet->MarkDirty(); - CKeyID vchAddress = pubKey.GetID(); - pwallet->MarkDirty(); - pwallet->SetAddressBook(vchAddress, label, "receive"); + if (!pwallet->AddWatchOnly(scriptpubkey_script, timestamp)) { + throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet"); + } - if (pwallet->HaveKey(vchAddress)) { - throw JSONRPCError(RPC_WALLET_ERROR, "The wallet already contains the private key for this address or script"); - } + if (!watchOnly && !pwallet->HaveCScript(CScriptID(scriptpubkey_script)) && !pwallet->AddCScript(scriptpubkey_script)) { + throw JSONRPCError(RPC_WALLET_ERROR, "Error adding scriptPubKey script to wallet"); + } - pwallet->mapKeyMetadata[vchAddress].nCreateTime = timestamp; + // add to address book or update label + if (IsValidDestination(scriptpubkey_dest)) { + pwallet->SetAddressBook(scriptpubkey_dest, label, "receive"); + } - if (!pwallet->AddKeyPubKey(key, pubKey)) { - throw JSONRPCError(RPC_WALLET_ERROR, "Error adding key to wallet"); - } + // Import private keys. + for (size_t i = 0; i < keys.size(); i++) { + const std::string& strPrivkey = keys[i].get_str(); - pwallet->UpdateTimeFirstKey(timestamp); + // Checks. + CKey key = DecodeSecret(strPrivkey); - success = true; + if (!key.IsValid()) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key encoding"); } - // Import scriptPubKey only. - if (pubKeys.size() == 0 && keys.size() == 0) { - if (::IsMine(*pwallet, script) == ISMINE_SPENDABLE) { - throw JSONRPCError(RPC_WALLET_ERROR, "The wallet already contains the private key for this address or script"); - } + CPubKey pubKey = key.GetPubKey(); + assert(key.VerifyPubKey(pubKey)); - pwallet->MarkDirty(); + CKeyID vchAddress = pubKey.GetID(); + pwallet->MarkDirty(); - if (!pwallet->AddWatchOnly(script, timestamp)) { - throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet"); - } + if (pwallet->HaveKey(vchAddress)) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Already have this key"); + } - // add to address book or update label - if (IsValidDestination(dest)) { - pwallet->SetAddressBook(dest, label, "receive"); - } + pwallet->mapKeyMetadata[vchAddress].nCreateTime = timestamp; - success = true; + if (!pwallet->AddKeyPubKey(key, pubKey)) { + throw JSONRPCError(RPC_WALLET_ERROR, "Error adding key to wallet"); } + + pwallet->UpdateTimeFirstKey(timestamp); } UniValue result = UniValue(UniValue::VOBJ); - result.pushKV("success", UniValue(success)); + result.pushKV("success", UniValue(true)); return result; } catch (const UniValue& e) { UniValue result = UniValue(UniValue::VOBJ); @@ -1117,7 +1083,8 @@ UniValue importmulti(const JSONRPCRequest& mainRequest) " \"now\" can be specified to bypass scanning, for keys which are known to never have been used, and\n" " 0 can be specified to scan the entire blockchain. Blocks up to 2 hours before the earliest key\n" " creation time of all keys being imported by the importmulti call will be scanned.\n" - " \"redeemscript\": \"<script>\" , (string, optional) Allowed only if the scriptPubKey is a P2SH address or a P2SH scriptPubKey\n" + " \"redeemscript\": \"<script>\" , (string, optional) Allowed only if the scriptPubKey is a P2SH or P2SH-P2WSH address/scriptPubKey\n" + " \"witnessscript\": \"<script>\" , (string, optional) Allowed only if the scriptPubKey is a P2SH-P2WSH or P2WSH address/scriptPubKey\n" " \"pubkeys\": [\"<pubKey>\", ... ] , (array, optional) Array of strings giving pubkeys that must occur in the output or redeemscript\n" " \"keys\": [\"<key>\", ... ] , (array, optional) Array of strings giving private keys whose corresponding public keys must occur in the output or redeemscript\n" " \"internal\": <true> , (boolean, optional, default: false) Stating whether matching outputs should be treated as not incoming payments\n" diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 8226bb85cb..45d4b5bceb 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -23,8 +23,8 @@ #include <script/sign.h> #include <shutdown.h> #include <timedata.h> -#include <util.h> -#include <utilmoneystr.h> +#include <util/system.h> +#include <util/moneystr.h> #include <wallet/coincontrol.h> #include <wallet/feebumper.h> #include <wallet/rpcwallet.h> @@ -3454,8 +3454,10 @@ UniValue getaddressinfo(const JSONRPCRequest& request) " \"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" + " \"solvable\" : true|false, (boolean) If the address is solvable by the wallet\n" " \"iswatchonly\" : true|false, (boolean) If the address is watchonly\n" " \"isscript\" : true|false, (boolean) If the key is a script\n" + " \"ischange\" : true|false, (boolean) If the address was used for change output\n" " \"iswitness\" : true|false, (boolean) If the address is a witness address\n" " \"witness_version\" : version (numeric, optional) The version number of the witness program\n" " \"witness_program\" : \"hex\" (string, optional) The hex value of the witness program\n" @@ -3508,11 +3510,13 @@ UniValue getaddressinfo(const JSONRPCRequest& request) isminetype mine = IsMine(*pwallet, dest); ret.pushKV("ismine", bool(mine & ISMINE_SPENDABLE)); ret.pushKV("iswatchonly", bool(mine & ISMINE_WATCH_ONLY)); + ret.pushKV("solvable", IsSolvable(*pwallet, scriptPubKey)); UniValue detail = DescribeWalletAddress(pwallet, dest); ret.pushKVs(detail); if (pwallet->mapAddressBook.count(dest)) { ret.pushKV("label", pwallet->mapAddressBook[dest].name); } + ret.pushKV("ischange", pwallet->IsChange(scriptPubKey)); const CKeyMetadata* meta = nullptr; CKeyID key_id = GetKeyForDestination(*pwallet, dest); if (!key_id.IsNull()) { diff --git a/src/wallet/test/psbt_wallet_tests.cpp b/src/wallet/test/psbt_wallet_tests.cpp index 34d6e1b87c..cb1ad25461 100644 --- a/src/wallet/test/psbt_wallet_tests.cpp +++ b/src/wallet/test/psbt_wallet_tests.cpp @@ -4,7 +4,7 @@ #include <key_io.h> #include <script/sign.h> -#include <utilstrencodings.h> +#include <util/strencodings.h> #include <wallet/rpcwallet.h> #include <wallet/wallet.h> #include <univalue.h> diff --git a/src/wallet/test/wallet_crypto_tests.cpp b/src/wallet/test/wallet_crypto_tests.cpp index f193d5c41d..ae7092fa89 100644 --- a/src/wallet/test/wallet_crypto_tests.cpp +++ b/src/wallet/test/wallet_crypto_tests.cpp @@ -3,7 +3,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <test/test_bitcoin.h> -#include <utilstrencodings.h> +#include <util/strencodings.h> #include <wallet/crypter.h> #include <vector> diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index dc7369df80..2ea9f45462 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -25,7 +25,7 @@ #include <shutdown.h> #include <timedata.h> #include <txmempool.h> -#include <utilmoneystr.h> +#include <util/moneystr.h> #include <wallet/fees.h> #include <algorithm> @@ -1261,6 +1261,11 @@ CAmount CWallet::GetCredit(const CTxOut& txout, const isminefilter& filter) cons bool CWallet::IsChange(const CTxOut& txout) const { + return IsChange(txout.scriptPubKey); +} + +bool CWallet::IsChange(const CScript& script) const +{ // TODO: fix handling of 'change' outputs. The assumption is that any // payment to a script that is ours, but is not in the address book // is change. That assumption is likely to break when we implement multisignature @@ -1268,10 +1273,10 @@ bool CWallet::IsChange(const CTxOut& txout) const // a better way of identifying which outputs are 'the send' and which are // 'the change' will need to be implemented (maybe extend CWalletTx to remember // which output, if any, was change). - if (::IsMine(*this, txout.scriptPubKey)) + if (::IsMine(*this, script)) { CTxDestination address; - if (!ExtractDestination(txout.scriptPubKey, address)) + if (!ExtractDestination(script, address)) return true; LOCK(cs_wallet); diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index f365a2bb3c..74eaa09506 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -12,11 +12,11 @@ #include <streams.h> #include <tinyformat.h> #include <ui_interface.h> -#include <utilstrencodings.h> +#include <util/strencodings.h> #include <validationinterface.h> #include <script/ismine.h> #include <script/sign.h> -#include <util.h> +#include <util/system.h> #include <wallet/crypter.h> #include <wallet/coinselection.h> #include <wallet/walletdb.h> @@ -969,6 +969,7 @@ public: isminetype IsMine(const CTxOut& txout) const; CAmount GetCredit(const CTxOut& txout, const isminefilter& filter) const; bool IsChange(const CTxOut& txout) const; + bool IsChange(const CScript& script) const; CAmount GetChange(const CTxOut& txout) const; bool IsMine(const CTransaction& tx) const; /** should probably be renamed to IsRelevantToMe */ diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index 5e85151358..09a33f252c 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -12,8 +12,8 @@ #include <protocol.h> #include <serialize.h> #include <sync.h> -#include <util.h> -#include <utiltime.h> +#include <util/system.h> +#include <util/time.h> #include <wallet/wallet.h> #include <atomic> diff --git a/src/wallet/walletutil.cpp b/src/wallet/walletutil.cpp index 5d236d73e1..6db4c63acb 100644 --- a/src/wallet/walletutil.cpp +++ b/src/wallet/walletutil.cpp @@ -4,7 +4,7 @@ #include <wallet/walletutil.h> -#include <util.h> +#include <util/system.h> fs::path GetWalletDir() { @@ -52,12 +52,17 @@ static bool IsBerkeleyBtree(const fs::path& path) std::vector<fs::path> ListWalletDir() { const fs::path wallet_dir = GetWalletDir(); + const size_t offset = wallet_dir.string().size() + 1; std::vector<fs::path> paths; - for (auto it = fs::recursive_directory_iterator(wallet_dir); it != end(it); ++it) { + for (auto it = fs::recursive_directory_iterator(wallet_dir); it != fs::recursive_directory_iterator(); ++it) { + // Get wallet path relative to walletdir by removing walletdir from the wallet path. + // This can be replaced by boost::filesystem::lexically_relative once boost is bumped to 1.60. + const fs::path path = it->path().string().substr(offset); + if (it->status().type() == fs::directory_file && IsBerkeleyBtree(it->path() / "wallet.dat")) { // Found a directory which contains wallet.dat btree file, add it as a wallet. - paths.emplace_back(fs::relative(it->path(), wallet_dir)); + paths.emplace_back(path); } else if (it.level() == 0 && it->symlink_status().type() == fs::regular_file && IsBerkeleyBtree(it->path())) { if (it->path().filename() == "wallet.dat") { // Found top-level wallet.dat btree file, add top level directory "" @@ -68,7 +73,7 @@ std::vector<fs::path> ListWalletDir() // software will never create these files but will allow them to be // opened in a shared database environment for backwards compatibility. // Add it to the list of available wallets. - paths.emplace_back(fs::relative(it->path(), wallet_dir)); + paths.emplace_back(path); } } } diff --git a/src/warnings.cpp b/src/warnings.cpp index 9f10c48eef..1c6ba13f60 100644 --- a/src/warnings.cpp +++ b/src/warnings.cpp @@ -5,7 +5,7 @@ #include <sync.h> #include <clientversion.h> -#include <util.h> +#include <util/system.h> #include <warnings.h> CCriticalSection cs_warnings; diff --git a/src/zmq/zmqabstractnotifier.cpp b/src/zmq/zmqabstractnotifier.cpp index 39cc8968d2..82e5ee5cc9 100644 --- a/src/zmq/zmqabstractnotifier.cpp +++ b/src/zmq/zmqabstractnotifier.cpp @@ -3,7 +3,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <zmq/zmqabstractnotifier.h> -#include <util.h> +#include <util/system.h> CZMQAbstractNotifier::~CZMQAbstractNotifier() diff --git a/src/zmq/zmqnotificationinterface.cpp b/src/zmq/zmqnotificationinterface.cpp index 1d9f86d450..df4e51ca20 100644 --- a/src/zmq/zmqnotificationinterface.cpp +++ b/src/zmq/zmqnotificationinterface.cpp @@ -8,7 +8,7 @@ #include <version.h> #include <validation.h> #include <streams.h> -#include <util.h> +#include <util/system.h> void zmqError(const char *str) { diff --git a/src/zmq/zmqpublishnotifier.cpp b/src/zmq/zmqpublishnotifier.cpp index 36a6458f67..718597e57c 100644 --- a/src/zmq/zmqpublishnotifier.cpp +++ b/src/zmq/zmqpublishnotifier.cpp @@ -7,7 +7,7 @@ #include <streams.h> #include <zmq/zmqpublishnotifier.h> #include <validation.h> -#include <util.h> +#include <util/system.h> #include <rpc/server.h> static std::multimap<std::string, CZMQAbstractPublishNotifier*> mapPublishNotifiers; diff --git a/test/functional/data/rpc_psbt.json b/test/functional/data/rpc_psbt.json index dd40a096de..57f2608ee9 100644 --- a/test/functional/data/rpc_psbt.json +++ b/test/functional/data/rpc_psbt.json @@ -17,7 +17,8 @@ "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAABB9oARzBEAiB0AYrUGACXuHMyPAAVcgs2hMyBI4kQSOfbzZtVrWecmQIgc9Npt0Dj61Pc76M4I8gHBRTKVafdlUTxV8FnkTJhEYwBSDBFAiEA9hA4swjcHahlo0hSdG8BV3KTQgjG0kRUOTzZm98iF3cCIAVuZ1pnWm0KArhbFOXikHTYolqbV2C+ooFvZhkQoAbqAUdSIQKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgfyEC2rYf9JoU22p9ArDNH7t4/EsYMStbTlTa5Nui+/71NtdSrgABASAAwusLAAAAABepFLf1+vQOPUClpFmx2zU18rcvqSHohwEHIyIAIIwjUxc3Q7WV37Sge3K6jkLjeX2nTof+fZ10l+OyAokDAQjaBABHMEQCIGLrelVhB6fHP0WsSrWh3d9vcHX7EnWWmn84Pv/3hLyyAiAMBdu3Rw2/LwhVfdNWxzJcHtMJE+mWzThAlF2xIijaXwFHMEQCIGX0W6WZi1mif/4ae+0BavHx+Q1Us6qPdFCqX1aiUQO9AiB/ckcDrR7blmgLKEtW1P/LiPf7dZ6rvgiqMPKbhROD0gFHUiEDCJ3BDHrG21T5EymvYXMz2ziM6tDCMfcjN50bmQMLAtwhAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zUq4AIQIDqaTDf1mW06ol26xrVwrwZQOUSSlCRgs1R1PtnuylhxDZDGpPAAAAgAAAAIAEAACAACICAn9jmXV9Lv9VoTatAsaEsYOLZVbl8bazQoKpS2tQBRCWENkMak8AAACAAAAAgAUAAIAA", "cHNidP8BAHMCAAAAATAa6YblFqHsisW0vGVz0y+DtGXiOtdhZ9aLOOcwtNvbAAAAAAD/////AnR7AQAAAAAAF6kUA6oXrogrXQ1Usl1jEE5P/s57nqKHYEOZOwAAAAAXqRS5IbG6b3IuS/qDtlV6MTmYakLsg4cAAAAAAAEBHwDKmjsAAAAAFgAU0tlLZK4IWH7vyO6xh8YB6Tn5A3wCAwABAAAAAAEAFgAUYunpgv/zTdgjlhAxawkM0qO3R8sAAQAiACCHa62DLx0WgBXtQSMqnqZaGBXZ7xPA74dZ9ktbKyeKZQEBJVEhA7fOI6AcW0vwCmQlN836uzFbZoMyhnR471EwnSvVf4qHUa4A", "cHNidP8BAHMCAAAAATAa6YblFqHsisW0vGVz0y+DtGXiOtdhZ9aLOOcwtNvbAAAAAAD/////AnR7AQAAAAAAF6kUA6oXrogrXQ1Usl1jEE5P/s57nqKHYEOZOwAAAAAXqRS5IbG6b3IuS/qDtlV6MTmYakLsg4cAAAAAAAEBHwDKmjsAAAAAFgAU0tlLZK4IWH7vyO6xh8YB6Tn5A3wAAgAAFgAUYunpgv/zTdgjlhAxawkM0qO3R8sAAQAiACCHa62DLx0WgBXtQSMqnqZaGBXZ7xPA74dZ9ktbKyeKZQEBJVEhA7fOI6AcW0vwCmQlN836uzFbZoMyhnR471EwnSvVf4qHUa4A", - "cHNidP8BAHMCAAAAATAa6YblFqHsisW0vGVz0y+DtGXiOtdhZ9aLOOcwtNvbAAAAAAD/////AnR7AQAAAAAAF6kUA6oXrogrXQ1Usl1jEE5P/s57nqKHYEOZOwAAAAAXqRS5IbG6b3IuS/qDtlV6MTmYakLsg4cAAAAAAAEBHwDKmjsAAAAAFgAU0tlLZK4IWH7vyO6xh8YB6Tn5A3wAAQAWABRi6emC//NN2COWEDFrCQzSo7dHywABACIAIIdrrYMvHRaAFe1BIyqeploYFdnvE8Dvh1n2S1srJ4plIQEAJVEhA7fOI6AcW0vwCmQlN836uzFbZoMyhnR471EwnSvVf4qHUa4A" + "cHNidP8BAHMCAAAAATAa6YblFqHsisW0vGVz0y+DtGXiOtdhZ9aLOOcwtNvbAAAAAAD/////AnR7AQAAAAAAF6kUA6oXrogrXQ1Usl1jEE5P/s57nqKHYEOZOwAAAAAXqRS5IbG6b3IuS/qDtlV6MTmYakLsg4cAAAAAAAEBHwDKmjsAAAAAFgAU0tlLZK4IWH7vyO6xh8YB6Tn5A3wAAQAWABRi6emC//NN2COWEDFrCQzSo7dHywABACIAIIdrrYMvHRaAFe1BIyqeploYFdnvE8Dvh1n2S1srJ4plIQEAJVEhA7fOI6AcW0vwCmQlN836uzFbZoMyhnR471EwnSvVf4qHUa4A", + "cHNidP8BAHMCAAAAAbiWoY6pOQepFsEGhUPXaulX9rvye2NH+NrdlAHg+WgpAQAAAAD/////AkBLTAAAAAAAF6kUqWwXCcLM5BN2zoNqMNT5qMlIi7+HQEtMAAAAAAAXqRSVF/in2XNxAlN1OSxkyp0z+Wtg2YcAAAAAAAEBIBNssgAAAAAAF6kUamsvautR8hRlMRY6OKNTx03DK96HAQcXFgAUo8u1LWpHprjt/uENAwBpGZD0UH0BCGsCRzBEAiAONfH3DYiw67ZbylrsxCF/XXpVwyWBRgofyRbPslzvwgIgIKCsWw5sHSIPh1icNvcVLZLHWj6NA7Dk+4Os2pOnMbQBIQPGStfYHPtyhpV7zIWtn0Q4GXv5gK1zy/tnJ+cBXu4iiwABABYAFMwmJQEz+HDpBEEabxJ5PogPsqZRAAEAFgAUyCrGc3h3FYCmiIspbv2pSTKZ5jU" ], "valid" : [ "cHNidP8BAHUCAAAAASaBcTce3/KF6Tet7qSze3gADAVmy7OtZGQXE8pCFxv2AAAAAAD+////AtPf9QUAAAAAGXapFNDFmQPFusKGh2DpD9UhpGZap2UgiKwA4fUFAAAAABepFDVF5uM7gyxHBQ8k0+65PJwDlIvHh7MuEwAAAQD9pQEBAAAAAAECiaPHHqtNIOA3G7ukzGmPopXJRjr6Ljl/hTPMti+VZ+UBAAAAFxYAFL4Y0VKpsBIDna89p95PUzSe7LmF/////4b4qkOnHf8USIk6UwpyN+9rRgi7st0tAXHmOuxqSJC0AQAAABcWABT+Pp7xp0XpdNkCxDVZQ6vLNL1TU/////8CAMLrCwAAAAAZdqkUhc/xCX/Z4Ai7NK9wnGIZeziXikiIrHL++E4sAAAAF6kUM5cluiHv1irHU6m80GfWx6ajnQWHAkcwRAIgJxK+IuAnDzlPVoMR3HyppolwuAJf3TskAinwf4pfOiQCIAGLONfc0xTnNMkna9b7QPZzMlvEuqFEyADS8vAtsnZcASED0uFWdJQbrUqZY3LLh+GFbTZSYG2YVi/jnF6efkE/IQUCSDBFAiEA0SuFLYXc2WHS9fSrZgZU327tzHlMDDPOXMMJ/7X85Y0CIGczio4OFyXBl/saiK9Z9R5E5CVbIBZ8hoQDHAXR8lkqASECI7cr7vCWXRC+B3jv7NYfysb3mk6haTkzgHNEZPhPKrMAAAAAAAAA", diff --git a/test/functional/feature_dbcrash.py b/test/functional/feature_dbcrash.py index ae1eacf2d7..70d67aa53a 100755 --- a/test/functional/feature_dbcrash.py +++ b/test/functional/feature_dbcrash.py @@ -69,6 +69,7 @@ class ChainstateWriteCrashTest(BitcoinTestFramework): def setup_network(self): self.add_nodes(self.num_nodes, extra_args=self.extra_args) self.start_nodes() + self.import_deterministic_coinbase_privkeys() # Leave them unconnected, we'll use submitblock directly in this test def restart_node(self, node_index, expected_tip): diff --git a/test/functional/feature_fee_estimation.py b/test/functional/feature_fee_estimation.py index aaab4279b5..b68e46adbc 100755 --- a/test/functional/feature_fee_estimation.py +++ b/test/functional/feature_fee_estimation.py @@ -144,6 +144,9 @@ class EstimateFeeTest(BitcoinTestFramework): # (68k weight is room enough for 120 or so transactions) # Node2 is a stingy miner, that # produces too small blocks (room for only 55 or so transactions) + self.start_nodes() + self.import_deterministic_coinbase_privkeys() + self.stop_nodes() def transact_and_mine(self, numblocks, mining_node): min_fee = Decimal("0.00001") @@ -171,11 +174,6 @@ class EstimateFeeTest(BitcoinTestFramework): newmem.append(utx) self.memutxo = newmem - def import_deterministic_coinbase_privkeys(self): - self.start_nodes() - super().import_deterministic_coinbase_privkeys() - self.stop_nodes() - def run_test(self): self.log.info("This test is time consuming, please be patient") self.log.info("Splitting inputs so we can generate tx's") diff --git a/test/functional/feature_pruning.py b/test/functional/feature_pruning.py index 772151dc4b..c820ca33e2 100755 --- a/test/functional/feature_pruning.py +++ b/test/functional/feature_pruning.py @@ -63,6 +63,8 @@ class PruneTest(BitcoinTestFramework): def setup_nodes(self): self.add_nodes(self.num_nodes, self.extra_args) self.start_nodes() + for n in self.nodes: + n.importprivkey(privkey=n.get_deterministic_priv_key().key, label='coinbase', rescan=False) def create_big_chain(self): # Start by creating some coinbases we can spend later diff --git a/test/functional/interface_zmq.py b/test/functional/interface_zmq.py index 48136a0108..12d484d7c2 100755 --- a/test/functional/interface_zmq.py +++ b/test/functional/interface_zmq.py @@ -69,6 +69,7 @@ class ZMQTest (BitcoinTestFramework): ] self.add_nodes(self.num_nodes, self.extra_args) self.start_nodes() + self.import_deterministic_coinbase_privkeys() def run_test(self): try: diff --git a/test/functional/p2p_leak_tx.py b/test/functional/p2p_leak_tx.py new file mode 100755 index 0000000000..dc4d475b2d --- /dev/null +++ b/test/functional/p2p_leak_tx.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python3 +# Copyright (c) 2017-2018 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 we don't leak txs to inbound peers that we haven't yet announced to""" + +from test_framework.messages import msg_getdata, CInv +from test_framework.mininode import P2PDataStore +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import ( + assert_equal, +) + + +class P2PNode(P2PDataStore): + def on_inv(self, msg): + pass + + +class P2PLeakTxTest(BitcoinTestFramework): + def set_test_params(self): + self.num_nodes = 1 + + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + + def run_test(self): + gen_node = self.nodes[0] # The block and tx generating node + gen_node.generate(1) + + inbound_peer = self.nodes[0].add_p2p_connection(P2PNode()) # An "attacking" inbound peer + + MAX_REPEATS = 100 + self.log.info("Running test up to {} times.".format(MAX_REPEATS)) + for i in range(MAX_REPEATS): + self.log.info('Run repeat {}'.format(i + 1)) + txid = gen_node.sendtoaddress(gen_node.getnewaddress(), 0.01) + + want_tx = msg_getdata() + want_tx.inv.append(CInv(t=1, h=int(txid, 16))) + inbound_peer.last_message.pop('notfound', None) + inbound_peer.send_message(want_tx) + inbound_peer.sync_with_ping() + + if inbound_peer.last_message.get('notfound'): + self.log.debug('tx {} was not yet announced to us.'.format(txid)) + self.log.debug("node has responded with a notfound message. End test.") + assert_equal(inbound_peer.last_message['notfound'].vec[0].hash, int(txid, 16)) + inbound_peer.last_message.pop('notfound') + break + else: + self.log.debug('tx {} was already announced to us. Try test again.'.format(txid)) + assert int(txid, 16) in [inv.hash for inv in inbound_peer.last_message['inv'].inv] + + +if __name__ == '__main__': + P2PLeakTxTest().main() diff --git a/test/functional/p2p_node_network_limited.py b/test/functional/p2p_node_network_limited.py index ec3d336dc1..359880506e 100755 --- a/test/functional/p2p_node_network_limited.py +++ b/test/functional/p2p_node_network_limited.py @@ -43,8 +43,8 @@ class NodeNetworkLimitedTest(BitcoinTestFramework): disconnect_nodes(self.nodes[1], 2) def setup_network(self): - super(NodeNetworkLimitedTest, self).setup_network() - self.disconnect_all() + self.add_nodes(self.num_nodes, self.extra_args) + self.start_nodes() def run_test(self): node = self.nodes[0].add_p2p_connection(P2PIgnoreInv()) diff --git a/test/functional/rpc_getblockstats.py b/test/functional/rpc_getblockstats.py index b24bed6adf..ca9e24367a 100755 --- a/test/functional/rpc_getblockstats.py +++ b/test/functional/rpc_getblockstats.py @@ -170,6 +170,8 @@ class GetblockstatsTest(BitcoinTestFramework): self.nodes[0].getblockstats, hash_or_height=1, stats=['minfee' , 'aaa%s' % inv_sel_stat]) assert_raises_rpc_error(-8, 'One or more of the selected stats requires -txindex enabled', + self.nodes[1].getblockstats, hash_or_height=1) + assert_raises_rpc_error(-8, 'One or more of the selected stats requires -txindex enabled', self.nodes[1].getblockstats, hash_or_height=self.start_height + self.max_stat_pos) # Mainchain's genesis block shouldn't be found on regtest diff --git a/test/functional/rpc_psbt.py b/test/functional/rpc_psbt.py index 54dc871448..fca910bf64 100755 --- a/test/functional/rpc_psbt.py +++ b/test/functional/rpc_psbt.py @@ -6,7 +6,7 @@ """ from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import assert_equal, assert_raises_rpc_error, find_output +from test_framework.util import assert_equal, assert_raises_rpc_error, find_output, disconnect_nodes, connect_nodes_bi, sync_blocks import json import os @@ -23,6 +23,45 @@ class PSBTTest(BitcoinTestFramework): def skip_test_if_missing_module(self): self.skip_if_no_wallet() + def test_utxo_conversion(self): + mining_node = self.nodes[2] + offline_node = self.nodes[0] + online_node = self.nodes[1] + + # Disconnect offline node from others + disconnect_nodes(offline_node, 1) + disconnect_nodes(online_node, 0) + disconnect_nodes(offline_node, 2) + disconnect_nodes(mining_node, 0) + + # Mine a transaction that credits the offline address + offline_addr = offline_node.getnewaddress(address_type="p2sh-segwit") + online_addr = online_node.getnewaddress(address_type="p2sh-segwit") + online_node.importaddress(offline_addr, "", False) + mining_node.sendtoaddress(address=offline_addr, amount=1.0) + mining_node.generate(nblocks=1) + sync_blocks([mining_node, online_node]) + + # Construct an unsigned PSBT on the online node (who doesn't know the output is Segwit, so will include a non-witness UTXO) + utxos = online_node.listunspent(addresses=[offline_addr]) + raw = online_node.createrawtransaction([{"txid":utxos[0]["txid"], "vout":utxos[0]["vout"]}],[{online_addr:0.9999}]) + psbt = online_node.walletprocesspsbt(online_node.converttopsbt(raw))["psbt"] + assert("non_witness_utxo" in mining_node.decodepsbt(psbt)["inputs"][0]) + + # Have the offline node sign the PSBT (which will update the UTXO to segwit) + signed_psbt = offline_node.walletprocesspsbt(psbt)["psbt"] + assert("witness_utxo" in mining_node.decodepsbt(signed_psbt)["inputs"][0]) + + # Make sure we can mine the resulting transaction + txid = mining_node.sendrawtransaction(mining_node.finalizepsbt(signed_psbt)["hex"]) + mining_node.generate(1) + sync_blocks([mining_node, online_node]) + assert_equal(online_node.gettxout(txid,0)["confirmations"], 1) + + # Reconnect + connect_nodes_bi(self.nodes, 0, 1) + connect_nodes_bi(self.nodes, 0, 2) + def run_test(self): # Create and fund a raw tx for sending 10 BTC psbtx1 = self.nodes[0].walletcreatefundedpsbt([], {self.nodes[2].getnewaddress():10})['psbt'] @@ -224,6 +263,12 @@ class PSBTTest(BitcoinTestFramework): extracted = self.nodes[2].finalizepsbt(extractor['extract'], True)['hex'] assert_equal(extracted, extractor['result']) + # Unload extra wallets + for i, signer in enumerate(signers): + self.nodes[2].unloadwallet("wallet{}".format(i)) + + self.test_utxo_conversion() + if __name__ == '__main__': PSBTTest().main() diff --git a/test/functional/test_framework/blocktools.py b/test/functional/test_framework/blocktools.py index 35004fb588..81cce1167b 100644 --- a/test/functional/test_framework/blocktools.py +++ b/test/functional/test_framework/blocktools.py @@ -169,7 +169,7 @@ def get_legacy_sigopcount_tx(tx, accurate=True): return count def witness_script(use_p2wsh, pubkey): - """Create a scriptPubKey for a pay-to-wtiness TxOut. + """Create a scriptPubKey for a pay-to-witness TxOut. This is 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 diff --git a/test/functional/test_framework/messages.py b/test/functional/test_framework/messages.py index 8e9372767d..92acbb9a09 100755 --- a/test/functional/test_framework/messages.py +++ b/test/functional/test_framework/messages.py @@ -1232,6 +1232,23 @@ class msg_mempool: return "msg_mempool()" +class msg_notfound: + __slots__ = ("vec", ) + command = b"notfound" + + def __init__(self, vec=None): + self.vec = vec or [] + + def deserialize(self, f): + self.vec = deser_vector(f, CInv) + + def serialize(self): + return ser_vector(self.vec) + + def __repr__(self): + return "msg_notfound(vec=%s)" % (repr(self.vec)) + + class msg_sendheaders: __slots__ = () command = b"sendheaders" diff --git a/test/functional/test_framework/mininode.py b/test/functional/test_framework/mininode.py index 6864e8a838..91fde136de 100755 --- a/test/functional/test_framework/mininode.py +++ b/test/functional/test_framework/mininode.py @@ -21,7 +21,38 @@ import struct import sys import threading -from test_framework.messages import CBlockHeader, MIN_VERSION_SUPPORTED, msg_addr, msg_block, MSG_BLOCK, msg_blocktxn, msg_cmpctblock, msg_feefilter, msg_getaddr, msg_getblocks, msg_getblocktxn, msg_getdata, msg_getheaders, msg_headers, msg_inv, msg_mempool, msg_ping, msg_pong, msg_reject, msg_sendcmpct, msg_sendheaders, msg_tx, MSG_TX, MSG_TYPE_MASK, msg_verack, msg_version, NODE_NETWORK, NODE_WITNESS, sha256 +from test_framework.messages import ( + CBlockHeader, + MIN_VERSION_SUPPORTED, + msg_addr, + msg_block, + MSG_BLOCK, + msg_blocktxn, + msg_cmpctblock, + msg_feefilter, + msg_getaddr, + msg_getblocks, + msg_getblocktxn, + msg_getdata, + msg_getheaders, + msg_headers, + msg_inv, + msg_mempool, + msg_notfound, + msg_ping, + msg_pong, + msg_reject, + msg_sendcmpct, + msg_sendheaders, + msg_tx, + MSG_TX, + MSG_TYPE_MASK, + msg_verack, + msg_version, + NODE_NETWORK, + NODE_WITNESS, + sha256, +) from test_framework.util import wait_until logger = logging.getLogger("TestFramework.mininode") @@ -40,6 +71,7 @@ MESSAGEMAP = { b"headers": msg_headers, b"inv": msg_inv, b"mempool": msg_mempool, + b"notfound": msg_notfound, b"ping": msg_ping, b"pong": msg_pong, b"reject": msg_reject, @@ -295,6 +327,7 @@ class P2PInterface(P2PConnection): def on_getheaders(self, message): pass def on_headers(self, message): pass def on_mempool(self, message): pass + def on_notfound(self, message): pass def on_pong(self, message): pass def on_reject(self, message): pass def on_sendcmpct(self, message): pass diff --git a/test/functional/test_framework/test_framework.py b/test/functional/test_framework/test_framework.py index 7e2ec673df..44fc185e6d 100755 --- a/test/functional/test_framework/test_framework.py +++ b/test/functional/test_framework/test_framework.py @@ -168,7 +168,6 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass): self.skip_test_if_missing_module() self.setup_chain() self.setup_network() - self.import_deterministic_coinbase_privkeys() self.run_test() success = TestStatus.PASSED except JSONRPCException as e: @@ -261,11 +260,9 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass): extra_args = self.extra_args self.add_nodes(self.num_nodes, extra_args) self.start_nodes() + self.import_deterministic_coinbase_privkeys() def import_deterministic_coinbase_privkeys(self): - if self.setup_clean_chain: - return - for n in self.nodes: try: n.getwalletinfo() @@ -273,7 +270,7 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass): assert str(e).startswith('Method not found') continue - n.importprivkey(n.get_deterministic_priv_key().key) + n.importprivkey(privkey=n.get_deterministic_priv_key().key, label='coinbase') def run_test(self): """Tests must override this method to define test logic""" diff --git a/test/functional/test_framework/test_node.py b/test/functional/test_framework/test_node.py index cc1bfabbfa..3a6107bb37 100755 --- a/test/functional/test_framework/test_node.py +++ b/test/functional/test_framework/test_node.py @@ -199,21 +199,6 @@ class TestNode(): def generate(self, nblocks, maxtries=1000000): self.log.debug("TestNode.generate() dispatches `generate` call to `generatetoaddress`") - # Try to import the node's deterministic private key. This is a no-op if the private key - # has already been imported. - try: - self.rpc.importprivkey(privkey=self.get_deterministic_priv_key().key, label='coinbase', rescan=False) - except JSONRPCException as e: - # This may fail if: - # - wallet is disabled ('Method not found') - # - there are multiple wallets to import to ('Wallet file not specified') - # - wallet is locked ('Error: Please enter the wallet passphrase with walletpassphrase first') - # Just ignore those errors. We can make this tidier by importing the privkey during TestFramework.setup_nodes - # TODO: tidy up deterministic privkey import. - assert str(e).startswith('Method not found') or \ - str(e).startswith('Wallet file not specified') or \ - str(e).startswith('Error: Please enter the wallet passphrase with walletpassphrase first') - return self.generatetoaddress(nblocks=nblocks, address=self.get_deterministic_priv_key().address, maxtries=maxtries) def get_wallet_rpc(self, wallet_name): diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py index c1dcc46e23..8cbc9655c6 100755 --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -68,9 +68,6 @@ if os.name != 'nt' or sys.getwindowsversion() >= (10, 0, 14393): TEST_EXIT_PASSED = 0 TEST_EXIT_SKIPPED = 77 -# 20 minutes represented in seconds -TRAVIS_TIMEOUT_DURATION = 20 * 60 - BASE_SCRIPTS = [ # Scripts that are run by the travis build process. # Longest test should go first, to favor running tests in parallel @@ -152,6 +149,7 @@ BASE_SCRIPTS = [ 'feature_versionbits_warning.py', 'rpc_preciousblock.py', 'wallet_importprunedfunds.py', + 'p2p_leak_tx.py', 'rpc_signmessage.py', 'feature_nulldummy.py', 'mempool_accept.py', @@ -215,13 +213,14 @@ def main(): 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('--ci', action='store_true', help='Run checks and code that are usually only enabled in a continuous integration environment') 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') parser.add_argument('--force', '-f', action='store_true', help='run tests even on platforms where they are disabled by default (e.g. windows).') parser.add_argument('--help', '-h', '-?', action='store_true', help='print help text and exit') parser.add_argument('--jobs', '-j', type=int, default=4, help='how many test scripts to run in parallel. Default=4.') parser.add_argument('--keepcache', '-k', action='store_true', help='the default behavior is to flush the cache directory on startup. --keepcache retains the cache from the previous testrun.') - parser.add_argument('--quiet', '-q', action='store_true', help='only print results summary and failure logs') + parser.add_argument('--quiet', '-q', action='store_true', help='only print dots, results summary and failure logs') parser.add_argument('--tmpdirprefix', '-t', default=tempfile.gettempdir(), help="Root directory for datadirs") parser.add_argument('--failfast', action='store_true', help='stop execution after the first test failure') args, unknown_args = parser.parse_known_args() @@ -305,26 +304,26 @@ def main(): subprocess.check_call([sys.executable, os.path.join(config["environment"]["SRCDIR"], 'test', 'functional', test_list[0].split()[0]), '-h']) sys.exit(0) - check_script_list(config["environment"]["SRCDIR"]) + check_script_list(src_dir=config["environment"]["SRCDIR"], fail_on_warn=args.ci) 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"], - tmpdir, + test_list=test_list, + src_dir=config["environment"]["SRCDIR"], + build_dir=config["environment"]["BUILDDIR"], + tmpdir=tmpdir, jobs=args.jobs, enable_coverage=args.coverage, args=passon_args, combined_logs_len=args.combinedlogslen, failfast=args.failfast, - level=logging_level + runs_ci=args.ci, ) -def run_tests(test_list, src_dir, build_dir, tmpdir, jobs=1, enable_coverage=False, args=None, combined_logs_len=0, failfast=False, level=logging.DEBUG): +def run_tests(*, test_list, src_dir, build_dir, tmpdir, jobs=1, enable_coverage=False, args=None, combined_logs_len=0, failfast=False, runs_ci): args = args or [] # Warn if bitcoind is already running (unix only) @@ -359,7 +358,14 @@ def run_tests(test_list, src_dir, build_dir, tmpdir, jobs=1, enable_coverage=Fal raise #Run Tests - job_queue = TestHandler(jobs, tests_dir, tmpdir, test_list, flags, level) + job_queue = TestHandler( + num_tests_parallel=jobs, + tests_dir=tests_dir, + tmpdir=tmpdir, + test_list=test_list, + flags=flags, + timeout_duration=20 * 60 if runs_ci else float('inf'), # in seconds + ) start_time = time.time() test_results = [] @@ -440,14 +446,14 @@ class TestHandler: Trigger the test scripts passed in via the list. """ - def __init__(self, num_tests_parallel, tests_dir, tmpdir, test_list=None, flags=None, logging_level=logging.DEBUG): - assert(num_tests_parallel >= 1) + def __init__(self, *, num_tests_parallel, tests_dir, tmpdir, test_list, flags, timeout_duration): + assert num_tests_parallel >= 1 self.num_jobs = num_tests_parallel self.tests_dir = tests_dir self.tmpdir = tmpdir + self.timeout_duration = timeout_duration self.test_list = test_list self.flags = flags - self.logging_level = logging_level self.num_running = 0 self.jobs = [] @@ -480,7 +486,7 @@ class TestHandler: time.sleep(.5) for job in self.jobs: (name, start_time, proc, testdir, log_out, log_err) = job - if os.getenv('TRAVIS') == 'true' and int(time.time() - start_time) > TRAVIS_TIMEOUT_DURATION: + if int(time.time() - start_time) > self.timeout_duration: # In travis, timeout individual tests (to stop tests hanging and not providing useful output). proc.send_signal(signal.SIGINT) if proc.poll() is not None: @@ -495,14 +501,12 @@ class TestHandler: status = "Failed" self.num_running -= 1 self.jobs.remove(job) - if self.logging_level == logging.DEBUG: - clearline = '\r' + (' ' * dot_count) + '\r' - print(clearline, end='', flush=True) - dot_count = 0 + clearline = '\r' + (' ' * dot_count) + '\r' + print(clearline, end='', flush=True) + dot_count = 0 return TestResult(name, status, int(time.time() - start_time)), testdir, stdout, stderr - if self.logging_level == logging.DEBUG: - print('.', end='', flush=True) - dot_count += 1 + print('.', end='', flush=True) + dot_count += 1 def kill_and_join(self): """Send SIGKILL to all jobs and block until all have ended.""" @@ -560,7 +564,7 @@ def check_script_prefixes(): raise AssertionError("Some tests are not following naming convention!") -def check_script_list(src_dir): +def check_script_list(*, src_dir, fail_on_warn): """Check scripts directory. Check that there are no scripts in the functional tests directory which are @@ -570,10 +574,11 @@ def check_script_list(src_dir): missed_tests = list(python_files - set(map(lambda x: x.split()[0], ALL_SCRIPTS + NON_SCRIPTS))) if len(missed_tests) != 0: print("%sWARNING!%s The following scripts are not being run: %s. Check the test lists in test_runner.py." % (BOLD[1], BOLD[0], str(missed_tests))) - if os.getenv('TRAVIS') == 'true': + if fail_on_warn: # On travis this warning is an error to prevent merging incomplete commits into master sys.exit(1) + class RPCCoverage(): """ Coverage reporting utilities for test_runner. diff --git a/test/functional/wallet_basic.py b/test/functional/wallet_basic.py index 4de3356d79..c9b40905f0 100755 --- a/test/functional/wallet_basic.py +++ b/test/functional/wallet_basic.py @@ -28,10 +28,9 @@ class WalletTest(BitcoinTestFramework): self.skip_if_no_wallet() def setup_network(self): - self.add_nodes(4) - self.start_node(0) - self.start_node(1) - self.start_node(2) + self.setup_nodes() + # Only need nodes 0-2 running at start of test + self.stop_node(3) connect_nodes_bi(self.nodes, 0, 1) connect_nodes_bi(self.nodes, 1, 2) connect_nodes_bi(self.nodes, 0, 2) @@ -480,7 +479,7 @@ class WalletTest(BitcoinTestFramework): # Verify nothing new in wallet assert_equal(total_txs, len(self.nodes[0].listtransactions("*", 99999))) - # Test getaddressinfo. Note that these addresses are taken from disablewallet.py + # Test getaddressinfo on external address. Note that these addresses are taken from disablewallet.py assert_raises_rpc_error(-5, "Invalid address", self.nodes[0].getaddressinfo, "3J98t1WpEZ73CNmQviecrnyiWrnqRhWNLy") address_info = self.nodes[0].getaddressinfo("mneYUmWYsuk7kySiURxCi3AGxrAqZxLgPZ") assert_equal(address_info['address'], "mneYUmWYsuk7kySiURxCi3AGxrAqZxLgPZ") @@ -488,6 +487,22 @@ class WalletTest(BitcoinTestFramework): assert not address_info["ismine"] assert not address_info["iswatchonly"] assert not address_info["isscript"] + assert not address_info["ischange"] + + # Test getaddressinfo 'ischange' field on change address. + self.nodes[0].generate(1) + destination = self.nodes[1].getnewaddress() + txid = self.nodes[0].sendtoaddress(destination, 0.123) + tx = self.nodes[0].decoderawtransaction(self.nodes[0].getrawtransaction(txid)) + output_addresses = [vout['scriptPubKey']['addresses'][0] for vout in tx["vout"]] + assert len(output_addresses) > 1 + for address in output_addresses: + ischange = self.nodes[0].getaddressinfo(address)['ischange'] + assert_equal(ischange, address != destination) + if ischange: + change = address + self.nodes[0].setlabel(change, 'foobar') + assert_equal(self.nodes[0].getaddressinfo(change)['ischange'], False) if __name__ == '__main__': WalletTest().main() diff --git a/test/functional/wallet_import_rescan.py b/test/functional/wallet_import_rescan.py index f043a544fc..08809a688a 100755 --- a/test/functional/wallet_import_rescan.py +++ b/test/functional/wallet_import_rescan.py @@ -122,16 +122,14 @@ class ImportRescanTest(BitcoinTestFramework): # Import keys with pruning disabled self.start_nodes(extra_args=[[]] * self.num_nodes) - super().import_deterministic_coinbase_privkeys() + for n in self.nodes: + n.importprivkey(privkey=n.get_deterministic_priv_key().key, label='coinbase') self.stop_nodes() self.start_nodes() for i in range(1, self.num_nodes): connect_nodes(self.nodes[i], 0) - def import_deterministic_coinbase_privkeys(self): - pass - def run_test(self): # Create one transaction on node 0 with a unique amount for # each possible type of wallet import RPC. diff --git a/test/functional/wallet_importmulti.py b/test/functional/wallet_importmulti.py index f78ff19791..9ba6860306 100755 --- a/test/functional/wallet_importmulti.py +++ b/test/functional/wallet_importmulti.py @@ -11,8 +11,14 @@ from test_framework.util import ( assert_greater_than, assert_raises_rpc_error, bytes_to_hex_str, + hex_str_to_bytes ) - +from test_framework.script import ( + CScript, + OP_0, + hash160 +) +from test_framework.messages import sha256 class ImportMultiTest(BitcoinTestFramework): def set_test_params(self): @@ -90,6 +96,19 @@ class ImportMultiTest(BitcoinTestFramework): assert_equal(address_assert['ismine'], False) assert_equal(address_assert['timestamp'], timestamp) + # ScriptPubKey + internal + label + self.log.info("Should not allow a label to be specified when internal is true") + address = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress()) + result = self.nodes[1].importmulti([{ + "scriptPubKey": address['scriptPubKey'], + "timestamp": "now", + "internal": True, + "label": "Example label" + }]) + assert_equal(result[0]['success'], False) + assert_equal(result[0]['error']['code'], -8) + assert_equal(result[0]['error']['message'], 'Internal addresses should not have a label') + # Nonstandard scriptPubKey + !internal self.log.info("Should not import a nonstandard scriptPubKey without internal flag") nonstandardScriptPubKey = address['scriptPubKey'] + bytes_to_hex_str(script.CScript([script.OP_NOP])) @@ -198,7 +217,7 @@ class ImportMultiTest(BitcoinTestFramework): }]) assert_equal(result[0]['success'], False) assert_equal(result[0]['error']['code'], -8) - assert_equal(result[0]['error']['message'], 'Incompatibility found between watchonly and keys') + assert_equal(result[0]['error']['message'], 'Watch-only addresses should not include private keys') address_assert = self.nodes[1].getaddressinfo(address['address']) assert_equal(address_assert['iswatchonly'], False) assert_equal(address_assert['ismine'], False) @@ -339,7 +358,7 @@ class ImportMultiTest(BitcoinTestFramework): }]) assert_equal(result[0]['success'], False) assert_equal(result[0]['error']['code'], -8) - assert_equal(result[0]['error']['message'], 'Incompatibility found between watchonly and keys') + assert_equal(result[0]['error']['message'], 'Watch-only addresses should not include private keys') # Address + Public key + !Internal + Wrong pubkey @@ -355,7 +374,7 @@ class ImportMultiTest(BitcoinTestFramework): }]) assert_equal(result[0]['success'], False) assert_equal(result[0]['error']['code'], -5) - assert_equal(result[0]['error']['message'], 'Consistency check failed') + assert_equal(result[0]['error']['message'], 'Key does not match address destination') address_assert = self.nodes[1].getaddressinfo(address['address']) assert_equal(address_assert['iswatchonly'], False) assert_equal(address_assert['ismine'], False) @@ -375,7 +394,7 @@ class ImportMultiTest(BitcoinTestFramework): result = self.nodes[1].importmulti(request) assert_equal(result[0]['success'], False) assert_equal(result[0]['error']['code'], -5) - assert_equal(result[0]['error']['message'], 'Consistency check failed') + assert_equal(result[0]['error']['message'], 'Key does not match address destination') address_assert = self.nodes[1].getaddressinfo(address['address']) assert_equal(address_assert['iswatchonly'], False) assert_equal(address_assert['ismine'], False) @@ -395,7 +414,7 @@ class ImportMultiTest(BitcoinTestFramework): }]) assert_equal(result[0]['success'], False) assert_equal(result[0]['error']['code'], -5) - assert_equal(result[0]['error']['message'], 'Consistency check failed') + assert_equal(result[0]['error']['message'], 'Key does not match address destination') address_assert = self.nodes[1].getaddressinfo(address['address']) assert_equal(address_assert['iswatchonly'], False) assert_equal(address_assert['ismine'], False) @@ -414,7 +433,7 @@ class ImportMultiTest(BitcoinTestFramework): }]) assert_equal(result[0]['success'], False) assert_equal(result[0]['error']['code'], -5) - assert_equal(result[0]['error']['message'], 'Consistency check failed') + assert_equal(result[0]['error']['message'], 'Key does not match address destination') address_assert = self.nodes[1].getaddressinfo(address['address']) assert_equal(address_assert['iswatchonly'], False) assert_equal(address_assert['ismine'], False) @@ -458,6 +477,147 @@ class ImportMultiTest(BitcoinTestFramework): "timestamp": "", }]) + # Import P2WPKH address as watch only + self.log.info("Should import a P2WPKH address as watch only") + address = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress(address_type="bech32")) + result = self.nodes[1].importmulti([{ + "scriptPubKey": { + "address": address['address'] + }, + "timestamp": "now", + }]) + assert_equal(result[0]['success'], True) + address_assert = self.nodes[1].getaddressinfo(address['address']) + assert_equal(address_assert['iswatchonly'], True) + assert_equal(address_assert['solvable'], False) + + # Import P2WPKH address with public key but no private key + self.log.info("Should import a P2WPKH address and public key as solvable but not spendable") + address = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress(address_type="bech32")) + result = self.nodes[1].importmulti([{ + "scriptPubKey": { + "address": address['address'] + }, + "timestamp": "now", + "pubkeys": [ address['pubkey'] ] + }]) + assert_equal(result[0]['success'], True) + address_assert = self.nodes[1].getaddressinfo(address['address']) + assert_equal(address_assert['ismine'], False) + assert_equal(address_assert['solvable'], True) + + # Import P2WPKH address with key and check it is spendable + self.log.info("Should import a P2WPKH address with key") + address = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress(address_type="bech32")) + result = self.nodes[1].importmulti([{ + "scriptPubKey": { + "address": address['address'] + }, + "timestamp": "now", + "keys": [self.nodes[0].dumpprivkey(address['address'])] + }]) + assert_equal(result[0]['success'], True) + address_assert = self.nodes[1].getaddressinfo(address['address']) + assert_equal(address_assert['iswatchonly'], False) + assert_equal(address_assert['ismine'], True) + + # P2WSH multisig address without scripts or keys + sig_address_1 = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress()) + sig_address_2 = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress()) + multi_sig_script = self.nodes[0].addmultisigaddress(2, [sig_address_1['pubkey'], sig_address_2['pubkey']], "", "bech32") + self.log.info("Should import a p2wsh multisig as watch only without respective redeem script and private keys") + result = self.nodes[1].importmulti([{ + "scriptPubKey": { + "address": multi_sig_script['address'] + }, + "timestamp": "now" + }]) + assert_equal(result[0]['success'], True) + address_assert = self.nodes[1].getaddressinfo(multi_sig_script['address']) + assert_equal(address_assert['solvable'], False) + + # Same P2WSH multisig address as above, but now with witnessscript + private keys + self.log.info("Should import a p2wsh with respective redeem script and private keys") + result = self.nodes[1].importmulti([{ + "scriptPubKey": { + "address": multi_sig_script['address'] + }, + "timestamp": "now", + "witnessscript": multi_sig_script['redeemScript'], + "keys": [ self.nodes[0].dumpprivkey(sig_address_1['address']), self.nodes[0].dumpprivkey(sig_address_2['address']) ] + }]) + assert_equal(result[0]['success'], True) + address_assert = self.nodes[1].getaddressinfo(multi_sig_script['address']) + assert_equal(address_assert['solvable'], True) + assert_equal(address_assert['ismine'], True) + assert_equal(address_assert['sigsrequired'], 2) + + # P2SH-P2WPKH address with no redeemscript or public or private key + sig_address_1 = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress(address_type="p2sh-segwit")) + pubkeyhash = hash160(hex_str_to_bytes(sig_address_1['pubkey'])) + pkscript = CScript([OP_0, pubkeyhash]) + self.log.info("Should import a p2sh-p2wpkh without redeem script or keys") + result = self.nodes[1].importmulti([{ + "scriptPubKey": { + "address": sig_address_1['address'] + }, + "timestamp": "now" + }]) + assert_equal(result[0]['success'], True) + address_assert = self.nodes[1].getaddressinfo(sig_address_1['address']) + assert_equal(address_assert['solvable'], False) + assert_equal(address_assert['ismine'], False) + + # P2SH-P2WPKH address + redeemscript + public key with no private key + self.log.info("Should import a p2sh-p2wpkh with respective redeem script and pubkey as solvable") + result = self.nodes[1].importmulti([{ + "scriptPubKey": { + "address": sig_address_1['address'] + }, + "timestamp": "now", + "redeemscript": bytes_to_hex_str(pkscript), + "pubkeys": [ sig_address_1['pubkey'] ] + }]) + assert_equal(result[0]['success'], True) + address_assert = self.nodes[1].getaddressinfo(sig_address_1['address']) + assert_equal(address_assert['solvable'], True) + assert_equal(address_assert['ismine'], False) + + # P2SH-P2WPKH address + redeemscript + private key + sig_address_1 = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress(address_type="p2sh-segwit")) + pubkeyhash = hash160(hex_str_to_bytes(sig_address_1['pubkey'])) + pkscript = CScript([OP_0, pubkeyhash]) + self.log.info("Should import a p2sh-p2wpkh with respective redeem script and private keys") + result = self.nodes[1].importmulti([{ + "scriptPubKey": { + "address": sig_address_1['address'] + }, + "timestamp": "now", + "redeemscript": bytes_to_hex_str(pkscript), + "keys": [ self.nodes[0].dumpprivkey(sig_address_1['address'])] + }]) + assert_equal(result[0]['success'], True) + address_assert = self.nodes[1].getaddressinfo(sig_address_1['address']) + assert_equal(address_assert['solvable'], True) + assert_equal(address_assert['ismine'], True) + + # P2SH-P2WSH 1-of-1 multisig + redeemscript with no private key + sig_address_1 = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress()) + multi_sig_script = self.nodes[0].addmultisigaddress(1, [sig_address_1['pubkey']], "", "p2sh-segwit") + scripthash = sha256(hex_str_to_bytes(multi_sig_script['redeemScript'])) + redeem_script = CScript([OP_0, scripthash]) + self.log.info("Should import a p2sh-p2wsh with respective redeem script but no private key") + result = self.nodes[1].importmulti([{ + "scriptPubKey": { + "address": multi_sig_script['address'] + }, + "timestamp": "now", + "redeemscript": bytes_to_hex_str(redeem_script), + "witnessscript": multi_sig_script['redeemScript'] + }]) + assert_equal(result[0]['success'], True) + address_assert = self.nodes[1].getaddressinfo(multi_sig_script['address']) + assert_equal(address_assert['solvable'], True) if __name__ == '__main__': ImportMultiTest ().main () diff --git a/test/functional/wallet_listreceivedby.py b/test/functional/wallet_listreceivedby.py index 9e8667c600..011975e371 100755 --- a/test/functional/wallet_listreceivedby.py +++ b/test/functional/wallet_listreceivedby.py @@ -18,11 +18,6 @@ class ReceivedByTest(BitcoinTestFramework): def set_test_params(self): self.num_nodes = 2 - def import_deterministic_coinbase_privkeys(self): - assert_equal(0, len(self.nodes[1].listreceivedbyaddress(minconf=0, include_empty=True, include_watchonly=True))) - super().import_deterministic_coinbase_privkeys() - self.num_cb_reward_addresses = len(self.nodes[1].listreceivedbyaddress(minconf=0, include_empty=True, include_watchonly=True)) - def skip_test_if_missing_module(self): self.skip_if_no_wallet() @@ -31,6 +26,9 @@ class ReceivedByTest(BitcoinTestFramework): self.nodes[0].generate(1) sync_blocks(self.nodes) + # save the number of coinbase reward addresses so far + num_cb_reward_addresses = len(self.nodes[1].listreceivedbyaddress(minconf=0, include_empty=True, include_watchonly=True)) + self.log.info("listreceivedbyaddress Test") # Send from node 0 to 1 @@ -76,7 +74,7 @@ class ReceivedByTest(BitcoinTestFramework): assert_raises_rpc_error(-4, "address_filter parameter was invalid", self.nodes[1].listreceivedbyaddress, minconf=0, include_empty=True, include_watchonly=True, address_filter="bamboozling") # Another address receive money res = self.nodes[1].listreceivedbyaddress(0, True, True) - assert_equal(len(res), 2 + self.num_cb_reward_addresses) # Right now 2 entries + assert_equal(len(res), 2 + num_cb_reward_addresses) # Right now 2 entries other_addr = self.nodes[1].getnewaddress() txid2 = self.nodes[0].sendtoaddress(other_addr, 0.1) self.nodes[0].generate(1) @@ -93,7 +91,7 @@ class ReceivedByTest(BitcoinTestFramework): assert_equal(len(res), 1) # Should be two entries though without filter res = self.nodes[1].listreceivedbyaddress(0, True, True) - assert_equal(len(res), 3 + self.num_cb_reward_addresses) # Became 3 entries + assert_equal(len(res), 3 + num_cb_reward_addresses) # Became 3 entries # Not on random addr other_addr = self.nodes[0].getnewaddress() # note on node[0]! just a random addr diff --git a/test/functional/wallet_multiwallet.py b/test/functional/wallet_multiwallet.py index 6a95ca4321..4f663c82c7 100755 --- a/test/functional/wallet_multiwallet.py +++ b/test/functional/wallet_multiwallet.py @@ -71,7 +71,7 @@ class MultiWalletTest(BitcoinTestFramework): wallet_names = ['w1', 'w2', 'w3', 'w', 'sub/w5', os.path.join(self.options.tmpdir, 'extern/w6'), 'w7_symlink', 'w8', ''] extra_args = ['-wallet={}'.format(n) for n in wallet_names] self.start_node(0, extra_args) - assert_equal(set(map(lambda w: w['name'], self.nodes[0].listwalletdir()['wallets'])), set(['', 'w3', 'w2', os.path.join('sub', 'w5'), 'w7', 'w7', 'w1', 'w8', 'w'])) + assert_equal(sorted(map(lambda w: w['name'], self.nodes[0].listwalletdir()['wallets'])), ['', os.path.join('sub', 'w5'), 'w', 'w1', 'w2', 'w3', 'w7', 'w7_symlink', 'w8']) assert_equal(set(node.listwallets()), set(wallet_names)) @@ -144,7 +144,7 @@ class MultiWalletTest(BitcoinTestFramework): self.restart_node(0, extra_args) - assert_equal(set(map(lambda w: w['name'], self.nodes[0].listwalletdir()['wallets'])), set(['', 'w3', 'w2', os.path.join('sub', 'w5'), 'w7', 'w7', 'w8_copy', 'w1', 'w8', 'w'])) + assert_equal(sorted(map(lambda w: w['name'], self.nodes[0].listwalletdir()['wallets'])), ['', os.path.join('sub', 'w5'), 'w', 'w1', 'w2', 'w3', 'w7', 'w7_symlink', 'w8', 'w8_copy']) wallets = [wallet(w) for w in wallet_names] wallet_bad = wallet("bad") @@ -291,7 +291,7 @@ class MultiWalletTest(BitcoinTestFramework): assert_equal(self.nodes[0].listwallets(), ['w1']) assert_equal(w1.getwalletinfo()['walletname'], 'w1') - assert_equal(set(map(lambda w: w['name'], self.nodes[0].listwalletdir()['wallets'])), set(['', 'w3', 'w2', os.path.join('sub', 'w5'), 'w7', 'w9', 'w7', 'w8_copy', 'w1', 'w8', 'w'])) + assert_equal(sorted(map(lambda w: w['name'], self.nodes[0].listwalletdir()['wallets'])), ['', os.path.join('sub', 'w5'), 'w', 'w1', 'w2', 'w3', 'w7', 'w7_symlink', 'w8', 'w8_copy', 'w9']) # Test backing up and restoring wallets self.log.info("Test wallet backup") diff --git a/test/lint/lint-circular-dependencies.sh b/test/lint/lint-circular-dependencies.sh index adb7a0c577..be67cbed31 100755 --- a/test/lint/lint-circular-dependencies.sh +++ b/test/lint/lint-circular-dependencies.sh @@ -9,7 +9,7 @@ export LC_ALL=C EXPECTED_CIRCULAR_DEPENDENCIES=( - "chainparamsbase -> util -> chainparamsbase" + "chainparamsbase -> util/system -> chainparamsbase" "checkpoints -> validation -> checkpoints" "index/txindex -> validation -> index/txindex" "policy/fees -> txmempool -> policy/fees" diff --git a/test/lint/lint-format-strings.py b/test/lint/lint-format-strings.py index 2fb35fd8ca..5caebf3739 100755 --- a/test/lint/lint-format-strings.py +++ b/test/lint/lint-format-strings.py @@ -16,8 +16,8 @@ FALSE_POSITIVES = [ ("src/dbwrapper.cpp", "vsnprintf(p, limit - p, format, backup_ap)"), ("src/index/base.cpp", "FatalError(const char* fmt, const Args&... args)"), ("src/netbase.cpp", "LogConnectFailure(bool manual_connection, const char* fmt, const Args&... args)"), - ("src/util.cpp", "strprintf(_(COPYRIGHT_HOLDERS), _(COPYRIGHT_HOLDERS_SUBSTITUTION))"), - ("src/util.cpp", "strprintf(COPYRIGHT_HOLDERS, COPYRIGHT_HOLDERS_SUBSTITUTION)"), + ("src/util/system.cpp", "strprintf(_(COPYRIGHT_HOLDERS), _(COPYRIGHT_HOLDERS_SUBSTITUTION))"), + ("src/util/system.cpp", "strprintf(COPYRIGHT_HOLDERS, COPYRIGHT_HOLDERS_SUBSTITUTION)"), ("src/wallet/wallet.h", "WalletLogPrintf(std::string fmt, Params... parameters)"), ("src/wallet/wallet.h", "LogPrintf((\"%s \" + fmt).c_str(), GetDisplayName(), parameters...)"), ("src/logging.h", "LogPrintf(const char* fmt, const Args&... args)"), diff --git a/test/lint/lint-locale-dependence.sh b/test/lint/lint-locale-dependence.sh index cbee437c91..44170a6b5a 100755 --- a/test/lint/lint-locale-dependence.sh +++ b/test/lint/lint-locale-dependence.sh @@ -2,7 +2,6 @@ export LC_ALL=C KNOWN_VIOLATIONS=( - "src/base58.cpp:.*isspace" "src/bitcoin-tx.cpp.*stoul" "src/bitcoin-tx.cpp.*trim_right" "src/bitcoin-tx.cpp:.*atoi" @@ -18,20 +17,17 @@ KNOWN_VIOLATIONS=( "src/test/getarg_tests.cpp.*split" "src/torcontrol.cpp:.*atoi" "src/torcontrol.cpp:.*strtol" - "src/uint256.cpp:.*isspace" "src/uint256.cpp:.*tolower" - "src/util.cpp:.*atoi" - "src/util.cpp:.*fprintf" - "src/util.cpp:.*tolower" - "src/utilmoneystr.cpp:.*isdigit" - "src/utilmoneystr.cpp:.*isspace" - "src/utilstrencodings.cpp:.*atoi" - "src/utilstrencodings.cpp:.*isspace" - "src/utilstrencodings.cpp:.*strtol" - "src/utilstrencodings.cpp:.*strtoll" - "src/utilstrencodings.cpp:.*strtoul" - "src/utilstrencodings.cpp:.*strtoull" - "src/utilstrencodings.h:.*atoi" + "src/util/system.cpp:.*atoi" + "src/util/system.cpp:.*fprintf" + "src/util/system.cpp:.*tolower" + "src/util/moneystr.cpp:.*isdigit" + "src/util/strencodings.cpp:.*atoi" + "src/util/strencodings.cpp:.*strtol" + "src/util/strencodings.cpp:.*strtoll" + "src/util/strencodings.cpp:.*strtoul" + "src/util/strencodings.cpp:.*strtoull" + "src/util/strencodings.h:.*atoi" ) REGEXP_IGNORE_EXTERNAL_DEPENDENCIES="^src/(crypto/ctaes/|leveldb/|secp256k1/|tinyformat.h|univalue/)" |