aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xcontrib/devtools/test-security-check.py11
-rwxr-xr-xcontrib/devtools/test-symbol-check.py7
-rw-r--r--doc/build-osx.md330
-rw-r--r--doc/dependencies.md5
-rw-r--r--doc/external-signer.md2
-rw-r--r--src/Makefile.am2
-rw-r--r--src/bench/coin_selection.cpp5
-rw-r--r--src/bench/wallet_balance.cpp5
-rw-r--r--src/bitcoin-cli.cpp10
-rw-r--r--src/bitcoind.cpp1
-rw-r--r--src/compat/glibc_compat.cpp7
-rw-r--r--src/compat/glibc_sanity.cpp45
-rw-r--r--src/compat/sanity.h1
-rw-r--r--src/i2p.cpp4
-rw-r--r--src/i2p.h8
-rw-r--r--src/init.cpp3
-rw-r--r--src/interfaces/chain.h8
-rw-r--r--src/miner.cpp3
-rw-r--r--src/miner.h6
-rw-r--r--src/net.cpp22
-rw-r--r--src/net.h10
-rw-r--r--src/net_processing.cpp141
-rw-r--r--src/net_processing.h7
-rw-r--r--src/netbase.cpp129
-rw-r--r--src/netbase.h139
-rw-r--r--src/node/interfaces.cpp11
-rw-r--r--src/node/psbt.h20
-rw-r--r--src/node/transaction.cpp8
-rw-r--r--src/optional.h20
-rw-r--r--src/psbt.h5
-rw-r--r--src/qt/addressbookpage.cpp2
-rw-r--r--src/qt/bitcoin.cpp8
-rw-r--r--src/qt/psbtoperationsdialog.cpp2
-rw-r--r--src/qt/qrimagewidget.cpp4
-rw-r--r--src/qt/sendcoinsdialog.cpp2
-rw-r--r--src/qt/test/addressbooktests.cpp2
-rw-r--r--src/qt/test/wallettests.cpp2
-rw-r--r--src/qt/transactionview.cpp2
-rw-r--r--src/qt/walletview.cpp2
-rw-r--r--src/rpc/rawtransaction.cpp6
-rw-r--r--src/script/descriptor.cpp19
-rw-r--r--src/script/descriptor.h4
-rw-r--r--src/signet.cpp12
-rw-r--r--src/signet.h4
-rw-r--r--src/test/descriptor_tests.cpp27
-rw-r--r--src/test/fuzz/autofile.cpp1
-rw-r--r--src/test/fuzz/buffered_file.cpp1
-rw-r--r--src/test/fuzz/deserialize.cpp4
-rw-r--r--src/test/fuzz/net.cpp2
-rw-r--r--src/test/fuzz/node_eviction.cpp3
-rw-r--r--src/test/fuzz/p2p_transport_deserializer.cpp3
-rw-r--r--src/test/fuzz/parse_numbers.cpp3
-rw-r--r--src/test/fuzz/psbt.cpp4
-rw-r--r--src/test/fuzz/script_descriptor_cache.cpp2
-rw-r--r--src/test/fuzz/system.cpp4
-rw-r--r--src/test/net_tests.cpp4
-rw-r--r--src/test/sanity_tests.cpp1
-rw-r--r--src/test/sock_tests.cpp31
-rw-r--r--src/test/util_tests.cpp67
-rw-r--r--src/txmempool.cpp9
-rw-r--r--src/txmempool.h6
-rw-r--r--src/util/sock.cpp10
-rw-r--r--src/util/sock.h5
-rw-r--r--src/util/system.cpp12
-rw-r--r--src/util/system.h4
-rw-r--r--src/util/tokenpipe.cpp1
-rw-r--r--src/validation.cpp4
-rw-r--r--src/validation.h7
-rw-r--r--src/wallet/coincontrol.h11
-rw-r--r--src/wallet/coinselection.cpp5
-rw-r--r--src/wallet/db.h4
-rw-r--r--src/wallet/load.cpp2
-rw-r--r--src/wallet/rpcdump.cpp2
-rw-r--r--src/wallet/rpcsigner.cpp3
-rw-r--r--src/wallet/rpcwallet.cpp16
-rw-r--r--src/wallet/scriptpubkeyman.cpp6
-rw-r--r--src/wallet/test/coinselector_tests.cpp22
-rw-r--r--src/wallet/test/wallet_tests.cpp6
-rw-r--r--src/wallet/wallet.cpp76
-rw-r--r--src/wallet/wallet.h28
-rw-r--r--src/wallet/walletdb.cpp3
-rwxr-xr-xtest/functional/rpc_fundrawtransaction.py14
82 files changed, 836 insertions, 623 deletions
diff --git a/contrib/devtools/test-security-check.py b/contrib/devtools/test-security-check.py
index ec2d886653..28b5f57489 100755
--- a/contrib/devtools/test-security-check.py
+++ b/contrib/devtools/test-security-check.py
@@ -5,6 +5,7 @@
'''
Test script for security-check.py
'''
+import os
import subprocess
import unittest
@@ -19,6 +20,10 @@ def write_testcode(filename):
}
''')
+def clean_files(source, executable):
+ os.remove(source)
+ os.remove(executable)
+
def call_security_check(cc, source, executable, options):
subprocess.run([cc,source,'-o',executable] + options, check=True)
p = subprocess.run(['./contrib/devtools/security-check.py',executable], stdout=subprocess.PIPE, universal_newlines=True)
@@ -44,6 +49,8 @@ class TestSecurityChecks(unittest.TestCase):
self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-znoexecstack','-fstack-protector-all','-Wl,-zrelro','-Wl,-z,now','-pie','-fPIE', '-Wl,-z,separate-code']),
(0, ''))
+ clean_files(source, executable)
+
def test_PE(self):
source = 'test1.c'
executable = 'test1.exe'
@@ -61,6 +68,8 @@ class TestSecurityChecks(unittest.TestCase):
self.assertEqual(call_security_check(cc, source, executable, ['-Wl,--nxcompat','-Wl,--dynamicbase','-Wl,--high-entropy-va','-pie','-fPIE']),
(0, ''))
+ clean_files(source, executable)
+
def test_MACHO(self):
source = 'test1.c'
executable = 'test1'
@@ -80,6 +89,8 @@ class TestSecurityChecks(unittest.TestCase):
self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-pie','-Wl,-bind_at_load','-fstack-protector-all']),
(0, ''))
+ clean_files(source, executable)
+
if __name__ == '__main__':
unittest.main()
diff --git a/contrib/devtools/test-symbol-check.py b/contrib/devtools/test-symbol-check.py
index ee7bfc9805..106dfd2c5a 100755
--- a/contrib/devtools/test-symbol-check.py
+++ b/contrib/devtools/test-symbol-check.py
@@ -5,18 +5,17 @@
'''
Test script for symbol-check.py
'''
+import os
import subprocess
import unittest
def call_symbol_check(cc, source, executable, options):
subprocess.run([cc,source,'-o',executable] + options, check=True)
p = subprocess.run(['./contrib/devtools/symbol-check.py',executable], stdout=subprocess.PIPE, universal_newlines=True)
+ os.remove(source)
+ os.remove(executable)
return (p.returncode, p.stdout.rstrip())
-def get_machine(cc):
- p = subprocess.run([cc,'-dumpmachine'], stdout=subprocess.PIPE, universal_newlines=True)
- return p.stdout.rstrip()
-
class TestSymbolChecks(unittest.TestCase):
def test_ELF(self):
source = 'test1.c'
diff --git a/doc/build-osx.md b/doc/build-osx.md
index 52a734c80a..16c6da66d5 100644
--- a/doc/build-osx.md
+++ b/doc/build-osx.md
@@ -1,116 +1,303 @@
-# macOS Build Instructions and Notes
+# macOS Build Guide
+
+**Updated for MacOS [11.2](https://www.apple.com/macos/big-sur/)**
+
+This guide describes how to build bitcoind, command-line utilities, and GUI on macOS
+
+**Note:** The following is for Intel Macs only!
+
+## Dependencies
+
+The following dependencies are **required**:
+
+Library | Purpose | Description
+-----------------------------------------------------------|------------|----------------------
+[automake](https://formulae.brew.sh/formula/automake) | Build | Generate makefile
+[libtool](https://formulae.brew.sh/formula/libtool) | Build | Shared library support
+[pkg-config](https://formulae.brew.sh/formula/pkg-config) | Build | Configure compiler and linker flags
+[boost](https://formulae.brew.sh/formula/boost) | Utility | Library for threading, data structures, etc
+[libevent](https://formulae.brew.sh/formula/libevent) | Networking | OS independent asynchronous networking
+
+The following dependencies are **optional**:
+
+Library | Purpose | Description
+--------------------------------------------------------------- |------------------|----------------------
+[berkeley-db@4](https://formulae.brew.sh/formula/berkeley-db@4) | Berkeley DB | Wallet storage (only needed when wallet enabled)
+[qt@5](https://formulae.brew.sh/formula/qt@5) | GUI | GUI toolkit (only needed when GUI enabled)
+[qrencode](https://formulae.brew.sh/formula/qrencode) | QR codes in GUI | Generating QR codes (only needed when GUI enabled)
+[zeromq](https://formulae.brew.sh/formula/zeromq) | ZMQ notification | Allows generating ZMQ notifications (requires ZMQ version >= 4.0.0)
+[sqlite](https://formulae.brew.sh/formula/sqlite) | SQLite DB | Wallet storage (only needed when wallet enabled)
+[miniupnpc](https://formulae.brew.sh/formula/miniupnpc) | UPnP Support | Firewall-jumping support (needed for port mapping support)
+[libnatpmp](https://formulae.brew.sh/formula/libnatpmp) | NAT-PMP Support | Firewall-jumping support (needed for port mapping support)
+[python3](https://formulae.brew.sh/formula/python@3.9) | Testing | Python Interpreter (only needed when running the test suite)
+
+The following dependencies are **optional** packages required for deploying:
+
+Library | Purpose | Description
+----------------------------------------------------|------------------|----------------------
+[librsvg](https://formulae.brew.sh/formula/librsvg) | Deploy Dependency| Library to render SVG files
+[ds_store](https://pypi.org/project/ds-store/) | Deploy Dependency| Examine and modify .DS_Store files
+[mac_alias](https://pypi.org/project/mac-alias/) | Deploy Dependency| Generate/Read binary alias and bookmark records
+
+See [dependencies.md](dependencies.md) for a complete overview.
+
+## Preparation
The commands in this guide should be executed in a Terminal application.
-The built-in one is located in
+macOS comes with a built-in Terminal located in:
+
```
/Applications/Utilities/Terminal.app
```
-## Preparation
-Install the macOS command line tools:
+### 1. Xcode Command Line Tools
-```shell
+The Xcode Command Line Tools are a collection of build tools for macOS.
+These tools must be installed in order to build Bitcoin Core from source.
+
+To install, run the following command from your terminal:
+
+``` bash
xcode-select --install
```
-When the popup appears, click `Install`.
+Upon running the command, you should see a popup appear.
+Click on `Install` to continue the installation process.
-Then install [Homebrew](https://brew.sh).
+### 2. Homebrew Package Manager
-## Dependencies
-```shell
-brew install automake libtool boost miniupnpc libnatpmp pkg-config python qt@5 libevent qrencode
+Homebrew is a package manager for macOS that allows one to install packages from the command line easily.
+While several package managers are available for macOS, this guide will focus on Homebrew as it is the most popular.
+Since the examples in this guide which walk through the installation of a package will use Homebrew, it is recommended that you install it to follow along.
+Otherwise, you can adapt the commands to your package manager of choice.
+
+To install the Homebrew package manager, see: https://brew.sh
+
+Note: If you run into issues while installing Homebrew or pulling packages, refer to [Homebrew's troubleshooting page](https://docs.brew.sh/Troubleshooting).
+
+### 3. Install Required Dependencies
+
+The first step is to download the required dependencies.
+These dependencies represent the packages required to get a barebones installation up and running.
+To install, run the following from your terminal:
+
+``` bash
+brew install automake libtool boost pkg-config libevent
```
-If you run into issues, check [Homebrew's troubleshooting page](https://docs.brew.sh/Troubleshooting).
-See [dependencies.md](dependencies.md) for a complete overview.
+### 4. Clone Bitcoin repository
-If you want to build the disk image with `make deploy` (.dmg / optional), you need RSVG:
-```shell
-brew install librsvg
+`git` should already be installed by default on your system.
+Now that all the required dependencies are installed, let's clone the Bitcoin Core repository to a directory.
+All build scripts and commands will run from this directory.
+
+``` bash
+git clone https://github.com/bitcoin/bitcoin.git
```
-and [`macdeployqtplus`](../contrib/macdeploy/README.md) dependencies:
-```shell
-pip3 install ds_store mac_alias
+### 5. Install Optional Dependencies
+
+#### Wallet Dependencies
+
+It is not necessary to build wallet functionality to run `bitcoind` or `bitcoin-qt`.
+To enable legacy wallets, you must install `berkeley-db@4`.
+To enable [descriptor wallets](https://github.com/bitcoin/bitcoin/blob/master/doc/descriptors.md), `sqlite` is required.
+Skip `berkeley-db@4` if you intend to *exclusively* use descriptor wallets.
+
+###### Legacy Wallet Support
+
+`berkeley-db@4` is required to enable support for legacy wallets.
+Skip if you don't intend to use legacy wallets.
+
+``` bash
+brew install berkeley-db@4
```
-The wallet support requires one or both of the dependencies ([*SQLite*](#sqlite) and [*Berkeley DB*](#berkeley-db)) in the sections below.
-To build Bitcoin Core without wallet, see [*Disable-wallet mode*](#disable-wallet-mode).
+###### Descriptor Wallet Support
-#### SQLite
+Note: Apple has included a useable `sqlite` package since macOS 10.14.
+You may not need to install this package.
-Usually, macOS installation already has a suitable SQLite installation.
-Also, the Homebrew package could be installed:
+`sqlite` is required to enable support for descriptor wallets.
+Skip if you don't intend to use descriptor wallets.
-```shell
+``` bash
brew install sqlite
```
+---
-In that case the Homebrew package will prevail.
+#### GUI Dependencies
-#### Berkeley DB
+###### Qt
-It is recommended to use Berkeley DB 4.8. If you have to build it yourself,
-you can use [this](/contrib/install_db4.sh) script to install it
-like so:
+Bitcoin Core includes a GUI built with the cross-platform Qt Framework.
+To compile the GUI, we need to install `qt@5`.
+Skip if you don't intend to use the GUI.
-```shell
-./contrib/install_db4.sh .
+``` bash
+brew install qt@5
```
-from the root of the repository.
+Note: Building with Qt binaries downloaded from the Qt website is not officially supported.
+See the notes in [#7714](https://github.com/bitcoin/bitcoin/issues/7714).
-Also, the Homebrew package could be installed:
+###### qrencode
-```shell
-brew install berkeley-db4
+The GUI can encode addresses in a QR Code. To build in QR support for the GUI, install `qrencode`.
+Skip if not using the GUI or don't want QR code functionality.
+
+``` bash
+brew install qrencode
```
+---
+
+#### Port Mapping Dependencies
+
+###### miniupnpc
-## Build Bitcoin Core
+miniupnpc may be used for UPnP port mapping.
+Skip if you do not need this functionality.
-1. Clone the Bitcoin Core source code:
- ```shell
- git clone https://github.com/bitcoin/bitcoin
- cd bitcoin
- ```
+``` bash
+brew install miniupnpc
+```
-2. Build Bitcoin Core:
+###### libnatpmp
- Configure and build the headless Bitcoin Core binaries as well as the GUI (if Qt is found).
+libnatpmp may be used for NAT-PMP port mapping.
+Skip if you do not need this functionality.
- You can disable the GUI build by passing `--without-gui` to configure.
- ```shell
- ./autogen.sh
- ./configure
- make
- ```
+``` bash
+brew install libnatpmp
+```
-3. It is recommended to build and run the unit tests:
- ```shell
- make check
- ```
+Note: UPnP and NAT-PMP support will be compiled in and disabled by default.
+Check out the [further configuration](#further-configuration) section for more information.
-4. You can also create a `.dmg` that contains the `.app` bundle (optional):
- ```shell
- make deploy
- ```
+---
-## Disable-wallet mode
-When the intention is to run only a P2P node without a wallet, Bitcoin Core may be
-compiled in disable-wallet mode with:
-```shell
-./configure --disable-wallet
+#### ZMQ Dependencies
+
+Support for ZMQ notifications requires the following dependency.
+Skip if you do not need ZMQ functionality.
+
+``` bash
+brew install zeromq
```
-In this case there is no dependency on [*Berkeley DB*](#berkeley-db) and [*SQLite*](#sqlite).
+ZMQ is automatically compiled in and enabled if the dependency is detected.
+Check out the [further configuration](#further-configuration) section for more information.
+
+For more information on ZMQ, see: [zmq.md](zmq.md)
-Mining is also possible in disable-wallet mode using the `getblocktemplate` RPC call.
+---
-## Running
-Bitcoin Core is now available at `./src/bitcoind`
+#### Test Suite Dependencies
+
+There is an included test suite that is useful for testing code changes when developing.
+To run the test suite (recommended), you will need to have Python 3 installed:
+
+``` bash
+brew install python
+```
+
+---
+
+#### Deploy Dependencies
+
+You can deploy a `.dmg` containing the Bitcoin Core application using `make deploy`.
+This command depends on a couple of python packages, so it is required that you have `python` installed.
+
+Ensuring that `python` is installed, you can install the deploy dependencies by running the following commands in your terminal:
+
+``` bash
+brew install librsvg
+```
+
+``` bash
+pip3 install ds_store mac_alias
+```
+
+## Building Bitcoin Core
+
+### 1. Configuration
+
+There are many ways to configure Bitcoin Core, here are a few common examples:
+
+##### Wallet (BDB + SQlite) Support, No GUI:
+
+If `berkeley-db@4` is installed, then legacy wallet support will be built.
+If `berkeley-db@4` is not installed, then this will throw an error.
+If `sqlite` is installed, then descriptor wallet support will also be built.
+Additionally, this explicitly disables the GUI.
+
+``` bash
+./autogen.sh
+./configure --with-gui=no
+```
+
+##### Wallet (only SQlite) and GUI Support:
+
+This explicitly enables the GUI and disables legacy wallet support.
+If `qt` is not installed, this will throw an error.
+If `sqlite` is installed then descriptor wallet functionality will be built.
+If `sqlite` is not installed, then wallet functionality will be disabled.
+
+``` bash
+./autogen.sh
+./configure --without-bdb --with-gui=yes
+```
+
+##### No Wallet or GUI
+
+``` bash
+./autogen.sh
+./configure --without-wallet --with-gui=no
+```
+
+##### Further Configuration
+
+You may want to dig deeper into the configuration options to achieve your desired behavior.
+Examine the output of the following command for a full list of configuration options:
+
+``` bash
+./configure -help
+```
+
+### 2. Compile
+
+After configuration, you are ready to compile.
+Run the following in your terminal to compile Bitcoin Core:
+
+``` bash
+make -jx # use -jX here for parallelism
+make check # Run tests if Python 3 is available
+```
+
+### 3. Deploy (optional)
+
+You can also create a `.dmg` containing the `.app` bundle by running the following command:
+
+``` bash
+make deploy
+```
+
+## Running Bitcoin Core
+
+Bitcoin Core should now be available at `./src/bitcoind`.
+If you compiled support for the GUI, it should be available at `./src/qt/bitcoin-qt`.
+
+The first time you run `bitcoind` or `bitcoin-qt`, it will start downloading the blockchain.
+This process could take many hours, or even days on slower than average systems.
+
+By default, blockchain and wallet data files will be stored in:
+
+``` bash
+/Users/${USER}/Library/Application Support/Bitcoin/
+```
Before running, you may create an empty configuration file:
+
```shell
mkdir -p "/Users/${USER}/Library/Application Support/Bitcoin"
@@ -119,22 +306,17 @@ touch "/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 many hours, or even days on slower than average systems.
-
You can monitor the download process by looking at the debug.log file:
+
```shell
tail -f $HOME/Library/Application\ Support/Bitcoin/debug.log
```
## Other commands:
+
```shell
./src/bitcoind -daemon # Starts the bitcoin daemon.
./src/bitcoin-cli --help # Outputs a list of command-line options.
./src/bitcoin-cli help # Outputs a list of RPC commands when the daemon is running.
+./src/qt/bitcoin-qt -server # Starts the bitcoin-qt server mode, allows bitcoin-cli control
```
-
-## Notes
-* Tested on OS X 10.14 Mojave through macOS 11 Big Sur on 64-bit Intel
-processors only.
-* Building with downloaded Qt binaries is not officially supported. See the notes in [#7714](https://github.com/bitcoin/bitcoin/issues/7714).
diff --git a/doc/dependencies.md b/doc/dependencies.md
index 159c6bcc28..31fe68bcd2 100644
--- a/doc/dependencies.md
+++ b/doc/dependencies.md
@@ -14,7 +14,7 @@ These are the dependencies currently used by Bitcoin Core. You can find instruct
| GCC | | [7+](https://gcc.gnu.org/) (C++17 support) | | | |
| HarfBuzz-NG | | | | | [Yes](https://github.com/bitcoin/bitcoin/blob/master/depends/packages/qt.mk) |
| libevent | [2.1.11-stable](https://github.com/libevent/libevent/releases) | [2.0.21](https://github.com/bitcoin/bitcoin/pull/18676) | No | | |
-| libnatpmp | [20150609](https://miniupnp.tuxfamily.org/files) | | No | | |
+| libnatpmp | git commit [4536032...](https://github.com/miniupnp/libnatpmp/tree/4536032ae32268a45c073a4d5e91bbab4534773a) | | No | | |
| libpng | | | | | [Yes](https://github.com/bitcoin/bitcoin/blob/master/depends/packages/qt.mk) |
| librsvg | | | | | |
| MiniUPnPc | [2.0.20180203](https://miniupnp.tuxfamily.org/files) | | No | | |
@@ -26,7 +26,7 @@ These are the dependencies currently used by Bitcoin Core. You can find instruct
| XCB | | | | | [Yes](https://github.com/bitcoin/bitcoin/blob/master/depends/packages/qt.mk) (Linux only) |
| xkbcommon | | | | | [Yes](https://github.com/bitcoin/bitcoin/blob/master/depends/packages/qt.mk) (Linux only) |
| ZeroMQ | [4.3.1](https://github.com/zeromq/libzmq/releases) | 4.0.0 | No | | |
-| zlib | [1.2.11](https://zlib.net/) | | | | No |
+| zlib | | | | | [Yes](https://github.com/bitcoin/bitcoin/blob/master/depends/packages/qt.mk) |
Controlling dependencies
------------------------
@@ -43,3 +43,4 @@ Some dependencies are not needed in all configurations. The following are some f
#### Other
* librsvg is only needed if you need to run `make deploy` on (cross-compilation to) macOS.
+* Not-Qt-bundled zlib is required to build the [DMG tool](../contrib/macdeploy/README.md#deterministic-macos-dmg-notes) from the libdmg-hfsplus project.
diff --git a/doc/external-signer.md b/doc/external-signer.md
index c91ea9bab7..2b3b378bee 100644
--- a/doc/external-signer.md
+++ b/doc/external-signer.md
@@ -4,7 +4,7 @@ Bitcoin Core can be launched with `-signer=<cmd>` where `<cmd>` is an external t
## Example usage
-The following example is based on the [HWI](https://github.com/bitcoin-core/HWI) tool. Although this tool is hosted under the Bitcoin Core GitHub organization and maintained by Bitcoin Core developers, it should be used with caution. It is considered experimental and has far less review than Bitcoin Core itself. Be particularly careful when running tools such as these on a computer with private keys on it.
+The following example is based on the [HWI](https://github.com/bitcoin-core/HWI) tool. Version 2.0 or newer is required. Although this tool is hosted under the Bitcoin Core GitHub organization and maintained by Bitcoin Core developers, it should be used with caution. It is considered experimental and has far less review than Bitcoin Core itself. Be particularly careful when running tools such as these on a computer with private keys on it.
When using a hardware wallet, consult the manufacturer website for (alternative) software they recommend. As long as their software conforms to the standard below, it should be able to work with Bitcoin Core.
diff --git a/src/Makefile.am b/src/Makefile.am
index 8f37e055ff..9903c2e9b3 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -182,7 +182,6 @@ BITCOIN_CORE_H = \
node/ui_interface.h \
node/utxo_snapshot.h \
noui.h \
- optional.h \
outputtype.h \
policy/feerate.h \
policy/fees.h \
@@ -553,7 +552,6 @@ libbitcoin_util_a_SOURCES = \
support/lockedpool.cpp \
chainparamsbase.cpp \
clientversion.cpp \
- compat/glibc_sanity.cpp \
compat/glibcxx_sanity.cpp \
compat/strnlen.cpp \
fs.cpp \
diff --git a/src/bench/coin_selection.cpp b/src/bench/coin_selection.cpp
index 376e70ffba..80acdec044 100644
--- a/src/bench/coin_selection.cpp
+++ b/src/bench/coin_selection.cpp
@@ -49,7 +49,10 @@ static void CoinSelection(benchmark::Bench& bench)
}
const CoinEligibilityFilter filter_standard(1, 6, 0);
- const CoinSelectionParams coin_selection_params(true, 34, 148, CFeeRate(0), 0, false);
+ const CoinSelectionParams coin_selection_params(/* use_bnb= */ true, /* change_output_size= */ 34,
+ /* change_spend_size= */ 148, /* effective_feerate= */ CFeeRate(0),
+ /* long_term_feerate= */ CFeeRate(0), /* discard_feerate= */ CFeeRate(0),
+ /* tx_no_inputs_size= */ 0, /* avoid_partial= */ false);
bench.run([&] {
std::set<CInputCoin> setCoinsRet;
CAmount nValueRet;
diff --git a/src/bench/wallet_balance.cpp b/src/bench/wallet_balance.cpp
index c96ef209e3..d7cc167885 100644
--- a/src/bench/wallet_balance.cpp
+++ b/src/bench/wallet_balance.cpp
@@ -5,13 +5,14 @@
#include <bench/bench.h>
#include <interfaces/chain.h>
#include <node/context.h>
-#include <optional.h>
#include <test/util/mining.h>
#include <test/util/setup_common.h>
#include <test/util/wallet.h>
#include <validationinterface.h>
#include <wallet/wallet.h>
+#include <optional>
+
static void WalletBalance(benchmark::Bench& bench, const bool set_dirty, const bool add_watchonly, const bool add_mine)
{
const auto test_setup = MakeNoLogFileContext<const TestingSetup>();
@@ -26,7 +27,7 @@ static void WalletBalance(benchmark::Bench& bench, const bool set_dirty, const b
}
auto handler = test_setup->m_node.chain->handleNotifications({&wallet, [](CWallet*) {}});
- const Optional<std::string> address_mine{add_mine ? Optional<std::string>{getnewaddress(wallet)} : nullopt};
+ const std::optional<std::string> address_mine{add_mine ? std::optional<std::string>{getnewaddress(wallet)} : std::nullopt};
if (add_watchonly) importaddress(wallet, ADDRESS_WATCHONLY);
for (int i = 0; i < 100; ++i) {
diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp
index dc4b142f83..ecd08c62eb 100644
--- a/src/bitcoin-cli.cpp
+++ b/src/bitcoin-cli.cpp
@@ -9,7 +9,6 @@
#include <chainparamsbase.h>
#include <clientversion.h>
-#include <optional.h>
#include <rpc/client.h>
#include <rpc/mining.h>
#include <rpc/protocol.h>
@@ -24,6 +23,7 @@
#include <cmath>
#include <functional>
#include <memory>
+#include <optional>
#include <stdio.h>
#include <string>
#include <tuple>
@@ -611,7 +611,7 @@ public:
}
};
-static UniValue CallRPC(BaseRequestHandler* rh, const std::string& strMethod, const std::vector<std::string>& args, const Optional<std::string>& rpcwallet = {})
+static UniValue CallRPC(BaseRequestHandler* rh, const std::string& strMethod, const std::vector<std::string>& args, const std::optional<std::string>& rpcwallet = {})
{
std::string host;
// In preference order, we choose the following for the port:
@@ -733,7 +733,7 @@ static UniValue CallRPC(BaseRequestHandler* rh, const std::string& strMethod, co
* @returns the RPC response as a UniValue object.
* @throws a CConnectionFailed std::runtime_error if connection failed or RPC server still in warmup.
*/
-static UniValue ConnectAndCallRPC(BaseRequestHandler* rh, const std::string& strMethod, const std::vector<std::string>& args, const Optional<std::string>& rpcwallet = {})
+static UniValue ConnectAndCallRPC(BaseRequestHandler* rh, const std::string& strMethod, const std::vector<std::string>& args, const std::optional<std::string>& rpcwallet = {})
{
UniValue response(UniValue::VOBJ);
// Execute and handle connection failures with -rpcwait.
@@ -817,7 +817,7 @@ static void GetWalletBalances(UniValue& result)
*/
static UniValue GetNewAddress()
{
- Optional<std::string> wallet_name{};
+ std::optional<std::string> wallet_name{};
if (gArgs.IsArgSet("-rpcwallet")) wallet_name = gArgs.GetArg("-rpcwallet", "");
DefaultRequestHandler rh;
return ConnectAndCallRPC(&rh, "getnewaddress", /* args=*/{}, wallet_name);
@@ -922,7 +922,7 @@ static int CommandLineRPC(int argc, char *argv[])
}
if (nRet == 0) {
// Perform RPC call
- Optional<std::string> wallet_name{};
+ std::optional<std::string> wallet_name{};
if (gArgs.IsArgSet("-rpcwallet")) wallet_name = gArgs.GetArg("-rpcwallet", "");
const UniValue reply = ConnectAndCallRPC(rh.get(), method, args, wallet_name);
diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp
index 32f06aec2c..1b4ca3e9a8 100644
--- a/src/bitcoind.cpp
+++ b/src/bitcoind.cpp
@@ -25,6 +25,7 @@
#include <util/url.h>
#include <functional>
+#include <optional>
const std::function<std::string(const char*)> G_TRANSLATION_FUN = nullptr;
UrlDecodeFn* const URL_DECODE = urlDecode;
diff --git a/src/compat/glibc_compat.cpp b/src/compat/glibc_compat.cpp
index 8a51f310f7..ff581d4a9e 100644
--- a/src/compat/glibc_compat.cpp
+++ b/src/compat/glibc_compat.cpp
@@ -9,13 +9,6 @@
#include <cstddef>
#include <cstdint>
-// Prior to GLIBC_2.14, memcpy was aliased to memmove.
-extern "C" void* memmove(void* a, const void* b, size_t c);
-extern "C" void* memcpy(void* a, const void* b, size_t c)
-{
- return memmove(a, b, c);
-}
-
#if defined(__i386__) || defined(__arm__)
extern "C" int64_t __udivmoddi4(uint64_t u, uint64_t v, uint64_t* rp);
diff --git a/src/compat/glibc_sanity.cpp b/src/compat/glibc_sanity.cpp
deleted file mode 100644
index 06d0dd6fba..0000000000
--- a/src/compat/glibc_sanity.cpp
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright (c) 2009-2020 The Bitcoin Core developers
-// Distributed under the MIT software license, see the accompanying
-// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-
-#if defined(HAVE_CONFIG_H)
-#include <config/bitcoin-config.h>
-#endif
-
-#include <cstddef>
-
-extern "C" void* memcpy(void* a, const void* b, size_t c);
-void* memcpy_int(void* a, const void* b, size_t c)
-{
- return memcpy(a, b, c);
-}
-
-namespace
-{
-// trigger: Use the memcpy_int wrapper which calls our internal memcpy.
-// A direct call to memcpy may be optimized away by the compiler.
-// test: Fill an array with a sequence of integers. memcpy to a new empty array.
-// Verify that the arrays are equal. Use an odd size to decrease the odds of
-// the call being optimized away.
-template <unsigned int T>
-bool sanity_test_memcpy()
-{
- unsigned int memcpy_test[T];
- unsigned int memcpy_verify[T] = {};
- for (unsigned int i = 0; i != T; ++i)
- memcpy_test[i] = i;
-
- memcpy_int(memcpy_verify, memcpy_test, sizeof(memcpy_test));
-
- for (unsigned int i = 0; i != T; ++i) {
- if (memcpy_verify[i] != i)
- return false;
- }
- return true;
-}
-} // namespace
-
-bool glibc_sanity_test()
-{
- return sanity_test_memcpy<1025>();
-}
diff --git a/src/compat/sanity.h b/src/compat/sanity.h
index 909c4f6da8..8efa416102 100644
--- a/src/compat/sanity.h
+++ b/src/compat/sanity.h
@@ -5,7 +5,6 @@
#ifndef BITCOIN_COMPAT_SANITY_H
#define BITCOIN_COMPAT_SANITY_H
-bool glibc_sanity_test();
bool glibcxx_sanity_test();
#endif // BITCOIN_COMPAT_SANITY_H
diff --git a/src/i2p.cpp b/src/i2p.cpp
index 42270deaeb..d16c620d88 100644
--- a/src/i2p.cpp
+++ b/src/i2p.cpp
@@ -153,7 +153,7 @@ bool Session::Accept(Connection& conn)
}
const std::string& peer_dest =
- conn.sock.RecvUntilTerminator('\n', MAX_WAIT_FOR_IO, *m_interrupt);
+ conn.sock.RecvUntilTerminator('\n', MAX_WAIT_FOR_IO, *m_interrupt, MAX_MSG_SIZE);
conn.peer = CService(DestB64ToAddr(peer_dest), Params().GetDefaultPort());
@@ -252,7 +252,7 @@ Session::Reply Session::SendRequestAndGetReply(const Sock& sock,
// signaled.
static constexpr auto recv_timeout = 3min;
- reply.full = sock.RecvUntilTerminator('\n', recv_timeout, *m_interrupt);
+ reply.full = sock.RecvUntilTerminator('\n', recv_timeout, *m_interrupt, MAX_MSG_SIZE);
for (const auto& kv : spanparsing::Split(reply.full, ' ')) {
const auto& pos = std::find(kv.begin(), kv.end(), '=');
diff --git a/src/i2p.h b/src/i2p.h
index 8fafe0a4d0..1ebe7d0329 100644
--- a/src/i2p.h
+++ b/src/i2p.h
@@ -41,6 +41,14 @@ struct Connection {
namespace sam {
/**
+ * The maximum size of an incoming message from the I2P SAM proxy (in bytes).
+ * Used to avoid a runaway proxy from sending us an "unlimited" amount of data without a terminator.
+ * The longest known message is ~1400 bytes, so this is high enough not to be triggered during
+ * normal operation, yet low enough to avoid a malicious proxy from filling our memory.
+ */
+static constexpr size_t MAX_MSG_SIZE{65536};
+
+/**
* I2P SAM session.
*/
class Session
diff --git a/src/init.cpp b/src/init.cpp
index b91a94bc25..7d5420e3be 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -585,6 +585,7 @@ void SetupServerArgs(NodeContext& node)
argsman.AddArg("-daemonwait", strprintf("Wait for initialization to be finished before exiting. This implies -daemon (default: %d)", DEFAULT_DAEMONWAIT), ArgsManager::ALLOW_BOOL, OptionsCategory::OPTIONS);
#else
hidden_args.emplace_back("-daemon");
+ hidden_args.emplace_back("-daemonwait");
#endif
// Add the hidden options
@@ -772,7 +773,7 @@ static bool InitSanityCheck()
return InitError(Untranslated("Elliptic curve cryptography sanity check failure. Aborting."));
}
- if (!glibc_sanity_test() || !glibcxx_sanity_test())
+ if (!glibcxx_sanity_test())
return false;
if (!Random_SanityCheck()) {
diff --git a/src/interfaces/chain.h b/src/interfaces/chain.h
index ebc5466173..3395741b1b 100644
--- a/src/interfaces/chain.h
+++ b/src/interfaces/chain.h
@@ -5,12 +5,12 @@
#ifndef BITCOIN_INTERFACES_CHAIN_H
#define BITCOIN_INTERFACES_CHAIN_H
-#include <optional.h> // For Optional and nullopt
#include <primitives/transaction.h> // For CTransactionRef
#include <util/settings.h> // For util::SettingsValue
#include <functional>
#include <memory>
+#include <optional>
#include <stddef.h>
#include <stdint.h>
#include <string>
@@ -94,7 +94,7 @@ public:
//! Get current chain height, not including genesis block (returns 0 if
//! chain only contains genesis block, nullopt if chain does not contain
//! any blocks)
- virtual Optional<int> getHeight() = 0;
+ virtual std::optional<int> getHeight() = 0;
//! Get block hash. Height must be valid or this function will abort.
virtual uint256 getBlockHash(int height) = 0;
@@ -109,7 +109,7 @@ public:
//! Return height of the highest block on chain in common with the locator,
//! which will either be the original block used to create the locator,
//! or one of its ancestors.
- virtual Optional<int> findLocatorFork(const CBlockLocator& locator) = 0;
+ virtual std::optional<int> findLocatorFork(const CBlockLocator& locator) = 0;
//! Check if transaction will be final given chain height current time.
virtual bool checkFinalTx(const CTransaction& tx) = 0;
@@ -154,7 +154,7 @@ public:
//! Return true if data is available for all blocks in the specified range
//! of blocks. This checks all blocks that are ancestors of block_hash in
//! the height range from min_height to max_height, inclusive.
- virtual bool hasBlocks(const uint256& block_hash, int min_height = 0, Optional<int> max_height = {}) = 0;
+ virtual bool hasBlocks(const uint256& block_hash, int min_height = 0, std::optional<int> max_height = {}) = 0;
//! Check if transaction is RBF opt in.
virtual RBFTransactionState isRBFOptIn(const CTransaction& tx) = 0;
diff --git a/src/miner.cpp b/src/miner.cpp
index fbaef0f224..fe7a54c052 100644
--- a/src/miner.cpp
+++ b/src/miner.cpp
@@ -96,9 +96,6 @@ void BlockAssembler::resetBlock()
nFees = 0;
}
-Optional<int64_t> BlockAssembler::m_last_block_num_txs{nullopt};
-Optional<int64_t> BlockAssembler::m_last_block_weight{nullopt};
-
std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(CChainState& chainstate, const CScript& scriptPubKeyIn)
{
int64_t nTimeStart = GetTimeMicros();
diff --git a/src/miner.h b/src/miner.h
index a67fec6dd8..023635814c 100644
--- a/src/miner.h
+++ b/src/miner.h
@@ -6,12 +6,12 @@
#ifndef BITCOIN_MINER_H
#define BITCOIN_MINER_H
-#include <optional.h>
#include <primitives/block.h>
#include <txmempool.h>
#include <validation.h>
#include <memory>
+#include <optional>
#include <stdint.h>
#include <boost/multi_index_container.hpp>
@@ -160,8 +160,8 @@ public:
/** Construct a new block template with coinbase to scriptPubKeyIn */
std::unique_ptr<CBlockTemplate> CreateNewBlock(CChainState& chainstate, const CScript& scriptPubKeyIn);
- static Optional<int64_t> m_last_block_num_txs;
- static Optional<int64_t> m_last_block_weight;
+ inline static std::optional<int64_t> m_last_block_num_txs{};
+ inline static std::optional<int64_t> m_last_block_weight{};
private:
// utility functions
diff --git a/src/net.cpp b/src/net.cpp
index 1e4a6a9aa7..6a2469f950 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -18,7 +18,6 @@
#include <net_permissions.h>
#include <netbase.h>
#include <node/ui_interface.h>
-#include <optional.h>
#include <protocol.h>
#include <random.h>
#include <scheduler.h>
@@ -39,6 +38,7 @@
#include <algorithm>
#include <cstdint>
#include <functional>
+#include <optional>
#include <unordered_map>
#include <math.h>
@@ -193,7 +193,7 @@ bool IsPeerAddrLocalGood(CNode *pnode)
IsReachable(addrLocal.GetNetwork());
}
-Optional<CAddress> GetLocalAddrForPeer(CNode *pnode)
+std::optional<CAddress> GetLocalAddrForPeer(CNode *pnode)
{
CAddress addrLocal = GetLocalAddress(&pnode->addr, pnode->GetLocalServices());
if (gArgs.GetBoolArg("-addrmantest", false)) {
@@ -215,7 +215,7 @@ Optional<CAddress> GetLocalAddrForPeer(CNode *pnode)
return addrLocal;
}
// Address is unroutable. Don't advertise.
- return nullopt;
+ return std::nullopt;
}
// learn a new local address
@@ -632,7 +632,7 @@ bool CNode::ReceiveMsgBytes(Span<const uint8_t> msg_bytes, bool& complete)
if (m_deserializer->Complete()) {
// decompose a transport agnostic CNetMessage from the deserializer
uint32_t out_err_raw_size{0};
- Optional<CNetMessage> result{m_deserializer->GetMessage(time, out_err_raw_size)};
+ std::optional<CNetMessage> result{m_deserializer->GetMessage(time, out_err_raw_size)};
if (!result) {
// Message deserialization failed. Drop the message but don't disconnect the peer.
// store the size of the corrupt message
@@ -723,10 +723,10 @@ const uint256& V1TransportDeserializer::GetMessageHash() const
return data_hash;
}
-Optional<CNetMessage> V1TransportDeserializer::GetMessage(const std::chrono::microseconds time, uint32_t& out_err_raw_size)
+std::optional<CNetMessage> V1TransportDeserializer::GetMessage(const std::chrono::microseconds time, uint32_t& out_err_raw_size)
{
// decompose a single CNetMessage from the TransportDeserializer
- Optional<CNetMessage> msg(std::move(vRecv));
+ std::optional<CNetMessage> msg(std::move(vRecv));
// store command string, time, and sizes
msg->m_command = hdr.GetCommand();
@@ -747,12 +747,12 @@ Optional<CNetMessage> V1TransportDeserializer::GetMessage(const std::chrono::mic
HexStr(hdr.pchChecksum),
m_node_id);
out_err_raw_size = msg->m_raw_message_size;
- msg = nullopt;
+ msg = std::nullopt;
} else if (!hdr.IsCommandValid()) {
LogPrint(BCLog::NET, "HEADER ERROR - COMMAND (%s, %u bytes), peer=%d\n",
hdr.GetCommand(), msg->m_message_size, m_node_id);
out_err_raw_size = msg->m_raw_message_size;
- msg = nullopt;
+ msg.reset();
}
// Always reset the network deserializer (prepare for the next message)
@@ -879,7 +879,7 @@ static void EraseLastKElements(std::vector<T> &elements, Comparator comparator,
elements.erase(elements.end() - eraseSize, elements.end());
}
-[[nodiscard]] Optional<NodeId> SelectNodeToEvict(std::vector<NodeEvictionCandidate>&& vEvictionCandidates)
+[[nodiscard]] std::optional<NodeId> SelectNodeToEvict(std::vector<NodeEvictionCandidate>&& vEvictionCandidates)
{
// Protect connections with certain characteristics
@@ -918,7 +918,7 @@ static void EraseLastKElements(std::vector<T> &elements, Comparator comparator,
total_protect_size -= initial_size - vEvictionCandidates.size();
EraseLastKElements(vEvictionCandidates, ReverseCompareNodeTimeConnected, total_protect_size);
- if (vEvictionCandidates.empty()) return nullopt;
+ if (vEvictionCandidates.empty()) return std::nullopt;
// If any remaining peers are preferred for eviction consider only them.
// This happens after the other preferences since if a peer is really the best by other criteria (esp relaying blocks)
@@ -989,7 +989,7 @@ bool CConnman::AttemptToEvictConnection()
vEvictionCandidates.push_back(candidate);
}
}
- const Optional<NodeId> node_id_to_evict = SelectNodeToEvict(std::move(vEvictionCandidates));
+ const std::optional<NodeId> node_id_to_evict = SelectNodeToEvict(std::move(vEvictionCandidates));
if (!node_id_to_evict) {
return false;
}
diff --git a/src/net.h b/src/net.h
index beef47f045..48d37084a0 100644
--- a/src/net.h
+++ b/src/net.h
@@ -18,7 +18,6 @@
#include <net_permissions.h>
#include <netaddress.h>
#include <netbase.h>
-#include <optional.h>
#include <policy/feerate.h>
#include <protocol.h>
#include <random.h>
@@ -35,6 +34,7 @@
#include <deque>
#include <map>
#include <memory>
+#include <optional>
#include <thread>
#include <vector>
@@ -200,7 +200,7 @@ enum
bool IsPeerAddrLocalGood(CNode *pnode);
/** Returns a local address that we should advertise to this peer */
-Optional<CAddress> GetLocalAddrForPeer(CNode *pnode);
+std::optional<CAddress> GetLocalAddrForPeer(CNode *pnode);
/**
* Mark a network as reachable or unreachable (no automatic connects to it)
@@ -311,7 +311,7 @@ public:
/** read and deserialize data, advances msg_bytes data pointer */
virtual int Read(Span<const uint8_t>& msg_bytes) = 0;
// decomposes a message from the context
- virtual Optional<CNetMessage> GetMessage(std::chrono::microseconds time, uint32_t& out_err) = 0;
+ virtual std::optional<CNetMessage> GetMessage(std::chrono::microseconds time, uint32_t& out_err) = 0;
virtual ~TransportDeserializer() {}
};
@@ -375,7 +375,7 @@ public:
}
return ret;
}
- Optional<CNetMessage> GetMessage(std::chrono::microseconds time, uint32_t& out_err_raw_size) override;
+ std::optional<CNetMessage> GetMessage(std::chrono::microseconds time, uint32_t& out_err_raw_size) override;
};
/** The TransportSerializer prepares messages for the network transport
@@ -1283,6 +1283,6 @@ struct NodeEvictionCandidate
bool m_is_local;
};
-[[nodiscard]] Optional<NodeId> SelectNodeToEvict(std::vector<NodeEvictionCandidate>&& vEvictionCandidates);
+[[nodiscard]] std::optional<NodeId> SelectNodeToEvict(std::vector<NodeEvictionCandidate>&& vEvictionCandidates);
#endif // BITCOIN_NET_H
diff --git a/src/net_processing.cpp b/src/net_processing.cpp
index 6ce984348c..6454f58675 100644
--- a/src/net_processing.cpp
+++ b/src/net_processing.cpp
@@ -34,6 +34,7 @@
#include <validation.h>
#include <memory>
+#include <optional>
#include <typeinfo>
/** How long to cache transactions in mapRelay for normal relay */
@@ -246,6 +247,7 @@ public:
bool GetNodeStateStats(NodeId nodeid, CNodeStateStats& stats) override;
bool IgnoresIncomingTxs() override { return m_ignore_incoming_txs; }
void SendPings() override;
+ void RelayTransaction(const uint256& txid, const uint256& wtxid) override;
void SetBestHeight(int height) override { m_best_height = height; };
void Misbehaving(const NodeId pnode, const int howmuch, const std::string& message) override;
void ProcessMessage(CNode& pfrom, const std::string& msg_type, CDataStream& vRecv,
@@ -259,7 +261,7 @@ private:
void EvictExtraOutboundPeers(int64_t time_in_seconds) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
/** Retrieve unbroadcast transactions from the mempool and reattempt sending to peers */
- void ReattemptInitialBroadcast(CScheduler& scheduler) const;
+ void ReattemptInitialBroadcast(CScheduler& scheduler);
/** Get a shared pointer to the Peer object.
* May return an empty shared_ptr if the Peer object can't be found. */
@@ -474,22 +476,19 @@ private:
size_t vExtraTxnForCompactIt GUARDED_BY(g_cs_orphans) = 0;
void ProcessBlockAvailability(NodeId nodeid) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
- void UpdateBlockAvailability(NodeId nodeid, const uint256 &hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
- bool CanDirectFetch(const Consensus::Params &consensusParams) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
- bool BlockRequestAllowed(const CBlockIndex* pindex, const Consensus::Params& consensusParams) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
+ void UpdateBlockAvailability(NodeId nodeid, const uint256& hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
+ bool CanDirectFetch() EXCLUSIVE_LOCKS_REQUIRED(cs_main);
+ bool BlockRequestAllowed(const CBlockIndex* pindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
bool AlreadyHaveBlock(const uint256& block_hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
- void ProcessGetBlockData(CNode& pfrom, Peer& peer, const CChainParams& chainparams, const CInv& inv, CConnman& connman);
- bool PrepareBlockFilterRequest(CNode& peer, const CChainParams& chain_params,
+ void ProcessGetBlockData(CNode& pfrom, Peer& peer, const CInv& inv);
+ bool PrepareBlockFilterRequest(CNode& peer,
BlockFilterType filter_type, uint32_t start_height,
const uint256& stop_hash, uint32_t max_height_diff,
const CBlockIndex*& stop_index,
BlockFilterIndex*& filter_index);
- void ProcessGetCFilters(CNode& peer, CDataStream& vRecv, const CChainParams& chain_params,
- CConnman& connman);
- void ProcessGetCFHeaders(CNode& peer, CDataStream& vRecv, const CChainParams& chain_params,
- CConnman& connman);
- void ProcessGetCFCheckPt(CNode& peer, CDataStream& vRecv, const CChainParams& chain_params,
- CConnman& connman);
+ void ProcessGetCFilters(CNode& peer, CDataStream& vRecv);
+ void ProcessGetCFHeaders(CNode& peer, CDataStream& vRecv);
+ void ProcessGetCFCheckPt(CNode& peer, CDataStream& vRecv);
};
} // namespace
@@ -728,9 +727,9 @@ bool PeerManagerImpl::TipMayBeStale()
return m_last_tip_update < GetTime() - consensusParams.nPowTargetSpacing * 3 && mapBlocksInFlight.empty();
}
-bool PeerManagerImpl::CanDirectFetch(const Consensus::Params &consensusParams)
+bool PeerManagerImpl::CanDirectFetch()
{
- return m_chainman.ActiveChain().Tip()->GetBlockTime() > GetAdjustedTime() - consensusParams.nPowTargetSpacing * 20;
+ return m_chainman.ActiveChain().Tip()->GetBlockTime() > GetAdjustedTime() - m_chainparams.GetConsensus().nPowTargetSpacing * 20;
}
static bool PeerHasHeader(CNodeState *state, const CBlockIndex *pindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
@@ -948,7 +947,7 @@ void PeerManagerImpl::InitializeNode(CNode *pnode)
}
}
-void PeerManagerImpl::ReattemptInitialBroadcast(CScheduler& scheduler) const
+void PeerManagerImpl::ReattemptInitialBroadcast(CScheduler& scheduler)
{
std::set<uint256> unbroadcast_txids = m_mempool.GetUnbroadcastTxs();
@@ -957,7 +956,7 @@ void PeerManagerImpl::ReattemptInitialBroadcast(CScheduler& scheduler) const
if (tx != nullptr) {
LOCK(cs_main);
- RelayTransaction(txid, tx->GetWitnessHash(), m_connman);
+ RelayTransaction(txid, tx->GetWitnessHash());
} else {
m_mempool.RemoveUnbroadcastTx(txid, true);
}
@@ -1193,13 +1192,13 @@ bool PeerManagerImpl::MaybePunishNodeForTx(NodeId nodeid, const TxValidationStat
// active chain if they are no more than a month older (both in time, and in
// best equivalent proof of work) than the best header chain we know about and
// we fully-validated them at some point.
-bool PeerManagerImpl::BlockRequestAllowed(const CBlockIndex* pindex, const Consensus::Params& consensusParams)
+bool PeerManagerImpl::BlockRequestAllowed(const CBlockIndex* pindex)
{
AssertLockHeld(cs_main);
if (m_chainman.ActiveChain().Contains(pindex)) return true;
return pindex->IsValid(BLOCK_VALID_SCRIPTS) && (pindexBestHeader != nullptr) &&
- (pindexBestHeader->GetBlockTime() - pindex->GetBlockTime() < STALE_RELAY_AGE_LIMIT) &&
- (GetBlockProofEquivalentTime(*pindexBestHeader, *pindex, *pindexBestHeader, consensusParams) < STALE_RELAY_AGE_LIMIT);
+ (pindexBestHeader->GetBlockTime() - pindex->GetBlockTime() < STALE_RELAY_AGE_LIMIT) &&
+ (GetBlockProofEquivalentTime(*pindexBestHeader, *pindex, *pindexBestHeader, m_chainparams.GetConsensus()) < STALE_RELAY_AGE_LIMIT);
}
std::unique_ptr<PeerManager> PeerManager::make(const CChainParams& chainparams, CConnman& connman, BanMan* banman,
@@ -1459,9 +1458,9 @@ void PeerManagerImpl::SendPings()
for(auto& it : m_peer_map) it.second->m_ping_queued = true;
}
-void RelayTransaction(const uint256& txid, const uint256& wtxid, const CConnman& connman)
+void PeerManagerImpl::RelayTransaction(const uint256& txid, const uint256& wtxid)
{
- connman.ForEachNode([&txid, &wtxid](CNode* pnode) EXCLUSIVE_LOCKS_REQUIRED(::cs_main) {
+ m_connman.ForEachNode([&txid, &wtxid](CNode* pnode) EXCLUSIVE_LOCKS_REQUIRED(::cs_main) {
AssertLockHeld(::cs_main);
CNodeState* state = State(pnode->GetId());
@@ -1529,13 +1528,12 @@ static void RelayAddress(const CNode& originator,
connman.ForEachNodeThen(std::move(sortfunc), std::move(pushfunc));
}
-void PeerManagerImpl::ProcessGetBlockData(CNode& pfrom, Peer& peer, const CChainParams& chainparams, const CInv& inv, CConnman& connman)
+void PeerManagerImpl::ProcessGetBlockData(CNode& pfrom, Peer& peer, const CInv& inv)
{
bool send = false;
std::shared_ptr<const CBlock> a_recent_block;
std::shared_ptr<const CBlockHeaderAndShortTxIDs> a_recent_compact_block;
bool fWitnessesPresentInARecentCompactBlock;
- const Consensus::Params& consensusParams = chainparams.GetConsensus();
{
LOCK(cs_most_recent_block);
a_recent_block = most_recent_block;
@@ -1561,7 +1559,7 @@ void PeerManagerImpl::ProcessGetBlockData(CNode& pfrom, Peer& peer, const CChain
} // release cs_main before calling ActivateBestChain
if (need_activate_chain) {
BlockValidationState state;
- if (!m_chainman.ActiveChainstate().ActivateBestChain(state, chainparams, a_recent_block)) {
+ if (!m_chainman.ActiveChainstate().ActivateBestChain(state, m_chainparams, a_recent_block)) {
LogPrint(BCLog::NET, "failed to activate chain (%s)\n", state.ToString());
}
}
@@ -1569,7 +1567,7 @@ void PeerManagerImpl::ProcessGetBlockData(CNode& pfrom, Peer& peer, const CChain
LOCK(cs_main);
const CBlockIndex* pindex = m_chainman.m_blockman.LookupBlockIndex(inv.hash);
if (pindex) {
- send = BlockRequestAllowed(pindex, consensusParams);
+ send = BlockRequestAllowed(pindex);
if (!send) {
LogPrint(BCLog::NET, "%s: ignoring request from peer=%i for old block that isn't in the main chain\n", __func__, pfrom.GetId());
}
@@ -1577,7 +1575,7 @@ void PeerManagerImpl::ProcessGetBlockData(CNode& pfrom, Peer& peer, const CChain
const CNetMsgMaker msgMaker(pfrom.GetCommonVersion());
// disconnect node in case we have reached the outbound limit for serving historical blocks
if (send &&
- connman.OutboundTargetReached(true) &&
+ m_connman.OutboundTargetReached(true) &&
(((pindexBestHeader != nullptr) && (pindexBestHeader->GetBlockTime() - pindex->GetBlockTime() > HISTORICAL_BLOCK_AGE)) || inv.IsMsgFilteredBlk()) &&
!pfrom.HasPermission(PF_DOWNLOAD) // nodes with the download permission may exceed target
) {
@@ -1608,23 +1606,24 @@ void PeerManagerImpl::ProcessGetBlockData(CNode& pfrom, Peer& peer, const CChain
// Fast-path: in this case it is possible to serve the block directly from disk,
// as the network format matches the format on disk
std::vector<uint8_t> block_data;
- if (!ReadRawBlockFromDisk(block_data, pindex, chainparams.MessageStart())) {
+ if (!ReadRawBlockFromDisk(block_data, pindex, m_chainparams.MessageStart())) {
assert(!"cannot load block from disk");
}
- connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::BLOCK, MakeSpan(block_data)));
+ m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::BLOCK, MakeSpan(block_data)));
// Don't set pblock as we've sent the block
} else {
// Send block from disk
std::shared_ptr<CBlock> pblockRead = std::make_shared<CBlock>();
- if (!ReadBlockFromDisk(*pblockRead, pindex, consensusParams))
+ if (!ReadBlockFromDisk(*pblockRead, pindex, m_chainparams.GetConsensus())) {
assert(!"cannot load block from disk");
+ }
pblock = pblockRead;
}
if (pblock) {
if (inv.IsMsgBlk()) {
- connman.PushMessage(&pfrom, msgMaker.Make(SERIALIZE_TRANSACTION_NO_WITNESS, NetMsgType::BLOCK, *pblock));
+ m_connman.PushMessage(&pfrom, msgMaker.Make(SERIALIZE_TRANSACTION_NO_WITNESS, NetMsgType::BLOCK, *pblock));
} else if (inv.IsMsgWitnessBlk()) {
- connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::BLOCK, *pblock));
+ m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::BLOCK, *pblock));
} else if (inv.IsMsgFilteredBlk()) {
bool sendMerkleBlock = false;
CMerkleBlock merkleBlock;
@@ -1636,7 +1635,7 @@ void PeerManagerImpl::ProcessGetBlockData(CNode& pfrom, Peer& peer, const CChain
}
}
if (sendMerkleBlock) {
- connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::MERKLEBLOCK, merkleBlock));
+ m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::MERKLEBLOCK, merkleBlock));
// CMerkleBlock just contains hashes, so also push any transactions in the block the client did not see
// This avoids hurting performance by pointlessly requiring a round-trip
// Note that there is currently no way for a node to request any single transactions we didn't send here -
@@ -1645,7 +1644,7 @@ void PeerManagerImpl::ProcessGetBlockData(CNode& pfrom, Peer& peer, const CChain
// however we MUST always provide at least what the remote peer needs
typedef std::pair<unsigned int, uint256> PairType;
for (PairType& pair : merkleBlock.vMatchedTxn)
- connman.PushMessage(&pfrom, msgMaker.Make(SERIALIZE_TRANSACTION_NO_WITNESS, NetMsgType::TX, *pblock->vtx[pair.first]));
+ m_connman.PushMessage(&pfrom, msgMaker.Make(SERIALIZE_TRANSACTION_NO_WITNESS, NetMsgType::TX, *pblock->vtx[pair.first]));
}
// else
// no response
@@ -1656,15 +1655,15 @@ void PeerManagerImpl::ProcessGetBlockData(CNode& pfrom, Peer& peer, const CChain
// instead we respond with the full, non-compact block.
bool fPeerWantsWitness = State(pfrom.GetId())->fWantsCmpctWitness;
int nSendFlags = fPeerWantsWitness ? 0 : SERIALIZE_TRANSACTION_NO_WITNESS;
- if (CanDirectFetch(consensusParams) && pindex->nHeight >= m_chainman.ActiveChain().Height() - MAX_CMPCTBLOCK_DEPTH) {
+ if (CanDirectFetch() && pindex->nHeight >= m_chainman.ActiveChain().Height() - MAX_CMPCTBLOCK_DEPTH) {
if ((fPeerWantsWitness || !fWitnessesPresentInARecentCompactBlock) && a_recent_compact_block && a_recent_compact_block->header.GetHash() == pindex->GetBlockHash()) {
- connman.PushMessage(&pfrom, msgMaker.Make(nSendFlags, NetMsgType::CMPCTBLOCK, *a_recent_compact_block));
+ m_connman.PushMessage(&pfrom, msgMaker.Make(nSendFlags, NetMsgType::CMPCTBLOCK, *a_recent_compact_block));
} else {
CBlockHeaderAndShortTxIDs cmpctblock(*pblock, fPeerWantsWitness);
- connman.PushMessage(&pfrom, msgMaker.Make(nSendFlags, NetMsgType::CMPCTBLOCK, cmpctblock));
+ m_connman.PushMessage(&pfrom, msgMaker.Make(nSendFlags, NetMsgType::CMPCTBLOCK, cmpctblock));
}
} else {
- connman.PushMessage(&pfrom, msgMaker.Make(nSendFlags, NetMsgType::BLOCK, *pblock));
+ m_connman.PushMessage(&pfrom, msgMaker.Make(nSendFlags, NetMsgType::BLOCK, *pblock));
}
}
}
@@ -1678,7 +1677,7 @@ void PeerManagerImpl::ProcessGetBlockData(CNode& pfrom, Peer& peer, const CChain
// wait for other stuff first.
std::vector<CInv> vInv;
vInv.push_back(CInv(MSG_BLOCK, m_chainman.ActiveChain().Tip()->GetBlockHash()));
- connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::INV, vInv));
+ m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::INV, vInv));
peer.m_continuation_block.SetNull();
}
}
@@ -1779,7 +1778,7 @@ void PeerManagerImpl::ProcessGetData(CNode& pfrom, Peer& peer, const std::atomic
if (it != peer.m_getdata_requests.end() && !pfrom.fPauseSend) {
const CInv &inv = *it++;
if (inv.IsGenBlkMsg()) {
- ProcessGetBlockData(pfrom, peer, m_chainparams, inv, m_connman);
+ ProcessGetBlockData(pfrom, peer, inv);
}
// else: If the first item on the queue is an unknown type, we erase it
// and continue processing the queue on the next call.
@@ -1927,10 +1926,9 @@ void PeerManagerImpl::ProcessHeadersMessage(CNode& pfrom, const Peer& peer,
m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::GETHEADERS, m_chainman.ActiveChain().GetLocator(pindexLast), uint256()));
}
- bool fCanDirectFetch = CanDirectFetch(m_chainparams.GetConsensus());
// If this set of headers is valid and ends in a block with at least as
// much work as our tip, download as much as possible.
- if (fCanDirectFetch && pindexLast->IsValid(BLOCK_VALID_TREE) && m_chainman.ActiveChain().Tip()->nChainWork <= pindexLast->nChainWork) {
+ if (CanDirectFetch() && pindexLast->IsValid(BLOCK_VALID_TREE) && m_chainman.ActiveChain().Tip()->nChainWork <= pindexLast->nChainWork) {
std::vector<const CBlockIndex*> vToFetch;
const CBlockIndex *pindexWalk = pindexLast;
// Calculate all the blocks we'd need to switch to pindexLast, up to a limit.
@@ -2041,7 +2039,7 @@ void PeerManagerImpl::ProcessOrphanTx(std::set<uint256>& orphan_work_set)
if (result.m_result_type == MempoolAcceptResult::ResultType::VALID) {
LogPrint(BCLog::MEMPOOL, " accepted orphan tx %s\n", orphanHash.ToString());
- RelayTransaction(orphanHash, porphanTx->GetWitnessHash(), m_connman);
+ RelayTransaction(orphanHash, porphanTx->GetWitnessHash());
m_orphanage.AddChildrenToWorkSet(*porphanTx, orphan_work_set);
m_orphanage.EraseTx(orphanHash);
for (const CTransactionRef& removedTx : result.m_replaced_transactions.value()) {
@@ -2103,7 +2101,6 @@ void PeerManagerImpl::ProcessOrphanTx(std::set<uint256>& orphan_work_set)
* May disconnect from the peer in the case of a bad request.
*
* @param[in] peer The peer that we received the request from
- * @param[in] chain_params Chain parameters
* @param[in] filter_type The filter type the request is for. Must be basic filters.
* @param[in] start_height The start height for the request
* @param[in] stop_hash The stop_hash for the request
@@ -2112,11 +2109,11 @@ void PeerManagerImpl::ProcessOrphanTx(std::set<uint256>& orphan_work_set)
* @param[out] filter_index The filter index, if the request can be serviced.
* @return True if the request can be serviced.
*/
-bool PeerManagerImpl::PrepareBlockFilterRequest(CNode& peer, const CChainParams& chain_params,
- BlockFilterType filter_type, uint32_t start_height,
- const uint256& stop_hash, uint32_t max_height_diff,
- const CBlockIndex*& stop_index,
- BlockFilterIndex*& filter_index)
+bool PeerManagerImpl::PrepareBlockFilterRequest(CNode& peer,
+ BlockFilterType filter_type, uint32_t start_height,
+ const uint256& stop_hash, uint32_t max_height_diff,
+ const CBlockIndex*& stop_index,
+ BlockFilterIndex*& filter_index)
{
const bool supported_filter_type =
(filter_type == BlockFilterType::BASIC &&
@@ -2133,7 +2130,7 @@ bool PeerManagerImpl::PrepareBlockFilterRequest(CNode& peer, const CChainParams&
stop_index = m_chainman.m_blockman.LookupBlockIndex(stop_hash);
// Check that the stop block exists and the peer would be allowed to fetch it.
- if (!stop_index || !BlockRequestAllowed(stop_index, chain_params.GetConsensus())) {
+ if (!stop_index || !BlockRequestAllowed(stop_index)) {
LogPrint(BCLog::NET, "peer %d requested invalid block hash: %s\n",
peer.GetId(), stop_hash.ToString());
peer.fDisconnect = true;
@@ -2172,11 +2169,8 @@ bool PeerManagerImpl::PrepareBlockFilterRequest(CNode& peer, const CChainParams&
*
* @param[in] peer The peer that we received the request from
* @param[in] vRecv The raw message received
- * @param[in] chain_params Chain parameters
- * @param[in] connman Pointer to the connection manager
*/
-void PeerManagerImpl::ProcessGetCFilters(CNode& peer, CDataStream& vRecv, const CChainParams& chain_params,
- CConnman& connman)
+void PeerManagerImpl::ProcessGetCFilters(CNode& peer, CDataStream& vRecv)
{
uint8_t filter_type_ser;
uint32_t start_height;
@@ -2188,7 +2182,7 @@ void PeerManagerImpl::ProcessGetCFilters(CNode& peer, CDataStream& vRecv, const
const CBlockIndex* stop_index;
BlockFilterIndex* filter_index;
- if (!PrepareBlockFilterRequest(peer, chain_params, filter_type, start_height, stop_hash,
+ if (!PrepareBlockFilterRequest(peer, filter_type, start_height, stop_hash,
MAX_GETCFILTERS_SIZE, stop_index, filter_index)) {
return;
}
@@ -2203,7 +2197,7 @@ void PeerManagerImpl::ProcessGetCFilters(CNode& peer, CDataStream& vRecv, const
for (const auto& filter : filters) {
CSerializedNetMsg msg = CNetMsgMaker(peer.GetCommonVersion())
.Make(NetMsgType::CFILTER, filter);
- connman.PushMessage(&peer, std::move(msg));
+ m_connman.PushMessage(&peer, std::move(msg));
}
}
@@ -2214,11 +2208,8 @@ void PeerManagerImpl::ProcessGetCFilters(CNode& peer, CDataStream& vRecv, const
*
* @param[in] peer The peer that we received the request from
* @param[in] vRecv The raw message received
- * @param[in] chain_params Chain parameters
- * @param[in] connman Pointer to the connection manager
*/
-void PeerManagerImpl::ProcessGetCFHeaders(CNode& peer, CDataStream& vRecv, const CChainParams& chain_params,
- CConnman& connman)
+void PeerManagerImpl::ProcessGetCFHeaders(CNode& peer, CDataStream& vRecv)
{
uint8_t filter_type_ser;
uint32_t start_height;
@@ -2230,7 +2221,7 @@ void PeerManagerImpl::ProcessGetCFHeaders(CNode& peer, CDataStream& vRecv, const
const CBlockIndex* stop_index;
BlockFilterIndex* filter_index;
- if (!PrepareBlockFilterRequest(peer, chain_params, filter_type, start_height, stop_hash,
+ if (!PrepareBlockFilterRequest(peer, filter_type, start_height, stop_hash,
MAX_GETCFHEADERS_SIZE, stop_index, filter_index)) {
return;
}
@@ -2259,7 +2250,7 @@ void PeerManagerImpl::ProcessGetCFHeaders(CNode& peer, CDataStream& vRecv, const
stop_index->GetBlockHash(),
prev_header,
filter_hashes);
- connman.PushMessage(&peer, std::move(msg));
+ m_connman.PushMessage(&peer, std::move(msg));
}
/**
@@ -2269,11 +2260,8 @@ void PeerManagerImpl::ProcessGetCFHeaders(CNode& peer, CDataStream& vRecv, const
*
* @param[in] peer The peer that we received the request from
* @param[in] vRecv The raw message received
- * @param[in] chain_params Chain parameters
- * @param[in] connman Pointer to the connection manager
*/
-void PeerManagerImpl::ProcessGetCFCheckPt(CNode& peer, CDataStream& vRecv, const CChainParams& chain_params,
- CConnman& connman)
+void PeerManagerImpl::ProcessGetCFCheckPt(CNode& peer, CDataStream& vRecv)
{
uint8_t filter_type_ser;
uint256 stop_hash;
@@ -2284,7 +2272,7 @@ void PeerManagerImpl::ProcessGetCFCheckPt(CNode& peer, CDataStream& vRecv, const
const CBlockIndex* stop_index;
BlockFilterIndex* filter_index;
- if (!PrepareBlockFilterRequest(peer, chain_params, filter_type, /*start_height=*/0, stop_hash,
+ if (!PrepareBlockFilterRequest(peer, filter_type, /*start_height=*/0, stop_hash,
/*max_height_diff=*/std::numeric_limits<uint32_t>::max(),
stop_index, filter_index)) {
return;
@@ -2310,7 +2298,7 @@ void PeerManagerImpl::ProcessGetCFCheckPt(CNode& peer, CDataStream& vRecv, const
filter_type_ser,
stop_index->GetBlockHash(),
headers);
- connman.PushMessage(&peer, std::move(msg));
+ m_connman.PushMessage(&peer, std::move(msg));
}
void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type, CDataStream& vRecv,
@@ -2948,7 +2936,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
return;
}
- if (!BlockRequestAllowed(pindex, m_chainparams.GetConsensus())) {
+ if (!BlockRequestAllowed(pindex)) {
LogPrint(BCLog::NET, "%s: ignoring request from peer=%i for old block header that isn't in the main chain\n", __func__, pfrom.GetId());
return;
}
@@ -3045,7 +3033,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
LogPrintf("Not relaying non-mempool transaction %s from forcerelay peer=%d\n", tx.GetHash().ToString(), pfrom.GetId());
} else {
LogPrintf("Force relaying tx %s from peer=%d\n", tx.GetHash().ToString(), pfrom.GetId());
- RelayTransaction(tx.GetHash(), tx.GetWitnessHash(), m_connman);
+ RelayTransaction(tx.GetHash(), tx.GetWitnessHash());
}
}
return;
@@ -3060,7 +3048,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
// requests for it.
m_txrequest.ForgetTxHash(tx.GetHash());
m_txrequest.ForgetTxHash(tx.GetWitnessHash());
- RelayTransaction(tx.GetHash(), tx.GetWitnessHash(), m_connman);
+ RelayTransaction(tx.GetHash(), tx.GetWitnessHash());
m_orphanage.AddChildrenToWorkSet(tx, peer->m_orphan_work_set);
pfrom.nLastTXTime = GetTime();
@@ -3286,8 +3274,9 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
}
// If we're not close to tip yet, give up and let parallel block fetch work its magic
- if (!fAlreadyInFlight && !CanDirectFetch(m_chainparams.GetConsensus()))
+ if (!fAlreadyInFlight && !CanDirectFetch()) {
return;
+ }
if (IsWitnessEnabled(pindex->pprev, m_chainparams.GetConsensus()) && !nodestate->fSupportsDesiredCmpctVersion) {
// Don't bother trying to process compact blocks from v1 peers
@@ -3780,17 +3769,17 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
}
if (msg_type == NetMsgType::GETCFILTERS) {
- ProcessGetCFilters(pfrom, vRecv, m_chainparams, m_connman);
+ ProcessGetCFilters(pfrom, vRecv);
return;
}
if (msg_type == NetMsgType::GETCFHEADERS) {
- ProcessGetCFHeaders(pfrom, vRecv, m_chainparams, m_connman);
+ ProcessGetCFHeaders(pfrom, vRecv);
return;
}
if (msg_type == NetMsgType::GETCFCHECKPT) {
- ProcessGetCFCheckPt(pfrom, vRecv, m_chainparams, m_connman);
+ ProcessGetCFCheckPt(pfrom, vRecv);
return;
}
@@ -4105,7 +4094,7 @@ void PeerManagerImpl::CheckForStaleTipAndEvictPeers()
m_stale_tip_check_time = time_in_seconds + STALE_CHECK_INTERVAL;
}
- if (!m_initial_sync_finished && CanDirectFetch(m_chainparams.GetConsensus())) {
+ if (!m_initial_sync_finished && CanDirectFetch()) {
m_connman.StartExtraBlockRelayPeers();
m_initial_sync_finished = true;
}
@@ -4218,7 +4207,7 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
if (pto->m_next_local_addr_send != 0us) {
pto->m_addr_known->reset();
}
- if (Optional<CAddress> local_addr = GetLocalAddrForPeer(pto)) {
+ if (std::optional<CAddress> local_addr = GetLocalAddrForPeer(pto)) {
FastRandomContext insecure_rand;
pto->PushAddress(*local_addr, insecure_rand);
}
diff --git a/src/net_processing.h b/src/net_processing.h
index 6f900410a7..f6f2d73721 100644
--- a/src/net_processing.h
+++ b/src/net_processing.h
@@ -47,6 +47,10 @@ public:
/** Whether this node ignores txs received over p2p. */
virtual bool IgnoresIncomingTxs() = 0;
+ /** Relay transaction to all peers. */
+ virtual void RelayTransaction(const uint256& txid, const uint256& wtxid)
+ EXCLUSIVE_LOCKS_REQUIRED(cs_main) = 0;
+
/** Send ping message to all peers */
virtual void SendPings() = 0;
@@ -71,7 +75,4 @@ public:
const std::chrono::microseconds time_received, const std::atomic<bool>& interruptMsgProc) = 0;
};
-/** Relay transaction to every node */
-void RelayTransaction(const uint256& txid, const uint256& wtxid, const CConnman& connman) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
-
#endif // BITCOIN_NET_PROCESSING_H
diff --git a/src/netbase.cpp b/src/netbase.cpp
index b95bb05e71..ac2392ebed 100644
--- a/src/netbase.cpp
+++ b/src/netbase.cpp
@@ -166,21 +166,6 @@ static bool LookupIntern(const std::string& name, std::vector<CNetAddr>& vIP, un
return (vIP.size() > 0);
}
-/**
- * Resolve a host string to its corresponding network addresses.
- *
- * @param name The string representing a host. Could be a name or a numerical
- * IP address (IPv6 addresses in their bracketed form are
- * allowed).
- * @param[out] vIP The resulting network addresses to which the specified host
- * string resolved.
- *
- * @returns Whether or not the specified host string successfully resolved to
- * any resulting network addresses.
- *
- * @see Lookup(const char *, std::vector<CService>&, int, bool, unsigned int)
- * for additional parameter descriptions.
- */
bool LookupHost(const std::string& name, std::vector<CNetAddr>& vIP, unsigned int nMaxSolutions, bool fAllowLookup, DNSLookupFn dns_lookup_function)
{
if (!ValidAsCString(name)) {
@@ -196,12 +181,6 @@ bool LookupHost(const std::string& name, std::vector<CNetAddr>& vIP, unsigned in
return LookupIntern(strHost, vIP, nMaxSolutions, fAllowLookup, dns_lookup_function);
}
- /**
- * Resolve a host string to its first corresponding network address.
- *
- * @see LookupHost(const std::string&, std::vector<CNetAddr>&, unsigned int, bool) for
- * additional parameter descriptions.
- */
bool LookupHost(const std::string& name, CNetAddr& addr, bool fAllowLookup, DNSLookupFn dns_lookup_function)
{
if (!ValidAsCString(name)) {
@@ -215,26 +194,6 @@ bool LookupHost(const std::string& name, CNetAddr& addr, bool fAllowLookup, DNSL
return true;
}
-/**
- * Resolve a service string to its corresponding service.
- *
- * @param name The string representing a service. Could be a name or a
- * numerical IP address (IPv6 addresses should be in their
- * disambiguated bracketed form), optionally followed by a port
- * number. (e.g. example.com:8333 or
- * [2001:db8:85a3:8d3:1319:8a2e:370:7348]:420)
- * @param[out] vAddr The resulting services to which the specified service string
- * resolved.
- * @param portDefault The default port for resulting services if not specified
- * by the service string.
- * @param fAllowLookup Whether or not hostname lookups are permitted. If yes,
- * external queries may be performed.
- * @param nMaxSolutions The maximum number of results we want, specifying 0
- * means "as many solutions as we get."
- *
- * @returns Whether or not the service string successfully resolved to any
- * resulting services.
- */
bool Lookup(const std::string& name, std::vector<CService>& vAddr, int portDefault, bool fAllowLookup, unsigned int nMaxSolutions, DNSLookupFn dns_lookup_function)
{
if (name.empty() || !ValidAsCString(name)) {
@@ -254,12 +213,6 @@ bool Lookup(const std::string& name, std::vector<CService>& vAddr, int portDefau
return true;
}
-/**
- * Resolve a service string to its first corresponding service.
- *
- * @see Lookup(const char *, std::vector<CService>&, int, bool, unsigned int)
- * for additional parameter descriptions.
- */
bool Lookup(const std::string& name, CService& addr, int portDefault, bool fAllowLookup, DNSLookupFn dns_lookup_function)
{
if (!ValidAsCString(name)) {
@@ -273,16 +226,6 @@ bool Lookup(const std::string& name, CService& addr, int portDefault, bool fAllo
return true;
}
-/**
- * Resolve a service string with a numeric IP to its first corresponding
- * service.
- *
- * @returns The resulting CService if the resolution was successful, [::]:0
- * otherwise.
- *
- * @see Lookup(const char *, CService&, int, bool) for additional parameter
- * descriptions.
- */
CService LookupNumeric(const std::string& name, int portDefault, DNSLookupFn dns_lookup_function)
{
if (!ValidAsCString(name)) {
@@ -420,24 +363,6 @@ static std::string Socks5ErrorString(uint8_t err)
}
}
-/**
- * Connect to a specified destination service through an already connected
- * SOCKS5 proxy.
- *
- * @param strDest The destination fully-qualified domain name.
- * @param port The destination port.
- * @param auth The credentials with which to authenticate with the specified
- * SOCKS5 proxy.
- * @param sock The SOCKS5 proxy socket.
- *
- * @returns Whether or not the operation succeeded.
- *
- * @note The specified SOCKS5 proxy socket must already be connected to the
- * SOCKS5 proxy.
- *
- * @see <a href="https://www.ietf.org/rfc/rfc1928.txt">RFC1928: SOCKS Protocol
- * Version 5</a>
- */
bool Socks5(const std::string& strDest, int port, const ProxyCredentials* auth, const Sock& sock)
{
IntrRecvError recvr;
@@ -612,18 +537,6 @@ static void LogConnectFailure(bool manual_connection, const char* fmt, const Arg
}
}
-/**
- * Try to connect to the specified service on the specified socket.
- *
- * @param addrConnect The service to which to connect.
- * @param hSocket The socket on which to connect.
- * @param nTimeout Wait this many milliseconds for the connection to be
- * established.
- * @param manual_connection Whether or not the connection was manually requested
- * (e.g. through the addnode RPC)
- *
- * @returns Whether or not a connection was successfully made.
- */
bool ConnectSocketDirectly(const CService &addrConnect, const SOCKET& hSocket, int nTimeout, bool manual_connection)
{
// Create a sockaddr from the specified service.
@@ -722,22 +635,6 @@ bool GetProxy(enum Network net, proxyType &proxyInfoOut) {
return true;
}
-/**
- * Set the name proxy to use for all connections to nodes specified by a
- * hostname. After setting this proxy, connecting to a node specified by a
- * hostname won't result in a local lookup of said hostname, rather, connect to
- * the node by asking the name proxy for a proxy connection to the hostname,
- * effectively delegating the hostname lookup to the specified proxy.
- *
- * This delegation increases privacy for those who set the name proxy as they no
- * longer leak their external hostname queries to their DNS servers.
- *
- * @returns Whether or not the operation succeeded.
- *
- * @note SOCKS5's support for UDP-over-SOCKS5 has been considered, but no SOCK5
- * server in common use (most notably Tor) actually implements UDP
- * support, and a DNS resolver is beyond the scope of this project.
- */
bool SetNameProxy(const proxyType &addrProxy) {
if (!addrProxy.IsValid())
return false;
@@ -768,21 +665,6 @@ bool IsProxy(const CNetAddr &addr) {
return false;
}
-/**
- * Connect to a specified destination service through a SOCKS5 proxy by first
- * connecting to the SOCKS5 proxy.
- *
- * @param proxy The SOCKS5 proxy.
- * @param strDest The destination service to which to connect.
- * @param port The destination port.
- * @param sock The socket on which to connect to the SOCKS5 proxy.
- * @param nTimeout Wait this many milliseconds for the connection to the SOCKS5
- * proxy to be established.
- * @param[out] outProxyConnectionFailed Whether or not the connection to the
- * SOCKS5 proxy failed.
- *
- * @returns Whether or not the operation succeeded.
- */
bool ConnectThroughProxy(const proxyType& proxy, const std::string& strDest, int port, const Sock& sock, int nTimeout, bool& outProxyConnectionFailed)
{
// first connect to proxy server
@@ -806,17 +688,6 @@ bool ConnectThroughProxy(const proxyType& proxy, const std::string& strDest, int
return true;
}
-/**
- * Parse and resolve a specified subnet string into the appropriate internal
- * representation.
- *
- * @param strSubnet A string representation of a subnet of the form `network
- * address [ "/", ( CIDR-style suffix | netmask ) ]`(e.g.
- * `2001:db8::/32`, `192.0.2.0/255.255.255.0`, or `8.8.8.8`).
- * @param ret The resulting internal representation of a subnet.
- *
- * @returns Whether the operation succeeded or not.
- */
bool LookupSubNet(const std::string& strSubnet, CSubNet& ret, DNSLookupFn dns_lookup_function)
{
if (!ValidAsCString(strSubnet)) {
diff --git a/src/netbase.h b/src/netbase.h
index 227da1a63b..e98a21ce1f 100644
--- a/src/netbase.h
+++ b/src/netbase.h
@@ -76,6 +76,22 @@ std::vector<std::string> GetNetworkNames(bool append_unroutable = false);
bool SetProxy(enum Network net, const proxyType &addrProxy);
bool GetProxy(enum Network net, proxyType &proxyInfoOut);
bool IsProxy(const CNetAddr &addr);
+/**
+ * Set the name proxy to use for all connections to nodes specified by a
+ * hostname. After setting this proxy, connecting to a node specified by a
+ * hostname won't result in a local lookup of said hostname, rather, connect to
+ * the node by asking the name proxy for a proxy connection to the hostname,
+ * effectively delegating the hostname lookup to the specified proxy.
+ *
+ * This delegation increases privacy for those who set the name proxy as they no
+ * longer leak their external hostname queries to their DNS servers.
+ *
+ * @returns Whether or not the operation succeeded.
+ *
+ * @note SOCKS5's support for UDP-over-SOCKS5 has been considered, but no SOCK5
+ * server in common use (most notably Tor) actually implements UDP
+ * support, and a DNS resolver is beyond the scope of this project.
+ */
bool SetNameProxy(const proxyType &addrProxy);
bool HaveNameProxy();
bool GetNameProxy(proxyType &nameProxyOut);
@@ -83,11 +99,83 @@ bool GetNameProxy(proxyType &nameProxyOut);
using DNSLookupFn = std::function<std::vector<CNetAddr>(const std::string&, bool)>;
extern DNSLookupFn g_dns_lookup;
+/**
+ * Resolve a host string to its corresponding network addresses.
+ *
+ * @param name The string representing a host. Could be a name or a numerical
+ * IP address (IPv6 addresses in their bracketed form are
+ * allowed).
+ * @param[out] vIP The resulting network addresses to which the specified host
+ * string resolved.
+ *
+ * @returns Whether or not the specified host string successfully resolved to
+ * any resulting network addresses.
+ *
+ * @see Lookup(const std::string&, std::vector<CService>&, int, bool, unsigned int, DNSLookupFn)
+ * for additional parameter descriptions.
+ */
bool LookupHost(const std::string& name, std::vector<CNetAddr>& vIP, unsigned int nMaxSolutions, bool fAllowLookup, DNSLookupFn dns_lookup_function = g_dns_lookup);
+
+/**
+ * Resolve a host string to its first corresponding network address.
+ *
+ * @see LookupHost(const std::string&, std::vector<CNetAddr>&, unsigned int, bool, DNSLookupFn)
+ * for additional parameter descriptions.
+ */
bool LookupHost(const std::string& name, CNetAddr& addr, bool fAllowLookup, DNSLookupFn dns_lookup_function = g_dns_lookup);
-bool Lookup(const std::string& name, CService& addr, int portDefault, bool fAllowLookup, DNSLookupFn dns_lookup_function = g_dns_lookup);
+
+/**
+ * Resolve a service string to its corresponding service.
+ *
+ * @param name The string representing a service. Could be a name or a
+ * numerical IP address (IPv6 addresses should be in their
+ * disambiguated bracketed form), optionally followed by a port
+ * number. (e.g. example.com:8333 or
+ * [2001:db8:85a3:8d3:1319:8a2e:370:7348]:420)
+ * @param[out] vAddr The resulting services to which the specified service string
+ * resolved.
+ * @param portDefault The default port for resulting services if not specified
+ * by the service string.
+ * @param fAllowLookup Whether or not hostname lookups are permitted. If yes,
+ * external queries may be performed.
+ * @param nMaxSolutions The maximum number of results we want, specifying 0
+ * means "as many solutions as we get."
+ *
+ * @returns Whether or not the service string successfully resolved to any
+ * resulting services.
+ */
bool Lookup(const std::string& name, std::vector<CService>& vAddr, int portDefault, bool fAllowLookup, unsigned int nMaxSolutions, DNSLookupFn dns_lookup_function = g_dns_lookup);
+
+/**
+ * Resolve a service string to its first corresponding service.
+ *
+ * @see Lookup(const std::string&, std::vector<CService>&, int, bool, unsigned int, DNSLookupFn)
+ * for additional parameter descriptions.
+ */
+bool Lookup(const std::string& name, CService& addr, int portDefault, bool fAllowLookup, DNSLookupFn dns_lookup_function = g_dns_lookup);
+
+/**
+ * Resolve a service string with a numeric IP to its first corresponding
+ * service.
+ *
+ * @returns The resulting CService if the resolution was successful, [::]:0 otherwise.
+ *
+ * @see Lookup(const std::string&, std::vector<CService>&, int, bool, unsigned int, DNSLookupFn)
+ * for additional parameter descriptions.
+ */
CService LookupNumeric(const std::string& name, int portDefault = 0, DNSLookupFn dns_lookup_function = g_dns_lookup);
+
+/**
+ * Parse and resolve a specified subnet string into the appropriate internal
+ * representation.
+ *
+ * @param strSubnet A string representation of a subnet of the form `network
+ * address [ "/", ( CIDR-style suffix | netmask ) ]`(e.g.
+ * `2001:db8::/32`, `192.0.2.0/255.255.255.0`, or `8.8.8.8`).
+ * @param ret The resulting internal representation of a subnet.
+ *
+ * @returns Whether the operation succeeded or not.
+ */
bool LookupSubNet(const std::string& strSubnet, CSubNet& subnet, DNSLookupFn dns_lookup_function = g_dns_lookup);
/**
@@ -102,14 +190,61 @@ std::unique_ptr<Sock> CreateSockTCP(const CService& address_family);
*/
extern std::function<std::unique_ptr<Sock>(const CService&)> CreateSock;
-bool ConnectSocketDirectly(const CService &addrConnect, const SOCKET& hSocketRet, int nTimeout, bool manual_connection);
+/**
+ * Try to connect to the specified service on the specified socket.
+ *
+ * @param addrConnect The service to which to connect.
+ * @param hSocket The socket on which to connect.
+ * @param nTimeout Wait this many milliseconds for the connection to be
+ * established.
+ * @param manual_connection Whether or not the connection was manually requested
+ * (e.g. through the addnode RPC)
+ *
+ * @returns Whether or not a connection was successfully made.
+ */
+bool ConnectSocketDirectly(const CService &addrConnect, const SOCKET& hSocket, int nTimeout, bool manual_connection);
+
+/**
+ * Connect to a specified destination service through a SOCKS5 proxy by first
+ * connecting to the SOCKS5 proxy.
+ *
+ * @param proxy The SOCKS5 proxy.
+ * @param strDest The destination service to which to connect.
+ * @param port The destination port.
+ * @param sock The socket on which to connect to the SOCKS5 proxy.
+ * @param nTimeout Wait this many milliseconds for the connection to the SOCKS5
+ * proxy to be established.
+ * @param[out] outProxyConnectionFailed Whether or not the connection to the
+ * SOCKS5 proxy failed.
+ *
+ * @returns Whether or not the operation succeeded.
+ */
bool ConnectThroughProxy(const proxyType& proxy, const std::string& strDest, int port, const Sock& sock, int nTimeout, bool& outProxyConnectionFailed);
+
/** Disable or enable blocking-mode for a socket */
bool SetSocketNonBlocking(const SOCKET& hSocket, bool fNonBlocking);
/** Set the TCP_NODELAY flag on a socket */
bool SetSocketNoDelay(const SOCKET& hSocket);
void InterruptSocks5(bool interrupt);
+/**
+ * Connect to a specified destination service through an already connected
+ * SOCKS5 proxy.
+ *
+ * @param strDest The destination fully-qualified domain name.
+ * @param port The destination port.
+ * @param auth The credentials with which to authenticate with the specified
+ * SOCKS5 proxy.
+ * @param sock The SOCKS5 proxy socket.
+ *
+ * @returns Whether or not the operation succeeded.
+ *
+ * @note The specified SOCKS5 proxy socket must already be connected to the
+ * SOCKS5 proxy.
+ *
+ * @see <a href="https://www.ietf.org/rfc/rfc1928.txt">RFC1928: SOCKS Protocol
+ * Version 5</a>
+ */
bool Socks5(const std::string& strDest, int port, const ProxyCredentials* auth, const Sock& socket);
#endif // BITCOIN_NETBASE_H
diff --git a/src/node/interfaces.cpp b/src/node/interfaces.cpp
index 9406ef07c5..50c8c29175 100644
--- a/src/node/interfaces.cpp
+++ b/src/node/interfaces.cpp
@@ -50,6 +50,7 @@
#endif
#include <memory>
+#include <optional>
#include <utility>
using interfaces::BlockTip;
@@ -415,7 +416,7 @@ class ChainImpl : public Chain
{
public:
explicit ChainImpl(NodeContext& node) : m_node(node) {}
- Optional<int> getHeight() override
+ std::optional<int> getHeight() override
{
LOCK(::cs_main);
const CChain& active = Assert(m_node.chainman)->ActiveChain();
@@ -423,7 +424,7 @@ public:
if (height >= 0) {
return height;
}
- return nullopt;
+ return std::nullopt;
}
uint256 getBlockHash(int height) override
{
@@ -452,7 +453,7 @@ public:
assert(std::addressof(::ChainActive()) == std::addressof(m_node.chainman->ActiveChain()));
return CheckFinalTx(m_node.chainman->ActiveChain().Tip(), tx);
}
- Optional<int> findLocatorFork(const CBlockLocator& locator) override
+ std::optional<int> findLocatorFork(const CBlockLocator& locator) override
{
LOCK(cs_main);
const CChain& active = Assert(m_node.chainman)->ActiveChain();
@@ -460,7 +461,7 @@ public:
if (CBlockIndex* fork = m_node.chainman->m_blockman.FindForkInGlobalIndex(active, locator)) {
return fork->nHeight;
}
- return nullopt;
+ return std::nullopt;
}
bool findBlock(const uint256& hash, const FoundBlock& block) override
{
@@ -518,7 +519,7 @@ public:
assert(std::addressof(g_chainman) == std::addressof(*m_node.chainman));
return GuessVerificationProgress(Params().TxData(), m_node.chainman->m_blockman.LookupBlockIndex(block_hash));
}
- bool hasBlocks(const uint256& block_hash, int min_height, Optional<int> max_height) override
+ bool hasBlocks(const uint256& block_hash, int min_height, std::optional<int> max_height) override
{
// hasBlocks returns true if all ancestors of block_hash in specified
// range have block data (are not pruned), false if any ancestors in
diff --git a/src/node/psbt.h b/src/node/psbt.h
index 7384dc415c..def4385c09 100644
--- a/src/node/psbt.h
+++ b/src/node/psbt.h
@@ -7,6 +7,8 @@
#include <psbt.h>
+#include <optional>
+
/**
* Holds an analysis of one input from a PSBT
*/
@@ -25,18 +27,18 @@ struct PSBTInputAnalysis {
* Holds the results of AnalyzePSBT (miscellaneous information about a PSBT)
*/
struct PSBTAnalysis {
- Optional<size_t> estimated_vsize; //!< Estimated weight of the transaction
- Optional<CFeeRate> estimated_feerate; //!< Estimated feerate (fee / weight) of the transaction
- Optional<CAmount> fee; //!< Amount of fee being paid by the transaction
- std::vector<PSBTInputAnalysis> inputs; //!< More information about the individual inputs of the transaction
- PSBTRole next; //!< Which of the BIP 174 roles needs to handle the transaction next
- std::string error; //!< Error message
+ std::optional<size_t> estimated_vsize; //!< Estimated weight of the transaction
+ std::optional<CFeeRate> estimated_feerate; //!< Estimated feerate (fee / weight) of the transaction
+ std::optional<CAmount> fee; //!< Amount of fee being paid by the transaction
+ std::vector<PSBTInputAnalysis> inputs; //!< More information about the individual inputs of the transaction
+ PSBTRole next; //!< Which of the BIP 174 roles needs to handle the transaction next
+ std::string error; //!< Error message
void SetInvalid(std::string err_msg)
{
- estimated_vsize = nullopt;
- estimated_feerate = nullopt;
- fee = nullopt;
+ estimated_vsize = std::nullopt;
+ estimated_feerate = std::nullopt;
+ fee = std::nullopt;
inputs.clear();
next = PSBTRole::CREATOR;
error = err_msg;
diff --git a/src/node/transaction.cpp b/src/node/transaction.cpp
index 97763f4fa2..f47e85aceb 100644
--- a/src/node/transaction.cpp
+++ b/src/node/transaction.cpp
@@ -29,9 +29,9 @@ static TransactionError HandleATMPError(const TxValidationState& state, std::str
TransactionError BroadcastTransaction(NodeContext& node, const CTransactionRef tx, std::string& err_string, const CAmount& max_tx_fee, bool relay, bool wait_callback)
{
// BroadcastTransaction can be called by either sendrawtransaction RPC or wallet RPCs.
- // node.connman is assigned both before chain clients and before RPC server is accepting calls,
- // and reset after chain clients and RPC sever are stopped. node.connman should never be null here.
- assert(node.connman);
+ // node.peerman is assigned both before chain clients and before RPC server is accepting calls,
+ // and reset after chain clients and RPC sever are stopped. node.peerman should never be null here.
+ assert(node.peerman);
assert(node.mempool);
std::promise<void> promise;
uint256 hashTx = tx->GetHash();
@@ -101,7 +101,7 @@ TransactionError BroadcastTransaction(NodeContext& node, const CTransactionRef t
node.mempool->AddUnbroadcastTx(hashTx);
LOCK(cs_main);
- RelayTransaction(hashTx, tx->GetWitnessHash(), *node.connman);
+ node.peerman->RelayTransaction(hashTx, tx->GetWitnessHash());
}
return TransactionError::OK;
diff --git a/src/optional.h b/src/optional.h
deleted file mode 100644
index 583c56eabd..0000000000
--- a/src/optional.h
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright (c) 2017-2020 The Bitcoin Core developers
-// Distributed under the MIT software license, see the accompanying
-// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-
-#ifndef BITCOIN_OPTIONAL_H
-#define BITCOIN_OPTIONAL_H
-
-#include <optional>
-#include <utility>
-
-//! Substitute for C++17 std::optional
-//! DEPRECATED use std::optional in new code.
-template <typename T>
-using Optional = std::optional<T>;
-
-//! Substitute for C++17 std::nullopt
-//! DEPRECATED use std::nullopt in new code.
-static auto& nullopt = std::nullopt;
-
-#endif // BITCOIN_OPTIONAL_H
diff --git a/src/psbt.h b/src/psbt.h
index b566726ee3..96ae39fdb8 100644
--- a/src/psbt.h
+++ b/src/psbt.h
@@ -7,13 +7,14 @@
#include <attributes.h>
#include <node/transaction.h>
-#include <optional.h>
#include <policy/feerate.h>
#include <primitives/transaction.h>
#include <pubkey.h>
#include <script/sign.h>
#include <script/signingprovider.h>
+#include <optional>
+
// Magic bytes
static constexpr uint8_t PSBT_MAGIC_BYTES[5] = {'p', 's', 'b', 't', 0xff};
@@ -389,7 +390,7 @@ struct PSBTOutput
/** A version of CTransaction with the PSBT format*/
struct PartiallySignedTransaction
{
- Optional<CMutableTransaction> tx;
+ std::optional<CMutableTransaction> tx;
std::vector<PSBTInput> inputs;
std::vector<PSBTOutput> outputs;
std::map<std::vector<unsigned char>, std::vector<unsigned char>> unknown;
diff --git a/src/qt/addressbookpage.cpp b/src/qt/addressbookpage.cpp
index ab6168a541..9927e925ac 100644
--- a/src/qt/addressbookpage.cpp
+++ b/src/qt/addressbookpage.cpp
@@ -295,7 +295,7 @@ void AddressBookPage::on_exportButton_clicked()
// CSV is currently the only supported format
QString filename = GUIUtil::getSaveFileName(this,
tr("Export Address List"), QString(),
- tr("Comma separated file (*.csv)"), nullptr);
+ tr("Comma separated file", "Name of CSV file format") + QLatin1String(" (*.csv)"), nullptr);
if (filename.isNull())
return;
diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp
index f25b415820..791a29f7a0 100644
--- a/src/qt/bitcoin.cpp
+++ b/src/qt/bitcoin.cpp
@@ -52,7 +52,6 @@
#include <QThread>
#include <QTimer>
#include <QTranslator>
-#include <QtGlobal>
#if defined(QT_STATICPLUGIN)
#include <QtPlugin>
@@ -467,13 +466,6 @@ int GuiMain(int argc, char* argv[])
QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
-#if (QT_VERSION <= QT_VERSION_CHECK(5, 9, 8)) && defined(Q_OS_MACOS)
- const auto os_name = QSysInfo::prettyProductName();
- if (os_name.startsWith("macOS 11") || os_name.startsWith("macOS 10.16")) {
- QApplication::setStyle("fusion");
- }
-#endif
-
BitcoinApplication app;
QFontDatabase::addApplicationFont(":/fonts/monospace");
diff --git a/src/qt/psbtoperationsdialog.cpp b/src/qt/psbtoperationsdialog.cpp
index d1f8d56100..17746b395b 100644
--- a/src/qt/psbtoperationsdialog.cpp
+++ b/src/qt/psbtoperationsdialog.cpp
@@ -141,7 +141,7 @@ void PSBTOperationsDialog::saveTransaction() {
filename_suggestion.append(".psbt");
QString filename = GUIUtil::getSaveFileName(this,
tr("Save Transaction Data"), filename_suggestion,
- tr("Partially Signed Transaction (Binary) (*.psbt)"), &selected_filter);
+ tr("Partially Signed Transaction (Binary)", "Name of binary PSBT file format") + QLatin1String(" (*.psbt)"), &selected_filter);
if (filename.isEmpty()) {
return;
}
diff --git a/src/qt/qrimagewidget.cpp b/src/qt/qrimagewidget.cpp
index 490826cbbb..a71c8831e9 100644
--- a/src/qt/qrimagewidget.cpp
+++ b/src/qt/qrimagewidget.cpp
@@ -120,7 +120,9 @@ void QRImageWidget::saveImage()
{
if (!GUIUtil::HasPixmap(this))
return;
- QString fn = GUIUtil::getSaveFileName(this, tr("Save QR Code"), QString(), tr("PNG Image (*.png)"), nullptr);
+ QString fn = GUIUtil::getSaveFileName(
+ this, tr("Save QR Code"), QString(),
+ tr("PNG Image", "Name of PNG file format") + QLatin1String(" (*.png)"), nullptr);
if (!fn.isEmpty())
{
exportImage().save(fn);
diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp
index e401f46696..95e1ce2210 100644
--- a/src/qt/sendcoinsdialog.cpp
+++ b/src/qt/sendcoinsdialog.cpp
@@ -430,7 +430,7 @@ void SendCoinsDialog::on_sendButton_clicked()
fileNameSuggestion.append(".psbt");
QString filename = GUIUtil::getSaveFileName(this,
tr("Save Transaction Data"), fileNameSuggestion,
- tr("Partially Signed Transaction (Binary) (*.psbt)"), &selectedFilter);
+ tr("Partially Signed Transaction (Binary)", "Name of binary PSBT file format") + QLatin1String(" (*.psbt)"), &selectedFilter);
if (filename.isEmpty()) {
return;
}
diff --git a/src/qt/test/addressbooktests.cpp b/src/qt/test/addressbooktests.cpp
index 35fcb2b0ca..a026069232 100644
--- a/src/qt/test/addressbooktests.cpp
+++ b/src/qt/test/addressbooktests.cpp
@@ -112,7 +112,7 @@ void TestAddAddressesToSendBook(interfaces::Node& node)
ClientModel clientModel(node, &optionsModel);
AddWallet(wallet);
WalletModel walletModel(interfaces::MakeWallet(wallet), clientModel, platformStyle.get());
- RemoveWallet(wallet, nullopt);
+ RemoveWallet(wallet, std::nullopt);
EditAddressDialog editAddressDialog(EditAddressDialog::NewSendingAddress);
editAddressDialog.setModel(walletModel.getAddressTableModel());
diff --git a/src/qt/test/wallettests.cpp b/src/qt/test/wallettests.cpp
index d6d2d0e3df..1107c44dc9 100644
--- a/src/qt/test/wallettests.cpp
+++ b/src/qt/test/wallettests.cpp
@@ -167,7 +167,7 @@ void TestGUI(interfaces::Node& node)
ClientModel clientModel(node, &optionsModel);
AddWallet(wallet);
WalletModel walletModel(interfaces::MakeWallet(wallet), clientModel, platformStyle.get());
- RemoveWallet(wallet, nullopt);
+ RemoveWallet(wallet, std::nullopt);
sendCoinsDialog.setModel(&walletModel);
transactionView.setModel(&walletModel);
diff --git a/src/qt/transactionview.cpp b/src/qt/transactionview.cpp
index f99a3e286d..42e08c6af7 100644
--- a/src/qt/transactionview.cpp
+++ b/src/qt/transactionview.cpp
@@ -357,7 +357,7 @@ void TransactionView::exportClicked()
// CSV is currently the only supported format
QString filename = GUIUtil::getSaveFileName(this,
tr("Export Transaction History"), QString(),
- tr("Comma separated file (*.csv)"), nullptr);
+ tr("Comma separated file", "Name of CSV file format") + QLatin1String(" (*.csv)"), nullptr);
if (filename.isNull())
return;
diff --git a/src/qt/walletview.cpp b/src/qt/walletview.cpp
index b1e6b43e60..8612893683 100644
--- a/src/qt/walletview.cpp
+++ b/src/qt/walletview.cpp
@@ -273,7 +273,7 @@ void WalletView::backupWallet()
{
QString filename = GUIUtil::getSaveFileName(this,
tr("Backup Wallet"), QString(),
- tr("Wallet Data (*.dat)"), nullptr);
+ tr("Wallet Data", "Name of wallet data file format") + QLatin1String(" (*.dat)"), nullptr);
if (filename.isEmpty())
return;
diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp
index 47c776bbd1..2f92a321f8 100644
--- a/src/rpc/rawtransaction.cpp
+++ b/src/rpc/rawtransaction.cpp
@@ -1828,13 +1828,13 @@ static RPCHelpMan analyzepsbt()
}
if (!inputs_result.empty()) result.pushKV("inputs", inputs_result);
- if (psbta.estimated_vsize != nullopt) {
+ if (psbta.estimated_vsize != std::nullopt) {
result.pushKV("estimated_vsize", (int)*psbta.estimated_vsize);
}
- if (psbta.estimated_feerate != nullopt) {
+ if (psbta.estimated_feerate != std::nullopt) {
result.pushKV("estimated_feerate", ValueFromAmount(psbta.estimated_feerate->GetFeePerK()));
}
- if (psbta.fee != nullopt) {
+ if (psbta.fee != std::nullopt) {
result.pushKV("fee", ValueFromAmount(*psbta.fee));
}
result.pushKV("next", PSBTRoleName(psbta.next));
diff --git a/src/script/descriptor.cpp b/src/script/descriptor.cpp
index 889cb4f06e..30399dca51 100644
--- a/src/script/descriptor.cpp
+++ b/src/script/descriptor.cpp
@@ -17,6 +17,7 @@
#include <util/vector.h>
#include <memory>
+#include <optional>
#include <string>
#include <vector>
@@ -632,7 +633,7 @@ public:
}
}
- Optional<OutputType> GetOutputType() const override { return nullopt; }
+ std::optional<OutputType> GetOutputType() const override { return std::nullopt; }
};
/** A parsed addr(A) descriptor. */
@@ -646,7 +647,7 @@ public:
AddressDescriptor(CTxDestination destination) : DescriptorImpl({}, {}, "addr"), m_destination(std::move(destination)) {}
bool IsSolvable() const final { return false; }
- Optional<OutputType> GetOutputType() const override
+ std::optional<OutputType> GetOutputType() const override
{
switch (m_destination.index()) {
case 1 /* PKHash */:
@@ -655,7 +656,7 @@ public:
case 4 /* WitnessV0KeyHash */:
case 5 /* WitnessUnknown */: return OutputType::BECH32;
case 0 /* CNoDestination */:
- default: return nullopt;
+ default: return std::nullopt;
}
}
bool IsSingleType() const final { return true; }
@@ -672,7 +673,7 @@ public:
RawDescriptor(CScript script) : DescriptorImpl({}, {}, "raw"), m_script(std::move(script)) {}
bool IsSolvable() const final { return false; }
- Optional<OutputType> GetOutputType() const override
+ std::optional<OutputType> GetOutputType() const override
{
CTxDestination dest;
ExtractDestination(m_script, dest);
@@ -683,7 +684,7 @@ public:
case 4 /* WitnessV0KeyHash */:
case 5 /* WitnessUnknown */: return OutputType::BECH32;
case 0 /* CNoDestination */:
- default: return nullopt;
+ default: return std::nullopt;
}
}
bool IsSingleType() const final { return true; }
@@ -711,7 +712,7 @@ protected:
}
public:
PKHDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(Vector(std::move(prov)), {}, "pkh") {}
- Optional<OutputType> GetOutputType() const override { return OutputType::LEGACY; }
+ std::optional<OutputType> GetOutputType() const override { return OutputType::LEGACY; }
bool IsSingleType() const final { return true; }
};
@@ -727,7 +728,7 @@ protected:
}
public:
WPKHDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(Vector(std::move(prov)), {}, "wpkh") {}
- Optional<OutputType> GetOutputType() const override { return OutputType::BECH32; }
+ std::optional<OutputType> GetOutputType() const override { return OutputType::BECH32; }
bool IsSingleType() const final { return true; }
};
@@ -783,7 +784,7 @@ protected:
public:
SHDescriptor(std::unique_ptr<DescriptorImpl> desc) : DescriptorImpl({}, std::move(desc), "sh") {}
- Optional<OutputType> GetOutputType() const override
+ std::optional<OutputType> GetOutputType() const override
{
assert(m_subdescriptor_arg);
if (m_subdescriptor_arg->GetOutputType() == OutputType::BECH32) return OutputType::P2SH_SEGWIT;
@@ -799,7 +800,7 @@ protected:
std::vector<CScript> MakeScripts(const std::vector<CPubKey>&, const CScript* script, FlatSigningProvider&) const override { return Vector(GetScriptForDestination(WitnessV0ScriptHash(*script))); }
public:
WSHDescriptor(std::unique_ptr<DescriptorImpl> desc) : DescriptorImpl({}, std::move(desc), "wsh") {}
- Optional<OutputType> GetOutputType() const override { return OutputType::BECH32; }
+ std::optional<OutputType> GetOutputType() const override { return OutputType::BECH32; }
bool IsSingleType() const final { return true; }
};
diff --git a/src/script/descriptor.h b/src/script/descriptor.h
index 46d51fa587..332ae2f230 100644
--- a/src/script/descriptor.h
+++ b/src/script/descriptor.h
@@ -5,12 +5,12 @@
#ifndef BITCOIN_SCRIPT_DESCRIPTOR_H
#define BITCOIN_SCRIPT_DESCRIPTOR_H
-#include <optional.h>
#include <outputtype.h>
#include <script/script.h>
#include <script/sign.h>
#include <script/signingprovider.h>
+#include <optional>
#include <vector>
using ExtPubKeyMap = std::unordered_map<uint32_t, CExtPubKey>;
@@ -124,7 +124,7 @@ struct Descriptor {
virtual void ExpandPrivate(int pos, const SigningProvider& provider, FlatSigningProvider& out) const = 0;
/** @return The OutputType of the scriptPubKey(s) produced by this descriptor. Or nullopt if indeterminate (multiple or none) */
- virtual Optional<OutputType> GetOutputType() const = 0;
+ virtual std::optional<OutputType> GetOutputType() const = 0;
};
/** Parse a `descriptor` string. Included private keys are put in `out`.
diff --git a/src/signet.cpp b/src/signet.cpp
index e68f031aa4..fb41e43752 100644
--- a/src/signet.cpp
+++ b/src/signet.cpp
@@ -65,7 +65,7 @@ static uint256 ComputeModifiedMerkleRoot(const CMutableTransaction& cb, const CB
return ComputeMerkleRoot(std::move(leaves));
}
-Optional<SignetTxs> SignetTxs::Create(const CBlock& block, const CScript& challenge)
+std::optional<SignetTxs> SignetTxs::Create(const CBlock& block, const CScript& challenge)
{
CMutableTransaction tx_to_spend;
tx_to_spend.nVersion = 0;
@@ -83,12 +83,12 @@ Optional<SignetTxs> SignetTxs::Create(const CBlock& block, const CScript& challe
// responses from block coinbase tx
// find and delete signet signature
- if (block.vtx.empty()) return nullopt; // no coinbase tx in block; invalid
+ if (block.vtx.empty()) return std::nullopt; // no coinbase tx in block; invalid
CMutableTransaction modified_cb(*block.vtx.at(0));
const int cidx = GetWitnessCommitmentIndex(block);
if (cidx == NO_WITNESS_COMMITMENT) {
- return nullopt; // require a witness commitment
+ return std::nullopt; // require a witness commitment
}
CScript& witness_commitment = modified_cb.vout.at(cidx).scriptPubKey;
@@ -101,9 +101,9 @@ Optional<SignetTxs> SignetTxs::Create(const CBlock& block, const CScript& challe
VectorReader v(SER_NETWORK, INIT_PROTO_VERSION, signet_solution, 0);
v >> tx_spending.vin[0].scriptSig;
v >> tx_spending.vin[0].scriptWitness.stack;
- if (!v.empty()) return nullopt; // extraneous data encountered
+ if (!v.empty()) return std::nullopt; // extraneous data encountered
} catch (const std::exception&) {
- return nullopt; // parsing error
+ return std::nullopt; // parsing error
}
}
uint256 signet_merkle = ComputeModifiedMerkleRoot(modified_cb, block);
@@ -129,7 +129,7 @@ bool CheckSignetBlockSolution(const CBlock& block, const Consensus::Params& cons
}
const CScript challenge(consensusParams.signet_challenge.begin(), consensusParams.signet_challenge.end());
- const Optional<SignetTxs> signet_txs = SignetTxs::Create(block, challenge);
+ const std::optional<SignetTxs> signet_txs = SignetTxs::Create(block, challenge);
if (!signet_txs) {
LogPrint(BCLog::VALIDATION, "CheckSignetBlockSolution: Errors in block (block solution parse failure)\n");
diff --git a/src/signet.h b/src/signet.h
index 23563a83c4..f876488c0a 100644
--- a/src/signet.h
+++ b/src/signet.h
@@ -9,7 +9,7 @@
#include <primitives/block.h>
#include <primitives/transaction.h>
-#include <optional.h>
+#include <optional>
/**
* Extract signature and check whether a block has a valid solution
@@ -28,7 +28,7 @@ class SignetTxs {
SignetTxs(const T1& to_spend, const T2& to_sign) : m_to_spend{to_spend}, m_to_sign{to_sign} { }
public:
- static Optional<SignetTxs> Create(const CBlock& block, const CScript& challenge);
+ static std::optional<SignetTxs> Create(const CBlock& block, const CScript& challenge);
const CTransaction m_to_spend;
const CTransaction m_to_sign;
diff --git a/src/test/descriptor_tests.cpp b/src/test/descriptor_tests.cpp
index acbd6a01ee..aecf955fee 100644
--- a/src/test/descriptor_tests.cpp
+++ b/src/test/descriptor_tests.cpp
@@ -10,6 +10,7 @@
#include <boost/test/unit_test.hpp>
+#include <optional>
#include <string>
#include <vector>
@@ -65,7 +66,7 @@ std::string UseHInsteadOfApostrophe(const std::string& desc)
const std::set<std::vector<uint32_t>> ONLY_EMPTY{{}};
-void DoCheck(const std::string& prv, const std::string& pub, const std::string& norm_prv, const std::string& norm_pub, int flags, const std::vector<std::vector<std::string>>& scripts, const Optional<OutputType>& type, const std::set<std::vector<uint32_t>>& paths = ONLY_EMPTY,
+void DoCheck(const std::string& prv, const std::string& pub, const std::string& norm_prv, const std::string& norm_pub, int flags, const std::vector<std::vector<std::string>>& scripts, const std::optional<OutputType>& type, const std::set<std::vector<uint32_t>>& paths = ONLY_EMPTY,
bool replace_apostrophe_with_h_in_prv=false, bool replace_apostrophe_with_h_in_pub=false)
{
FlatSigningProvider keys_priv, keys_pub;
@@ -262,7 +263,7 @@ void DoCheck(const std::string& prv, const std::string& pub, const std::string&
BOOST_CHECK_MESSAGE(left_paths.empty(), "Not all expected key paths found: " + prv);
}
-void Check(const std::string& prv, const std::string& pub, const std::string& norm_prv, const std::string& norm_pub, int flags, const std::vector<std::vector<std::string>>& scripts, const Optional<OutputType>& type, const std::set<std::vector<uint32_t>>& paths = ONLY_EMPTY)
+void Check(const std::string& prv, const std::string& pub, const std::string& norm_prv, const std::string& norm_pub, int flags, const std::vector<std::vector<std::string>>& scripts, const std::optional<OutputType>& type, const std::set<std::vector<uint32_t>>& paths = ONLY_EMPTY)
{
bool found_apostrophes_in_prv = false;
bool found_apostrophes_in_pub = false;
@@ -295,8 +296,8 @@ BOOST_FIXTURE_TEST_SUITE(descriptor_tests, BasicTestingSetup)
BOOST_AUTO_TEST_CASE(descriptor_test)
{
// Basic single-key compressed
- Check("combo(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "combo(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", "combo(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "combo(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", SIGNABLE, {{"2103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bdac","76a9149a1c78a507689f6f54b847ad1cef1e614ee23f1e88ac","00149a1c78a507689f6f54b847ad1cef1e614ee23f1e","a91484ab21b1b2fd065d4504ff693d832434b6108d7b87"}}, nullopt);
- Check("pk(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", "pk(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", SIGNABLE, {{"2103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bdac"}}, nullopt);
+ Check("combo(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "combo(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", "combo(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "combo(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", SIGNABLE, {{"2103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bdac","76a9149a1c78a507689f6f54b847ad1cef1e614ee23f1e88ac","00149a1c78a507689f6f54b847ad1cef1e614ee23f1e","a91484ab21b1b2fd065d4504ff693d832434b6108d7b87"}}, std::nullopt);
+ Check("pk(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", "pk(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", SIGNABLE, {{"2103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bdac"}}, std::nullopt);
Check("pkh([deadbeef/1/2'/3/4']L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "pkh([deadbeef/1/2'/3/4']03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", "pkh([deadbeef/1/2'/3/4']L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "pkh([deadbeef/1/2'/3/4']03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", SIGNABLE, {{"76a9149a1c78a507689f6f54b847ad1cef1e614ee23f1e88ac"}}, OutputType::LEGACY, {{1,0x80000002UL,3,0x80000004UL}});
Check("wpkh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "wpkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", "wpkh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "wpkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", SIGNABLE, {{"00149a1c78a507689f6f54b847ad1cef1e614ee23f1e"}}, OutputType::BECH32);
Check("sh(wpkh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1))", "sh(wpkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))", "sh(wpkh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1))", "sh(wpkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))", SIGNABLE, {{"a91484ab21b1b2fd065d4504ff693d832434b6108d7b87"}}, OutputType::P2SH_SEGWIT);
@@ -305,8 +306,8 @@ BOOST_AUTO_TEST_CASE(descriptor_test)
CheckUnparsable("pkh([deadbeef]/1/2'/3/4']L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "pkh([deadbeef]/1/2'/3/4']03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", "Multiple ']' characters found for a single pubkey"); // Multiple end brackets in key origin
// Basic single-key uncompressed
- Check("combo(5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "combo(04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", "combo(5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "combo(04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)",SIGNABLE, {{"4104a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235ac","76a914b5bd079c4d57cc7fc28ecf8213a6b791625b818388ac"}}, nullopt);
- Check("pk(5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "pk(04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", "pk(5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "pk(04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", SIGNABLE, {{"4104a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235ac"}}, nullopt);
+ Check("combo(5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "combo(04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", "combo(5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "combo(04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)",SIGNABLE, {{"4104a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235ac","76a914b5bd079c4d57cc7fc28ecf8213a6b791625b818388ac"}}, std::nullopt);
+ Check("pk(5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "pk(04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", "pk(5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "pk(04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", SIGNABLE, {{"4104a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235ac"}}, std::nullopt);
Check("pkh(5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "pkh(04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", "pkh(5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "pkh(04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", SIGNABLE, {{"76a914b5bd079c4d57cc7fc28ecf8213a6b791625b818388ac"}}, OutputType::LEGACY);
CheckUnparsable("wpkh(5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "wpkh(04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", "Uncompressed keys are not allowed"); // No uncompressed keys in witness
CheckUnparsable("wsh(pk(5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss))", "wsh(pk(04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235))", "Uncompressed keys are not allowed"); // No uncompressed keys in witness
@@ -321,23 +322,23 @@ BOOST_AUTO_TEST_CASE(descriptor_test)
Check("sh(wsh(pkh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)))", "sh(wsh(pkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)))", "sh(wsh(pkh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)))", "sh(wsh(pkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)))", SIGNABLE, {{"a914b61b92e2ca21bac1e72a3ab859a742982bea960a87"}}, OutputType::P2SH_SEGWIT);
// Versions with BIP32 derivations
- Check("combo([01234567]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc)", "combo([01234567]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL)", "combo([01234567]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc)", "combo([01234567]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL)", SIGNABLE, {{"2102d2b36900396c9282fa14628566582f206a5dd0bcc8d5e892611806cafb0301f0ac","76a91431a507b815593dfc51ffc7245ae7e5aee304246e88ac","001431a507b815593dfc51ffc7245ae7e5aee304246e","a9142aafb926eb247cb18240a7f4c07983ad1f37922687"}}, nullopt);
- Check("pk(xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0)", "pk(xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0)", "pk(xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0)", "pk(xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0)", DEFAULT, {{"210379e45b3cf75f9c5f9befd8e9506fb962f6a9d185ac87001ec44a8d3df8d4a9e3ac"}}, nullopt, {{0}});
+ Check("combo([01234567]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc)", "combo([01234567]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL)", "combo([01234567]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc)", "combo([01234567]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL)", SIGNABLE, {{"2102d2b36900396c9282fa14628566582f206a5dd0bcc8d5e892611806cafb0301f0ac","76a91431a507b815593dfc51ffc7245ae7e5aee304246e88ac","001431a507b815593dfc51ffc7245ae7e5aee304246e","a9142aafb926eb247cb18240a7f4c07983ad1f37922687"}}, std::nullopt);
+ Check("pk(xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0)", "pk(xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0)", "pk(xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0)", "pk(xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0)", DEFAULT, {{"210379e45b3cf75f9c5f9befd8e9506fb962f6a9d185ac87001ec44a8d3df8d4a9e3ac"}}, std::nullopt, {{0}});
Check("pkh(xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483647'/0)", "pkh(xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483647'/0)", "pkh([bd16bee5/2147483647']xprv9vHkqa6XAPwKqSKSEJMcAB3yoCZhaSVsGZbSkFY5L3Lfjjk8sjZucbsbvEw5o3QrSA69nPfZDCgFnNnLhQ2ohpZuwummndnPasDw2Qr6dC2/0)", "pkh([bd16bee5/2147483647']xpub69H7F5dQzmVd3vPuLKtcXJziMEQByuDidnX3YdwgtNsecY5HRGtAAQC5mXTt4dsv9RzyjgDjAQs9VGVV6ydYCHnprc9vvaA5YtqWyL6hyds/0)", HARDENED, {{"76a914ebdc90806a9c4356c1c88e42216611e1cb4c1c1788ac"}}, OutputType::LEGACY, {{0xFFFFFFFFUL,0}});
Check("wpkh([ffffffff/13']xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt/1/2/*)", "wpkh([ffffffff/13']xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*)", "wpkh([ffffffff/13']xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt/1/2/*)", "wpkh([ffffffff/13']xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*)", RANGE, {{"0014326b2249e3a25d5dc60935f044ee835d090ba859"},{"0014af0bd98abc2f2cae66e36896a39ffe2d32984fb7"},{"00141fa798efd1cbf95cebf912c031b8a4a6e9fb9f27"}}, OutputType::BECH32, {{0x8000000DUL, 1, 2, 0}, {0x8000000DUL, 1, 2, 1}, {0x8000000DUL, 1, 2, 2}});
Check("sh(wpkh(xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi/10/20/30/40/*'))", "sh(wpkh(xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*'))", "sh(wpkh(xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi/10/20/30/40/*'))", "sh(wpkh(xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*'))", RANGE | HARDENED | DERIVE_HARDENED, {{"a9149a4d9901d6af519b2a23d4a2f51650fcba87ce7b87"},{"a914bed59fc0024fae941d6e20a3b44a109ae740129287"},{"a9148483aa1116eb9c05c482a72bada4b1db24af654387"}}, OutputType::P2SH_SEGWIT, {{10, 20, 30, 40, 0x80000000UL}, {10, 20, 30, 40, 0x80000001UL}, {10, 20, 30, 40, 0x80000002UL}});
- Check("combo(xprvA2JDeKCSNNZky6uBCviVfJSKyQ1mDYahRjijr5idH2WwLsEd4Hsb2Tyh8RfQMuPh7f7RtyzTtdrbdqqsunu5Mm3wDvUAKRHSC34sJ7in334/*)", "combo(xpub6FHa3pjLCk84BayeJxFW2SP4XRrFd1JYnxeLeU8EqN3vDfZmbqBqaGJAyiLjTAwm6ZLRQUMv1ZACTj37sR62cfN7fe5JnJ7dh8zL4fiyLHV/*)", "combo(xprvA2JDeKCSNNZky6uBCviVfJSKyQ1mDYahRjijr5idH2WwLsEd4Hsb2Tyh8RfQMuPh7f7RtyzTtdrbdqqsunu5Mm3wDvUAKRHSC34sJ7in334/*)", "combo(xpub6FHa3pjLCk84BayeJxFW2SP4XRrFd1JYnxeLeU8EqN3vDfZmbqBqaGJAyiLjTAwm6ZLRQUMv1ZACTj37sR62cfN7fe5JnJ7dh8zL4fiyLHV/*)", RANGE, {{"2102df12b7035bdac8e3bab862a3a83d06ea6b17b6753d52edecba9be46f5d09e076ac","76a914f90e3178ca25f2c808dc76624032d352fdbdfaf288ac","0014f90e3178ca25f2c808dc76624032d352fdbdfaf2","a91408f3ea8c68d4a7585bf9e8bda226723f70e445f087"},{"21032869a233c9adff9a994e4966e5b821fd5bac066da6c3112488dc52383b4a98ecac","76a914a8409d1b6dfb1ed2a3e8aa5e0ef2ff26b15b75b788ac","0014a8409d1b6dfb1ed2a3e8aa5e0ef2ff26b15b75b7","a91473e39884cb71ae4e5ac9739e9225026c99763e6687"}}, nullopt, {{0}, {1}});
+ Check("combo(xprvA2JDeKCSNNZky6uBCviVfJSKyQ1mDYahRjijr5idH2WwLsEd4Hsb2Tyh8RfQMuPh7f7RtyzTtdrbdqqsunu5Mm3wDvUAKRHSC34sJ7in334/*)", "combo(xpub6FHa3pjLCk84BayeJxFW2SP4XRrFd1JYnxeLeU8EqN3vDfZmbqBqaGJAyiLjTAwm6ZLRQUMv1ZACTj37sR62cfN7fe5JnJ7dh8zL4fiyLHV/*)", "combo(xprvA2JDeKCSNNZky6uBCviVfJSKyQ1mDYahRjijr5idH2WwLsEd4Hsb2Tyh8RfQMuPh7f7RtyzTtdrbdqqsunu5Mm3wDvUAKRHSC34sJ7in334/*)", "combo(xpub6FHa3pjLCk84BayeJxFW2SP4XRrFd1JYnxeLeU8EqN3vDfZmbqBqaGJAyiLjTAwm6ZLRQUMv1ZACTj37sR62cfN7fe5JnJ7dh8zL4fiyLHV/*)", RANGE, {{"2102df12b7035bdac8e3bab862a3a83d06ea6b17b6753d52edecba9be46f5d09e076ac","76a914f90e3178ca25f2c808dc76624032d352fdbdfaf288ac","0014f90e3178ca25f2c808dc76624032d352fdbdfaf2","a91408f3ea8c68d4a7585bf9e8bda226723f70e445f087"},{"21032869a233c9adff9a994e4966e5b821fd5bac066da6c3112488dc52383b4a98ecac","76a914a8409d1b6dfb1ed2a3e8aa5e0ef2ff26b15b75b788ac","0014a8409d1b6dfb1ed2a3e8aa5e0ef2ff26b15b75b7","a91473e39884cb71ae4e5ac9739e9225026c99763e6687"}}, std::nullopt, {{0}, {1}});
CheckUnparsable("combo([012345678]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc)", "combo([012345678]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL)", "Fingerprint is not 4 bytes (9 characters instead of 8 characters)"); // Too long key fingerprint
CheckUnparsable("pkh(xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483648)", "pkh(xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483648)", "Key path value 2147483648 is out of range"); // BIP 32 path element overflow
CheckUnparsable("pkh(xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/1aa)", "pkh(xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/1aa)", "Key path value '1aa' is not a valid uint32"); // Path is not valid uint
Check("pkh([01234567/10/20]xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483647'/0)", "pkh([01234567/10/20]xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483647'/0)", "pkh([01234567/10/20/2147483647']xprv9vHkqa6XAPwKqSKSEJMcAB3yoCZhaSVsGZbSkFY5L3Lfjjk8sjZucbsbvEw5o3QrSA69nPfZDCgFnNnLhQ2ohpZuwummndnPasDw2Qr6dC2/0)", "pkh([01234567/10/20/2147483647']xpub69H7F5dQzmVd3vPuLKtcXJziMEQByuDidnX3YdwgtNsecY5HRGtAAQC5mXTt4dsv9RzyjgDjAQs9VGVV6ydYCHnprc9vvaA5YtqWyL6hyds/0)", HARDENED, {{"76a914ebdc90806a9c4356c1c88e42216611e1cb4c1c1788ac"}}, OutputType::LEGACY, {{10, 20, 0xFFFFFFFFUL, 0}});
// Multisig constructions
- Check("multi(1,L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1,5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "multi(1,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", "multi(1,L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1,5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "multi(1,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", SIGNABLE, {{"512103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd4104a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea23552ae"}}, nullopt);
- Check("sortedmulti(1,L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1,5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "sortedmulti(1,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", "sortedmulti(1,L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1,5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "sortedmulti(1,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", SIGNABLE, {{"512103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd4104a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea23552ae"}}, nullopt);
- Check("sortedmulti(1,5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss,L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "sortedmulti(1,04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", "sortedmulti(1,5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss,L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "sortedmulti(1,04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", SIGNABLE, {{"512103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd4104a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea23552ae"}}, nullopt);
+ Check("multi(1,L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1,5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "multi(1,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", "multi(1,L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1,5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "multi(1,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", SIGNABLE, {{"512103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd4104a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea23552ae"}}, std::nullopt);
+ Check("sortedmulti(1,L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1,5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "sortedmulti(1,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", "sortedmulti(1,L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1,5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "sortedmulti(1,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", SIGNABLE, {{"512103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd4104a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea23552ae"}}, std::nullopt);
+ Check("sortedmulti(1,5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss,L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "sortedmulti(1,04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", "sortedmulti(1,5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss,L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "sortedmulti(1,04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", SIGNABLE, {{"512103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd4104a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea23552ae"}}, std::nullopt);
Check("sh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))", "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))", "sh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))", "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))", DEFAULT, {{"a91445a9a622a8b0a1269944be477640eedc447bbd8487"}}, OutputType::LEGACY, {{0x8000006FUL,222},{0}});
- Check("sortedmulti(2,xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc/*,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0/0/*)", "sortedmulti(2,xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/*,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0/0/*)", "sortedmulti(2,xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc/*,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0/0/*)", "sortedmulti(2,xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/*,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0/0/*)", RANGE, {{"5221025d5fc65ebb8d44a5274b53bac21ff8307fec2334a32df05553459f8b1f7fe1b62102fbd47cc8034098f0e6a94c6aeee8528abf0a2153a5d8e46d325b7284c046784652ae"}, {"52210264fd4d1f5dea8ded94c61e9641309349b62f27fbffe807291f664e286bfbe6472103f4ece6dfccfa37b211eb3d0af4d0c61dba9ef698622dc17eecdf764beeb005a652ae"}, {"5221022ccabda84c30bad578b13c89eb3b9544ce149787e5b538175b1d1ba259cbb83321024d902e1a2fc7a8755ab5b694c575fce742c48d9ff192e63df5193e4c7afe1f9c52ae"}}, nullopt, {{0}, {1}, {2}, {0, 0, 0}, {0, 0, 1}, {0, 0, 2}});
+ Check("sortedmulti(2,xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc/*,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0/0/*)", "sortedmulti(2,xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/*,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0/0/*)", "sortedmulti(2,xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc/*,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0/0/*)", "sortedmulti(2,xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/*,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0/0/*)", RANGE, {{"5221025d5fc65ebb8d44a5274b53bac21ff8307fec2334a32df05553459f8b1f7fe1b62102fbd47cc8034098f0e6a94c6aeee8528abf0a2153a5d8e46d325b7284c046784652ae"}, {"52210264fd4d1f5dea8ded94c61e9641309349b62f27fbffe807291f664e286bfbe6472103f4ece6dfccfa37b211eb3d0af4d0c61dba9ef698622dc17eecdf764beeb005a652ae"}, {"5221022ccabda84c30bad578b13c89eb3b9544ce149787e5b538175b1d1ba259cbb83321024d902e1a2fc7a8755ab5b694c575fce742c48d9ff192e63df5193e4c7afe1f9c52ae"}}, std::nullopt, {{0}, {1}, {2}, {0, 0, 0}, {0, 0, 1}, {0, 0, 2}});
Check("wsh(multi(2,xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483647'/0,xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt/1/2/*,xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi/10/20/30/40/*'))", "wsh(multi(2,xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483647'/0,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*,xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*'))", "wsh(multi(2,[bd16bee5/2147483647']xprv9vHkqa6XAPwKqSKSEJMcAB3yoCZhaSVsGZbSkFY5L3Lfjjk8sjZucbsbvEw5o3QrSA69nPfZDCgFnNnLhQ2ohpZuwummndnPasDw2Qr6dC2/0,xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt/1/2/*,xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi/10/20/30/40/*'))", "wsh(multi(2,[bd16bee5/2147483647']xpub69H7F5dQzmVd3vPuLKtcXJziMEQByuDidnX3YdwgtNsecY5HRGtAAQC5mXTt4dsv9RzyjgDjAQs9VGVV6ydYCHnprc9vvaA5YtqWyL6hyds/0,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*,xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*'))", HARDENED | RANGE | DERIVE_HARDENED, {{"0020b92623201f3bb7c3771d45b2ad1d0351ea8fbf8cfe0a0e570264e1075fa1948f"},{"002036a08bbe4923af41cf4316817c93b8d37e2f635dd25cfff06bd50df6ae7ea203"},{"0020a96e7ab4607ca6b261bfe3245ffda9c746b28d3f59e83d34820ec0e2b36c139c"}}, OutputType::BECH32, {{0xFFFFFFFFUL,0}, {1,2,0}, {1,2,1}, {1,2,2}, {10, 20, 30, 40, 0x80000000UL}, {10, 20, 30, 40, 0x80000001UL}, {10, 20, 30, 40, 0x80000002UL}});
Check("sh(wsh(multi(16,KzoAz5CanayRKex3fSLQ2BwJpN7U52gZvxMyk78nDMHuqrUxuSJy,KwGNz6YCCQtYvFzMtrC6D3tKTKdBBboMrLTsjr2NYVBwapCkn7Mr,KxogYhiNfwxuswvXV66eFyKcCpm7dZ7TqHVqujHAVUjJxyivxQ9X,L2BUNduTSyZwZjwNHynQTF14mv2uz2NRq5n5sYWTb4FkkmqgEE9f,L1okJGHGn1kFjdXHKxXjwVVtmCMR2JA5QsbKCSpSb7ReQjezKeoD,KxDCNSST75HFPaW5QKpzHtAyaCQC7p9Vo3FYfi2u4dXD1vgMiboK,L5edQjFtnkcf5UWURn6UuuoFrabgDQUHdheKCziwN42aLwS3KizU,KzF8UWFcEC7BYTq8Go1xVimMkDmyNYVmXV5PV7RuDicvAocoPB8i,L3nHUboKG2w4VSJ5jYZ5CBM97oeK6YuKvfZxrefdShECcjEYKMWZ,KyjHo36dWkYhimKmVVmQTq3gERv3pnqA4xFCpvUgbGDJad7eS8WE,KwsfyHKRUTZPQtysN7M3tZ4GXTnuov5XRgjdF2XCG8faAPmFruRF,KzCUbGhN9LJhdeFfL9zQgTJMjqxdBKEekRGZX24hXdgCNCijkkap,KzgpMBwwsDLwkaC5UrmBgCYaBD2WgZ7PBoGYXR8KT7gCA9UTN5a3,KyBXTPy4T7YG4q9tcAM3LkvfRpD1ybHMvcJ2ehaWXaSqeGUxEdkP,KzJDe9iwJRPtKP2F2AoN6zBgzS7uiuAwhWCfGdNeYJ3PC1HNJ8M8,L1xbHrxynrqLKkoYc4qtoQPx6uy5qYXR5ZDYVYBSRmCV5piU3JG9)))","sh(wsh(multi(16,03669b8afcec803a0d323e9a17f3ea8e68e8abe5a278020a929adbec52421adbd0,0260b2003c386519fc9eadf2b5cf124dd8eea4c4e68d5e154050a9346ea98ce600,0362a74e399c39ed5593852a30147f2959b56bb827dfa3e60e464b02ccf87dc5e8,0261345b53de74a4d721ef877c255429961b7e43714171ac06168d7e08c542a8b8,02da72e8b46901a65d4374fe6315538d8f368557dda3a1dcf9ea903f3afe7314c8,0318c82dd0b53fd3a932d16e0ba9e278fcc937c582d5781be626ff16e201f72286,0297ccef1ef99f9d73dec9ad37476ddb232f1238aff877af19e72ba04493361009,02e502cfd5c3f972fe9a3e2a18827820638f96b6f347e54d63deb839011fd5765d,03e687710f0e3ebe81c1037074da939d409c0025f17eb86adb9427d28f0f7ae0e9,02c04d3a5274952acdbc76987f3184b346a483d43be40874624b29e3692c1df5af,02ed06e0f418b5b43a7ec01d1d7d27290fa15f75771cb69b642a51471c29c84acd,036d46073cbb9ffee90473f3da429abc8de7f8751199da44485682a989a4bebb24,02f5d1ff7c9029a80a4e36b9a5497027ef7f3e73384a4a94fbfe7c4e9164eec8bc,02e41deffd1b7cce11cde209a781adcffdabd1b91c0ba0375857a2bfd9302419f3,02d76625f7956a7fc505ab02556c23ee72d832f1bac391bcd2d3abce5710a13d06,0399eb0a5487515802dc14544cf10b3666623762fbed2ec38a3975716e2c29c232)))", "sh(wsh(multi(16,KzoAz5CanayRKex3fSLQ2BwJpN7U52gZvxMyk78nDMHuqrUxuSJy,KwGNz6YCCQtYvFzMtrC6D3tKTKdBBboMrLTsjr2NYVBwapCkn7Mr,KxogYhiNfwxuswvXV66eFyKcCpm7dZ7TqHVqujHAVUjJxyivxQ9X,L2BUNduTSyZwZjwNHynQTF14mv2uz2NRq5n5sYWTb4FkkmqgEE9f,L1okJGHGn1kFjdXHKxXjwVVtmCMR2JA5QsbKCSpSb7ReQjezKeoD,KxDCNSST75HFPaW5QKpzHtAyaCQC7p9Vo3FYfi2u4dXD1vgMiboK,L5edQjFtnkcf5UWURn6UuuoFrabgDQUHdheKCziwN42aLwS3KizU,KzF8UWFcEC7BYTq8Go1xVimMkDmyNYVmXV5PV7RuDicvAocoPB8i,L3nHUboKG2w4VSJ5jYZ5CBM97oeK6YuKvfZxrefdShECcjEYKMWZ,KyjHo36dWkYhimKmVVmQTq3gERv3pnqA4xFCpvUgbGDJad7eS8WE,KwsfyHKRUTZPQtysN7M3tZ4GXTnuov5XRgjdF2XCG8faAPmFruRF,KzCUbGhN9LJhdeFfL9zQgTJMjqxdBKEekRGZX24hXdgCNCijkkap,KzgpMBwwsDLwkaC5UrmBgCYaBD2WgZ7PBoGYXR8KT7gCA9UTN5a3,KyBXTPy4T7YG4q9tcAM3LkvfRpD1ybHMvcJ2ehaWXaSqeGUxEdkP,KzJDe9iwJRPtKP2F2AoN6zBgzS7uiuAwhWCfGdNeYJ3PC1HNJ8M8,L1xbHrxynrqLKkoYc4qtoQPx6uy5qYXR5ZDYVYBSRmCV5piU3JG9)))","sh(wsh(multi(16,03669b8afcec803a0d323e9a17f3ea8e68e8abe5a278020a929adbec52421adbd0,0260b2003c386519fc9eadf2b5cf124dd8eea4c4e68d5e154050a9346ea98ce600,0362a74e399c39ed5593852a30147f2959b56bb827dfa3e60e464b02ccf87dc5e8,0261345b53de74a4d721ef877c255429961b7e43714171ac06168d7e08c542a8b8,02da72e8b46901a65d4374fe6315538d8f368557dda3a1dcf9ea903f3afe7314c8,0318c82dd0b53fd3a932d16e0ba9e278fcc937c582d5781be626ff16e201f72286,0297ccef1ef99f9d73dec9ad37476ddb232f1238aff877af19e72ba04493361009,02e502cfd5c3f972fe9a3e2a18827820638f96b6f347e54d63deb839011fd5765d,03e687710f0e3ebe81c1037074da939d409c0025f17eb86adb9427d28f0f7ae0e9,02c04d3a5274952acdbc76987f3184b346a483d43be40874624b29e3692c1df5af,02ed06e0f418b5b43a7ec01d1d7d27290fa15f75771cb69b642a51471c29c84acd,036d46073cbb9ffee90473f3da429abc8de7f8751199da44485682a989a4bebb24,02f5d1ff7c9029a80a4e36b9a5497027ef7f3e73384a4a94fbfe7c4e9164eec8bc,02e41deffd1b7cce11cde209a781adcffdabd1b91c0ba0375857a2bfd9302419f3,02d76625f7956a7fc505ab02556c23ee72d832f1bac391bcd2d3abce5710a13d06,0399eb0a5487515802dc14544cf10b3666623762fbed2ec38a3975716e2c29c232)))", SIGNABLE, {{"a9147fc63e13dc25e8a95a3cee3d9a714ac3afd96f1e87"}}, OutputType::P2SH_SEGWIT);
CheckUnparsable("sh(multi(16,KzoAz5CanayRKex3fSLQ2BwJpN7U52gZvxMyk78nDMHuqrUxuSJy,KwGNz6YCCQtYvFzMtrC6D3tKTKdBBboMrLTsjr2NYVBwapCkn7Mr,KxogYhiNfwxuswvXV66eFyKcCpm7dZ7TqHVqujHAVUjJxyivxQ9X,L2BUNduTSyZwZjwNHynQTF14mv2uz2NRq5n5sYWTb4FkkmqgEE9f,L1okJGHGn1kFjdXHKxXjwVVtmCMR2JA5QsbKCSpSb7ReQjezKeoD,KxDCNSST75HFPaW5QKpzHtAyaCQC7p9Vo3FYfi2u4dXD1vgMiboK,L5edQjFtnkcf5UWURn6UuuoFrabgDQUHdheKCziwN42aLwS3KizU,KzF8UWFcEC7BYTq8Go1xVimMkDmyNYVmXV5PV7RuDicvAocoPB8i,L3nHUboKG2w4VSJ5jYZ5CBM97oeK6YuKvfZxrefdShECcjEYKMWZ,KyjHo36dWkYhimKmVVmQTq3gERv3pnqA4xFCpvUgbGDJad7eS8WE,KwsfyHKRUTZPQtysN7M3tZ4GXTnuov5XRgjdF2XCG8faAPmFruRF,KzCUbGhN9LJhdeFfL9zQgTJMjqxdBKEekRGZX24hXdgCNCijkkap,KzgpMBwwsDLwkaC5UrmBgCYaBD2WgZ7PBoGYXR8KT7gCA9UTN5a3,KyBXTPy4T7YG4q9tcAM3LkvfRpD1ybHMvcJ2ehaWXaSqeGUxEdkP,KzJDe9iwJRPtKP2F2AoN6zBgzS7uiuAwhWCfGdNeYJ3PC1HNJ8M8,L1xbHrxynrqLKkoYc4qtoQPx6uy5qYXR5ZDYVYBSRmCV5piU3JG9))","sh(multi(16,03669b8afcec803a0d323e9a17f3ea8e68e8abe5a278020a929adbec52421adbd0,0260b2003c386519fc9eadf2b5cf124dd8eea4c4e68d5e154050a9346ea98ce600,0362a74e399c39ed5593852a30147f2959b56bb827dfa3e60e464b02ccf87dc5e8,0261345b53de74a4d721ef877c255429961b7e43714171ac06168d7e08c542a8b8,02da72e8b46901a65d4374fe6315538d8f368557dda3a1dcf9ea903f3afe7314c8,0318c82dd0b53fd3a932d16e0ba9e278fcc937c582d5781be626ff16e201f72286,0297ccef1ef99f9d73dec9ad37476ddb232f1238aff877af19e72ba04493361009,02e502cfd5c3f972fe9a3e2a18827820638f96b6f347e54d63deb839011fd5765d,03e687710f0e3ebe81c1037074da939d409c0025f17eb86adb9427d28f0f7ae0e9,02c04d3a5274952acdbc76987f3184b346a483d43be40874624b29e3692c1df5af,02ed06e0f418b5b43a7ec01d1d7d27290fa15f75771cb69b642a51471c29c84acd,036d46073cbb9ffee90473f3da429abc8de7f8751199da44485682a989a4bebb24,02f5d1ff7c9029a80a4e36b9a5497027ef7f3e73384a4a94fbfe7c4e9164eec8bc,02e41deffd1b7cce11cde209a781adcffdabd1b91c0ba0375857a2bfd9302419f3,02d76625f7956a7fc505ab02556c23ee72d832f1bac391bcd2d3abce5710a13d06,0399eb0a5487515802dc14544cf10b3666623762fbed2ec38a3975716e2c29c232))", "P2SH script is too large, 547 bytes is larger than 520 bytes"); // P2SH does not fit 16 compressed pubkeys in a redeemscript
diff --git a/src/test/fuzz/autofile.cpp b/src/test/fuzz/autofile.cpp
index dbc0b5ab81..479342e4be 100644
--- a/src/test/fuzz/autofile.cpp
+++ b/src/test/fuzz/autofile.cpp
@@ -2,7 +2,6 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include <optional.h>
#include <streams.h>
#include <test/fuzz/FuzzedDataProvider.h>
#include <test/fuzz/fuzz.h>
diff --git a/src/test/fuzz/buffered_file.cpp b/src/test/fuzz/buffered_file.cpp
index ffe38f10fc..ed72260d10 100644
--- a/src/test/fuzz/buffered_file.cpp
+++ b/src/test/fuzz/buffered_file.cpp
@@ -2,7 +2,6 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include <optional.h>
#include <streams.h>
#include <test/fuzz/FuzzedDataProvider.h>
#include <test/fuzz/fuzz.h>
diff --git a/src/test/fuzz/deserialize.cpp b/src/test/fuzz/deserialize.cpp
index 64c6e49615..1290c78712 100644
--- a/src/test/fuzz/deserialize.cpp
+++ b/src/test/fuzz/deserialize.cpp
@@ -15,7 +15,6 @@
#include <net.h>
#include <netbase.h>
#include <node/utxo_snapshot.h>
-#include <optional.h>
#include <primitives/block.h>
#include <protocol.h>
#include <psbt.h>
@@ -26,6 +25,7 @@
#include <version.h>
#include <exception>
+#include <optional>
#include <stdexcept>
#include <stdint.h>
#include <unistd.h>
@@ -69,7 +69,7 @@ T Deserialize(CDataStream ds)
}
template <typename T>
-void DeserializeFromFuzzingInput(FuzzBufferType buffer, T& obj, const Optional<int> protocol_version = nullopt)
+void DeserializeFromFuzzingInput(FuzzBufferType buffer, T& obj, const std::optional<int> protocol_version = std::nullopt)
{
CDataStream ds(buffer, SER_NETWORK, INIT_PROTO_VERSION);
if (protocol_version) {
diff --git a/src/test/fuzz/net.cpp b/src/test/fuzz/net.cpp
index b056f46f2e..272f6415a9 100644
--- a/src/test/fuzz/net.cpp
+++ b/src/test/fuzz/net.cpp
@@ -7,7 +7,6 @@
#include <net.h>
#include <net_permissions.h>
#include <netaddress.h>
-#include <optional.h>
#include <protocol.h>
#include <random.h>
#include <test/fuzz/FuzzedDataProvider.h>
@@ -17,6 +16,7 @@
#include <test/util/setup_common.h>
#include <cstdint>
+#include <optional>
#include <string>
#include <vector>
diff --git a/src/test/fuzz/node_eviction.cpp b/src/test/fuzz/node_eviction.cpp
index 606ebfc151..603d520cf5 100644
--- a/src/test/fuzz/node_eviction.cpp
+++ b/src/test/fuzz/node_eviction.cpp
@@ -3,7 +3,6 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <net.h>
-#include <optional.h>
#include <protocol.h>
#include <test/fuzz/FuzzedDataProvider.h>
#include <test/fuzz/fuzz.h>
@@ -37,7 +36,7 @@ FUZZ_TARGET(node_eviction)
// Make a copy since eviction_candidates may be in some valid but otherwise
// indeterminate state after the SelectNodeToEvict(&&) call.
const std::vector<NodeEvictionCandidate> eviction_candidates_copy = eviction_candidates;
- const Optional<NodeId> node_to_evict = SelectNodeToEvict(std::move(eviction_candidates));
+ const std::optional<NodeId> node_to_evict = SelectNodeToEvict(std::move(eviction_candidates));
if (node_to_evict) {
assert(std::any_of(eviction_candidates_copy.begin(), eviction_candidates_copy.end(), [&node_to_evict](const NodeEvictionCandidate& eviction_candidate) { return *node_to_evict == eviction_candidate.id; }));
}
diff --git a/src/test/fuzz/p2p_transport_deserializer.cpp b/src/test/fuzz/p2p_transport_deserializer.cpp
index 163f1b839e..3a1fdaad8f 100644
--- a/src/test/fuzz/p2p_transport_deserializer.cpp
+++ b/src/test/fuzz/p2p_transport_deserializer.cpp
@@ -10,6 +10,7 @@
#include <cassert>
#include <cstdint>
#include <limits>
+#include <optional>
#include <vector>
void initialize_p2p_transport_deserializer()
@@ -30,7 +31,7 @@ FUZZ_TARGET_INIT(p2p_transport_deserializer, initialize_p2p_transport_deserializ
if (deserializer.Complete()) {
const std::chrono::microseconds m_time{std::numeric_limits<int64_t>::max()};
uint32_t out_err_raw_size{0};
- Optional<CNetMessage> result{deserializer.GetMessage(m_time, out_err_raw_size)};
+ std::optional<CNetMessage> result{deserializer.GetMessage(m_time, out_err_raw_size)};
if (result) {
assert(result->m_command.size() <= CMessageHeader::COMMAND_SIZE);
assert(result->m_raw_message_size <= buffer.size());
diff --git a/src/test/fuzz/parse_numbers.cpp b/src/test/fuzz/parse_numbers.cpp
index ddd2bcfba3..1ad5fb6a05 100644
--- a/src/test/fuzz/parse_numbers.cpp
+++ b/src/test/fuzz/parse_numbers.cpp
@@ -18,6 +18,9 @@ FUZZ_TARGET(parse_numbers)
double d;
(void)ParseDouble(random_string, &d);
+ uint8_t u8;
+ (void)ParseUInt8(random_string, &u8);
+
int32_t i32;
(void)ParseInt32(random_string, &i32);
(void)atoi(random_string);
diff --git a/src/test/fuzz/psbt.cpp b/src/test/fuzz/psbt.cpp
index eb2754054a..d1cc6f9c7e 100644
--- a/src/test/fuzz/psbt.cpp
+++ b/src/test/fuzz/psbt.cpp
@@ -5,7 +5,6 @@
#include <test/fuzz/fuzz.h>
#include <node/psbt.h>
-#include <optional.h>
#include <psbt.h>
#include <pubkey.h>
#include <script/script.h>
@@ -13,6 +12,7 @@
#include <version.h>
#include <cstdint>
+#include <optional>
#include <string>
#include <vector>
@@ -39,7 +39,7 @@ FUZZ_TARGET_INIT(psbt, initialize_psbt)
(void)psbt.IsNull();
- Optional<CMutableTransaction> tx = psbt.tx;
+ std::optional<CMutableTransaction> tx = psbt.tx;
if (tx) {
const CMutableTransaction& mtx = *tx;
const PartiallySignedTransaction psbt_from_tx{mtx};
diff --git a/src/test/fuzz/script_descriptor_cache.cpp b/src/test/fuzz/script_descriptor_cache.cpp
index 1c62c018e7..6ce13d5679 100644
--- a/src/test/fuzz/script_descriptor_cache.cpp
+++ b/src/test/fuzz/script_descriptor_cache.cpp
@@ -2,7 +2,6 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include <optional.h>
#include <pubkey.h>
#include <script/descriptor.h>
#include <test/fuzz/FuzzedDataProvider.h>
@@ -10,6 +9,7 @@
#include <test/fuzz/util.h>
#include <cstdint>
+#include <optional>
#include <string>
#include <vector>
diff --git a/src/test/fuzz/system.cpp b/src/test/fuzz/system.cpp
index d9571209fa..b25dcfcd3b 100644
--- a/src/test/fuzz/system.cpp
+++ b/src/test/fuzz/system.cpp
@@ -51,7 +51,7 @@ FUZZ_TARGET(system)
// Avoid hitting:
// util/system.cpp:425: void ArgsManager::AddArg(const std::string &, const std::string &, unsigned int, const OptionsCategory &): Assertion `ret.second' failed.
const std::string argument_name = GetArgumentName(fuzzed_data_provider.ConsumeRandomLengthString(16));
- if (args_manager.GetArgFlags(argument_name) != nullopt) {
+ if (args_manager.GetArgFlags(argument_name) != std::nullopt) {
return;
}
args_manager.AddArg(argument_name, fuzzed_data_provider.ConsumeRandomLengthString(16), fuzzed_data_provider.ConsumeIntegral<unsigned int>() & ~ArgsManager::COMMAND, options_category);
@@ -63,7 +63,7 @@ FUZZ_TARGET(system)
std::vector<std::string> hidden_arguments;
for (const std::string& name : names) {
const std::string hidden_argument = GetArgumentName(name);
- if (args_manager.GetArgFlags(hidden_argument) != nullopt) {
+ if (args_manager.GetArgFlags(hidden_argument) != std::nullopt) {
continue;
}
if (std::find(hidden_arguments.begin(), hidden_arguments.end(), hidden_argument) != hidden_arguments.end()) {
diff --git a/src/test/net_tests.cpp b/src/test/net_tests.cpp
index 167242a971..3172f119bd 100644
--- a/src/test/net_tests.cpp
+++ b/src/test/net_tests.cpp
@@ -9,7 +9,6 @@
#include <cstdint>
#include <net.h>
#include <netbase.h>
-#include <optional.h>
#include <serialize.h>
#include <span.h>
#include <streams.h>
@@ -24,6 +23,7 @@
#include <algorithm>
#include <ios>
#include <memory>
+#include <optional>
#include <string>
using namespace std::literals;
@@ -827,7 +827,7 @@ std::vector<NodeEvictionCandidate> GetRandomNodeEvictionCandidates(const int n_c
bool IsEvicted(std::vector<NodeEvictionCandidate> candidates, const std::vector<NodeId>& node_ids, FastRandomContext& random_context)
{
Shuffle(candidates.begin(), candidates.end(), random_context);
- const Optional<NodeId> evicted_node_id = SelectNodeToEvict(std::move(candidates));
+ const std::optional<NodeId> evicted_node_id = SelectNodeToEvict(std::move(candidates));
if (!evicted_node_id) {
return false;
}
diff --git a/src/test/sanity_tests.cpp b/src/test/sanity_tests.cpp
index 3e4b963fe3..496292875d 100644
--- a/src/test/sanity_tests.cpp
+++ b/src/test/sanity_tests.cpp
@@ -13,7 +13,6 @@ BOOST_FIXTURE_TEST_SUITE(sanity_tests, BasicTestingSetup)
BOOST_AUTO_TEST_CASE(basic_sanity)
{
- BOOST_CHECK_MESSAGE(glibc_sanity_test() == true, "libc sanity test");
BOOST_CHECK_MESSAGE(glibcxx_sanity_test() == true, "stdlib sanity test");
BOOST_CHECK_MESSAGE(ECC_InitSanityCheck() == true, "secp256k1 sanity test");
BOOST_CHECK_MESSAGE(ChronoSanityCheck() == true, "chrono epoch test");
diff --git a/src/test/sock_tests.cpp b/src/test/sock_tests.cpp
index ed9780dfb5..400de875b7 100644
--- a/src/test/sock_tests.cpp
+++ b/src/test/sock_tests.cpp
@@ -4,11 +4,13 @@
#include <compat.h>
#include <test/util/setup_common.h>
+#include <threadinterrupt.h>
#include <util/sock.h>
#include <util/system.h>
#include <boost/test/unit_test.hpp>
+#include <cassert>
#include <thread>
using namespace std::chrono_literals;
@@ -144,6 +146,35 @@ BOOST_AUTO_TEST_CASE(wait)
waiter.join();
}
+BOOST_AUTO_TEST_CASE(recv_until_terminator_limit)
+{
+ constexpr auto timeout = 1min; // High enough so that it is never hit.
+ CThreadInterrupt interrupt;
+ int s[2];
+ CreateSocketPair(s);
+
+ Sock sock_send(s[0]);
+ Sock sock_recv(s[1]);
+
+ std::thread receiver([&sock_recv, &timeout, &interrupt]() {
+ constexpr size_t max_data{10};
+ bool threw_as_expected{false};
+ // BOOST_CHECK_EXCEPTION() writes to some variables shared with the main thread which
+ // creates a data race. So mimic it manually.
+ try {
+ sock_recv.RecvUntilTerminator('\n', timeout, interrupt, max_data);
+ } catch (const std::runtime_error& e) {
+ threw_as_expected = HasReason("too many bytes without a terminator")(e);
+ }
+ assert(threw_as_expected);
+ });
+
+ BOOST_REQUIRE_NO_THROW(sock_send.SendComplete("1234567", timeout, interrupt));
+ BOOST_REQUIRE_NO_THROW(sock_send.SendComplete("89a\n", timeout, interrupt));
+
+ receiver.join();
+}
+
#endif /* WIN32 */
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp
index b742fcaf0b..98a322eae5 100644
--- a/src/test/util_tests.cpp
+++ b/src/test/util_tests.cpp
@@ -7,7 +7,6 @@
#include <clientversion.h>
#include <hash.h> // For Hash()
#include <key.h> // For CKey
-#include <optional.h>
#include <sync.h>
#include <test/util/logging.h>
#include <test/util/setup_common.h>
@@ -23,6 +22,7 @@
#include <util/vector.h>
#include <array>
+#include <optional>
#include <stdint.h>
#include <string.h>
#include <thread>
@@ -38,6 +38,7 @@
#include <boost/test/unit_test.hpp>
using namespace std::literals;
+static const std::string STRING_WITH_EMBEDDED_NULL_CHAR{"1"s "\0" "1"s};
/* defined in logging.cpp */
namespace BCLog {
@@ -227,9 +228,9 @@ public:
bool default_int = false;
bool default_bool = false;
const char* string_value = nullptr;
- Optional<int64_t> int_value;
- Optional<bool> bool_value;
- Optional<std::vector<std::string>> list_value;
+ std::optional<int64_t> int_value;
+ std::optional<bool> bool_value;
+ std::optional<std::vector<std::string>> list_value;
const char* error = nullptr;
explicit Expect(util::SettingsValue s) : setting(std::move(s)) {}
@@ -1272,7 +1273,7 @@ BOOST_AUTO_TEST_CASE(util_ParseMoney)
// Parsing strings with embedded NUL characters should fail
BOOST_CHECK(!ParseMoney("\0-1"s, ret));
- BOOST_CHECK(!ParseMoney("\0" "1"s, ret));
+ BOOST_CHECK(!ParseMoney(STRING_WITH_EMBEDDED_NULL_CHAR, ret));
BOOST_CHECK(!ParseMoney("1\0"s, ret));
}
@@ -1450,9 +1451,7 @@ BOOST_AUTO_TEST_CASE(test_ParseInt32)
BOOST_CHECK(!ParseInt32("aap", &n));
BOOST_CHECK(!ParseInt32("0x1", &n)); // no hex
BOOST_CHECK(!ParseInt32("0x1", &n)); // no hex
- const char test_bytes[] = {'1', 0, '1'};
- std::string teststr(test_bytes, sizeof(test_bytes));
- BOOST_CHECK(!ParseInt32(teststr, &n)); // no embedded NULs
+ BOOST_CHECK(!ParseInt32(STRING_WITH_EMBEDDED_NULL_CHAR, &n));
// Overflow and underflow
BOOST_CHECK(!ParseInt32("-2147483649", nullptr));
BOOST_CHECK(!ParseInt32("2147483648", nullptr));
@@ -1480,9 +1479,7 @@ BOOST_AUTO_TEST_CASE(test_ParseInt64)
BOOST_CHECK(!ParseInt64("1a", &n));
BOOST_CHECK(!ParseInt64("aap", &n));
BOOST_CHECK(!ParseInt64("0x1", &n)); // no hex
- const char test_bytes[] = {'1', 0, '1'};
- std::string teststr(test_bytes, sizeof(test_bytes));
- BOOST_CHECK(!ParseInt64(teststr, &n)); // no embedded NULs
+ BOOST_CHECK(!ParseInt64(STRING_WITH_EMBEDDED_NULL_CHAR, &n));
// Overflow and underflow
BOOST_CHECK(!ParseInt64("-9223372036854775809", nullptr));
BOOST_CHECK(!ParseInt64("9223372036854775808", nullptr));
@@ -1490,6 +1487,42 @@ BOOST_AUTO_TEST_CASE(test_ParseInt64)
BOOST_CHECK(!ParseInt64("32482348723847471234", nullptr));
}
+BOOST_AUTO_TEST_CASE(test_ParseUInt8)
+{
+ uint8_t n;
+ // Valid values
+ BOOST_CHECK(ParseUInt8("255", nullptr));
+ BOOST_CHECK(ParseUInt8("0", &n) && n == 0);
+ BOOST_CHECK(ParseUInt8("255", &n) && n == 255);
+ BOOST_CHECK(ParseUInt8("0255", &n) && n == 255); // no octal
+ BOOST_CHECK(ParseUInt8("255", &n) && n == static_cast<uint8_t>(255));
+ BOOST_CHECK(ParseUInt8("+255", &n) && n == 255);
+ BOOST_CHECK(ParseUInt8("00000000000000000012", &n) && n == 12);
+ BOOST_CHECK(ParseUInt8("00000000000000000000", &n) && n == 0);
+ // Invalid values
+ BOOST_CHECK(!ParseUInt8("-00000000000000000000", &n));
+ BOOST_CHECK(!ParseUInt8("", &n));
+ BOOST_CHECK(!ParseUInt8(" 1", &n)); // no padding inside
+ BOOST_CHECK(!ParseUInt8(" -1", &n));
+ BOOST_CHECK(!ParseUInt8("++1", &n));
+ BOOST_CHECK(!ParseUInt8("+-1", &n));
+ BOOST_CHECK(!ParseUInt8("-+1", &n));
+ BOOST_CHECK(!ParseUInt8("--1", &n));
+ BOOST_CHECK(!ParseUInt8("-1", &n));
+ BOOST_CHECK(!ParseUInt8("1 ", &n));
+ BOOST_CHECK(!ParseUInt8("1a", &n));
+ BOOST_CHECK(!ParseUInt8("aap", &n));
+ BOOST_CHECK(!ParseUInt8("0x1", &n)); // no hex
+ BOOST_CHECK(!ParseUInt8("0x1", &n)); // no hex
+ BOOST_CHECK(!ParseUInt8(STRING_WITH_EMBEDDED_NULL_CHAR, &n));
+ // Overflow and underflow
+ BOOST_CHECK(!ParseUInt8("-255", &n));
+ BOOST_CHECK(!ParseUInt8("256", &n));
+ BOOST_CHECK(!ParseUInt8("-123", &n));
+ BOOST_CHECK(!ParseUInt8("-123", nullptr));
+ BOOST_CHECK(!ParseUInt8("256", nullptr));
+}
+
BOOST_AUTO_TEST_CASE(test_ParseUInt32)
{
uint32_t n;
@@ -1519,9 +1552,7 @@ BOOST_AUTO_TEST_CASE(test_ParseUInt32)
BOOST_CHECK(!ParseUInt32("aap", &n));
BOOST_CHECK(!ParseUInt32("0x1", &n)); // no hex
BOOST_CHECK(!ParseUInt32("0x1", &n)); // no hex
- const char test_bytes[] = {'1', 0, '1'};
- std::string teststr(test_bytes, sizeof(test_bytes));
- BOOST_CHECK(!ParseUInt32(teststr, &n)); // no embedded NULs
+ BOOST_CHECK(!ParseUInt32(STRING_WITH_EMBEDDED_NULL_CHAR, &n));
// Overflow and underflow
BOOST_CHECK(!ParseUInt32("-2147483648", &n));
BOOST_CHECK(!ParseUInt32("4294967296", &n));
@@ -1550,9 +1581,7 @@ BOOST_AUTO_TEST_CASE(test_ParseUInt64)
BOOST_CHECK(!ParseUInt64("1a", &n));
BOOST_CHECK(!ParseUInt64("aap", &n));
BOOST_CHECK(!ParseUInt64("0x1", &n)); // no hex
- const char test_bytes[] = {'1', 0, '1'};
- std::string teststr(test_bytes, sizeof(test_bytes));
- BOOST_CHECK(!ParseUInt64(teststr, &n)); // no embedded NULs
+ BOOST_CHECK(!ParseUInt64(STRING_WITH_EMBEDDED_NULL_CHAR, &n));
// Overflow and underflow
BOOST_CHECK(!ParseUInt64("-9223372036854775809", nullptr));
BOOST_CHECK(!ParseUInt64("18446744073709551616", nullptr));
@@ -1582,9 +1611,7 @@ BOOST_AUTO_TEST_CASE(test_ParseDouble)
BOOST_CHECK(!ParseDouble("1a", &n));
BOOST_CHECK(!ParseDouble("aap", &n));
BOOST_CHECK(!ParseDouble("0x1", &n)); // no hex
- const char test_bytes[] = {'1', 0, '1'};
- std::string teststr(test_bytes, sizeof(test_bytes));
- BOOST_CHECK(!ParseDouble(teststr, &n)); // no embedded NULs
+ BOOST_CHECK(!ParseDouble(STRING_WITH_EMBEDDED_NULL_CHAR, &n));
// Overflow and underflow
BOOST_CHECK(!ParseDouble("-1e10000", nullptr));
BOOST_CHECK(!ParseDouble("1e10000", nullptr));
diff --git a/src/txmempool.cpp b/src/txmempool.cpp
index f10b4ad740..faccd1ade0 100644
--- a/src/txmempool.cpp
+++ b/src/txmempool.cpp
@@ -8,7 +8,6 @@
#include <consensus/consensus.h>
#include <consensus/tx_verify.h>
#include <consensus/validation.h>
-#include <optional.h>
#include <policy/fees.h>
#include <policy/policy.h>
#include <policy/settings.h>
@@ -19,6 +18,8 @@
#include <validation.h>
#include <validationinterface.h>
+#include <optional>
+
CTxMemPoolEntry::CTxMemPoolEntry(const CTransactionRef& _tx, const CAmount& _nFee,
int64_t _nTime, unsigned int _entryHeight,
bool _spendsCoinbase, int64_t _sigOpsCost, LockPoints lp)
@@ -159,7 +160,7 @@ bool CTxMemPool::CalculateMemPoolAncestors(const CTxMemPoolEntry &entry, setEntr
// GetMemPoolParents() is only valid for entries in the mempool, so we
// iterate mapTx to find parents.
for (unsigned int i = 0; i < tx.vin.size(); i++) {
- Optional<txiter> piter = GetIter(tx.vin[i].prevout.hash);
+ std::optional<txiter> piter = GetIter(tx.vin[i].prevout.hash);
if (piter) {
staged_ancestors.insert(**piter);
if (staged_ancestors.size() + 1 > limitAncestorCount) {
@@ -890,11 +891,11 @@ const CTransaction* CTxMemPool::GetConflictTx(const COutPoint& prevout) const
return it == mapNextTx.end() ? nullptr : it->second;
}
-Optional<CTxMemPool::txiter> CTxMemPool::GetIter(const uint256& txid) const
+std::optional<CTxMemPool::txiter> CTxMemPool::GetIter(const uint256& txid) const
{
auto it = mapTx.find(txid);
if (it != mapTx.end()) return it;
- return Optional<txiter>{};
+ return {};
}
CTxMemPool::setEntries CTxMemPool::GetIterSet(const std::set<uint256>& hashes) const
diff --git a/src/txmempool.h b/src/txmempool.h
index 8a96294192..9d4ea760e7 100644
--- a/src/txmempool.h
+++ b/src/txmempool.h
@@ -8,6 +8,7 @@
#include <atomic>
#include <map>
+#include <optional>
#include <set>
#include <string>
#include <utility>
@@ -16,7 +17,6 @@
#include <amount.h>
#include <coins.h>
#include <indirectmap.h>
-#include <optional.h>
#include <policy/feerate.h>
#include <primitives/transaction.h>
#include <random.h>
@@ -644,7 +644,7 @@ public:
const CTransaction* GetConflictTx(const COutPoint& prevout) const EXCLUSIVE_LOCKS_REQUIRED(cs);
/** Returns an iterator to the given hash, if found */
- Optional<txiter> GetIter(const uint256& txid) const EXCLUSIVE_LOCKS_REQUIRED(cs);
+ std::optional<txiter> GetIter(const uint256& txid) const EXCLUSIVE_LOCKS_REQUIRED(cs);
/** Translate a set of hashes into a set of pool iterators to avoid repeated lookups */
setEntries GetIterSet(const std::set<uint256>& hashes) const EXCLUSIVE_LOCKS_REQUIRED(cs);
@@ -841,7 +841,7 @@ public:
return m_epoch.visited(it->m_epoch_marker);
}
- bool visited(Optional<txiter> it) const EXCLUSIVE_LOCKS_REQUIRED(cs, m_epoch)
+ bool visited(std::optional<txiter> it) const EXCLUSIVE_LOCKS_REQUIRED(cs, m_epoch)
{
assert(m_epoch.guarded()); // verify guard even when it==nullopt
return !it || visited(*it);
diff --git a/src/util/sock.cpp b/src/util/sock.cpp
index e13c52a16a..f9ecfef5d4 100644
--- a/src/util/sock.cpp
+++ b/src/util/sock.cpp
@@ -175,7 +175,8 @@ void Sock::SendComplete(const std::string& data,
std::string Sock::RecvUntilTerminator(uint8_t terminator,
std::chrono::milliseconds timeout,
- CThreadInterrupt& interrupt) const
+ CThreadInterrupt& interrupt,
+ size_t max_data) const
{
const auto deadline = GetTime<std::chrono::milliseconds>() + timeout;
std::string data;
@@ -190,9 +191,14 @@ std::string Sock::RecvUntilTerminator(uint8_t terminator,
// at a time is about 50 times slower.
for (;;) {
+ if (data.size() >= max_data) {
+ throw std::runtime_error(
+ strprintf("Received too many bytes without a terminator (%u)", data.size()));
+ }
+
char buf[512];
- const ssize_t peek_ret{Recv(buf, sizeof(buf), MSG_PEEK)};
+ const ssize_t peek_ret{Recv(buf, std::min(sizeof(buf), max_data - data.size()), MSG_PEEK)};
switch (peek_ret) {
case -1: {
diff --git a/src/util/sock.h b/src/util/sock.h
index ecebb84205..4b0618dcff 100644
--- a/src/util/sock.h
+++ b/src/util/sock.h
@@ -135,13 +135,16 @@ public:
* @param[in] terminator Character up to which to read from the socket.
* @param[in] timeout Timeout for the entire operation.
* @param[in] interrupt If this is signaled then the operation is canceled.
+ * @param[in] max_data The maximum amount of data (in bytes) to receive. If this many bytes
+ * are received and there is still no terminator, then this method will throw an exception.
* @return The data that has been read, without the terminating character.
* @throws std::runtime_error if the operation cannot be completed. In this case some bytes may
* have been consumed from the socket.
*/
virtual std::string RecvUntilTerminator(uint8_t terminator,
std::chrono::milliseconds timeout,
- CThreadInterrupt& interrupt) const;
+ CThreadInterrupt& interrupt,
+ size_t max_data) const;
/**
* Check if still connected.
diff --git a/src/util/system.cpp b/src/util/system.cpp
index 63b3c52ee5..0b83a76504 100644
--- a/src/util/system.cpp
+++ b/src/util/system.cpp
@@ -315,7 +315,7 @@ bool ArgsManager::ParseParameters(int argc, const char* const argv[], std::strin
if (key[0] != '-') {
if (!m_accept_any_command && m_command.empty()) {
// The first non-dash arg is a registered command
- Optional<unsigned int> flags = GetArgFlags(key);
+ std::optional<unsigned int> flags = GetArgFlags(key);
if (!flags || !(*flags & ArgsManager::COMMAND)) {
error = strprintf("Invalid command '%s'", argv[i]);
return false;
@@ -337,7 +337,7 @@ bool ArgsManager::ParseParameters(int argc, const char* const argv[], std::strin
key.erase(0, 1);
std::string section;
util::SettingsValue value = InterpretOption(section, key, val);
- Optional<unsigned int> flags = GetArgFlags('-' + key);
+ std::optional<unsigned int> flags = GetArgFlags('-' + key);
// Unknown command line options and command line options with dot
// characters (which are returned from InterpretOption with nonempty
@@ -363,7 +363,7 @@ bool ArgsManager::ParseParameters(int argc, const char* const argv[], std::strin
return success;
}
-Optional<unsigned int> ArgsManager::GetArgFlags(const std::string& name) const
+std::optional<unsigned int> ArgsManager::GetArgFlags(const std::string& name) const
{
LOCK(cs_args);
for (const auto& arg_map : m_available_args) {
@@ -372,7 +372,7 @@ Optional<unsigned int> ArgsManager::GetArgFlags(const std::string& name) const
return search->second.m_flags;
}
}
- return nullopt;
+ return std::nullopt;
}
std::optional<const ArgsManager::Command> ArgsManager::GetCommand() const
@@ -874,7 +874,7 @@ bool ArgsManager::ReadConfigStream(std::istream& stream, const std::string& file
std::string section;
std::string key = option.first;
util::SettingsValue value = InterpretOption(section, key, option.second);
- Optional<unsigned int> flags = GetArgFlags('-' + key);
+ std::optional<unsigned int> flags = GetArgFlags('-' + key);
if (flags) {
if (!CheckValid(key, value, *flags, error)) {
return false;
@@ -1034,7 +1034,7 @@ void ArgsManager::logArgsPrefix(
std::string section_str = section.empty() ? "" : "[" + section + "] ";
for (const auto& arg : args) {
for (const auto& value : arg.second) {
- Optional<unsigned int> flags = GetArgFlags('-' + arg.first);
+ std::optional<unsigned int> flags = GetArgFlags('-' + arg.first);
if (flags) {
std::string value_str = (*flags & SENSITIVE) ? "****" : value.write();
LogPrintf("%s %s%s=%s\n", prefix, section_str, arg.first, value_str);
diff --git a/src/util/system.h b/src/util/system.h
index 30b8cb1c68..291f3f5541 100644
--- a/src/util/system.h
+++ b/src/util/system.h
@@ -19,7 +19,6 @@
#include <compat/assumptions.h>
#include <fs.h>
#include <logging.h>
-#include <optional.h>
#include <sync.h>
#include <tinyformat.h>
#include <util/settings.h>
@@ -28,6 +27,7 @@
#include <exception>
#include <map>
+#include <optional>
#include <set>
#include <stdint.h>
#include <string>
@@ -375,7 +375,7 @@ public:
* Return Flags for known arg.
* Return nullopt for unknown arg.
*/
- Optional<unsigned int> GetArgFlags(const std::string& name) const;
+ std::optional<unsigned int> GetArgFlags(const std::string& name) const;
/**
* Read and update settings file with saved settings. This needs to be
diff --git a/src/util/tokenpipe.cpp b/src/util/tokenpipe.cpp
index 79465dd430..4c091cd2e6 100644
--- a/src/util/tokenpipe.cpp
+++ b/src/util/tokenpipe.cpp
@@ -9,6 +9,7 @@
#include <errno.h>
#include <fcntl.h>
+#include <optional>
#include <unistd.h>
TokenPipeEnd TokenPipe::TakeReadEnd()
diff --git a/src/validation.cpp b/src/validation.cpp
index a1bd79bdfc..74df13f462 100644
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -23,7 +23,6 @@
#include <logging/timer.h>
#include <node/coinstats.h>
#include <node/ui_interface.h>
-#include <optional.h>
#include <policy/policy.h>
#include <policy/settings.h>
#include <pow.h>
@@ -50,6 +49,7 @@
#include <validationinterface.h>
#include <warnings.h>
+#include <optional>
#include <string>
#include <boost/algorithm/string/replace.hpp>
@@ -5175,7 +5175,7 @@ double GuessVerificationProgress(const ChainTxData& data, const CBlockIndex *pin
return std::min<double>(pindex->nChainTx / fTxTotal, 1.0);
}
-Optional<uint256> ChainstateManager::SnapshotBlockhash() const {
+std::optional<uint256> ChainstateManager::SnapshotBlockhash() const {
LOCK(::cs_main);
if (m_active_chainstate != nullptr &&
!m_active_chainstate->m_from_snapshot_blockhash.IsNull()) {
diff --git a/src/validation.h b/src/validation.h
index ea783ddcd1..2ff5f4ac87 100644
--- a/src/validation.h
+++ b/src/validation.h
@@ -17,7 +17,6 @@
#include <crypto/common.h> // for ReadLE64
#include <fs.h>
#include <node/utxo_snapshot.h>
-#include <optional.h>
#include <policy/feerate.h>
#include <protocol.h> // For CMessageHeader::MessageStartChars
#include <script/script_error.h>
@@ -32,6 +31,7 @@
#include <atomic>
#include <map>
#include <memory>
+#include <optional>
#include <set>
#include <stdint.h>
#include <string>
@@ -205,8 +205,7 @@ struct MempoolAcceptResult {
/** Constructor for failure case */
explicit MempoolAcceptResult(TxValidationState state)
- : m_result_type(ResultType::INVALID),
- m_state(state), m_replaced_transactions(nullopt), m_base_fees(nullopt) {
+ : m_result_type(ResultType::INVALID), m_state(state) {
Assume(!state.IsValid()); // Can be invalid or error
}
@@ -924,7 +923,7 @@ public:
bool IsSnapshotActive() const;
- Optional<uint256> SnapshotBlockhash() const;
+ std::optional<uint256> SnapshotBlockhash() const;
//! Is there a snapshot in use and has it been fully validated?
bool IsSnapshotValidated() const { return m_snapshot_validated; }
diff --git a/src/wallet/coincontrol.h b/src/wallet/coincontrol.h
index c499b0ff25..d25a3fb3fa 100644
--- a/src/wallet/coincontrol.h
+++ b/src/wallet/coincontrol.h
@@ -5,13 +5,14 @@
#ifndef BITCOIN_WALLET_COINCONTROL_H
#define BITCOIN_WALLET_COINCONTROL_H
-#include <optional.h>
#include <outputtype.h>
#include <policy/feerate.h>
#include <policy/fees.h>
#include <primitives/transaction.h>
#include <script/standard.h>
+#include <optional>
+
const int DEFAULT_MIN_DEPTH = 0;
const int DEFAULT_MAX_DEPTH = 9999999;
@@ -25,7 +26,7 @@ public:
//! Custom change destination, if not set an address is generated
CTxDestination destChange;
//! Override the default change type if set, ignored if destChange is set
- Optional<OutputType> m_change_type;
+ std::optional<OutputType> m_change_type;
//! If false, only selected inputs are used
bool m_add_inputs;
//! If false, allows unselected inputs, but requires all selected inputs be used
@@ -35,11 +36,11 @@ public:
//! Override automatic min/max checks on fee, m_feerate must be set if true
bool fOverrideFeeRate;
//! Override the wallet's m_pay_tx_fee if set
- Optional<CFeeRate> m_feerate;
+ std::optional<CFeeRate> m_feerate;
//! Override the default confirmation target if set
- Optional<unsigned int> m_confirm_target;
+ std::optional<unsigned int> m_confirm_target;
//! Override the wallet's m_signal_rbf if set
- Optional<bool> m_signal_bip125_rbf;
+ std::optional<bool> m_signal_bip125_rbf;
//! Avoid partial use of funds sent to a given address
bool m_avoid_partial_spends;
//! Forbids inclusion of dirty (previously used) addresses
diff --git a/src/wallet/coinselection.cpp b/src/wallet/coinselection.cpp
index 10f89e3a6f..5a18308a73 100644
--- a/src/wallet/coinselection.cpp
+++ b/src/wallet/coinselection.cpp
@@ -4,11 +4,12 @@
#include <wallet/coinselection.h>
-#include <optional.h>
#include <policy/feerate.h>
#include <util/system.h>
#include <util/moneystr.h>
+#include <optional>
+
// Descending order comparator
struct {
bool operator()(const OutputGroup& a, const OutputGroup& b) const
@@ -222,7 +223,7 @@ bool KnapsackSolver(const CAmount& nTargetValue, std::vector<OutputGroup>& group
nValueRet = 0;
// List of values less than target
- Optional<OutputGroup> lowest_larger;
+ std::optional<OutputGroup> lowest_larger;
std::vector<OutputGroup> applicable_groups;
CAmount nTotalLower = 0;
diff --git a/src/wallet/db.h b/src/wallet/db.h
index b64e9fa533..7a0d3d2e07 100644
--- a/src/wallet/db.h
+++ b/src/wallet/db.h
@@ -8,12 +8,12 @@
#include <clientversion.h>
#include <fs.h>
-#include <optional.h>
#include <streams.h>
#include <support/allocators/secure.h>
#include <atomic>
#include <memory>
+#include <optional>
#include <string>
struct bilingual_str;
@@ -203,7 +203,7 @@ enum class DatabaseFormat {
struct DatabaseOptions {
bool require_existing = false;
bool require_create = false;
- Optional<DatabaseFormat> require_format;
+ std::optional<DatabaseFormat> require_format;
uint64_t create_flags = 0;
SecureString create_passphrase;
bool verify = true;
diff --git a/src/wallet/load.cpp b/src/wallet/load.cpp
index 30832f983b..4543f6fb4c 100644
--- a/src/wallet/load.cpp
+++ b/src/wallet/load.cpp
@@ -154,7 +154,7 @@ void UnloadWallets()
auto wallet = wallets.back();
wallets.pop_back();
std::vector<bilingual_str> warnings;
- RemoveWallet(wallet, nullopt, warnings);
+ RemoveWallet(wallet, std::nullopt, warnings);
UnloadWallet(std::move(wallet));
}
}
diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp
index 50423c3e32..0737e68cf3 100644
--- a/src/wallet/rpcdump.cpp
+++ b/src/wallet/rpcdump.cpp
@@ -1788,7 +1788,7 @@ RPCHelpMan listdescriptors()
const bool active = active_spk_mans.count(desc_spk_man) != 0;
spk.pushKV("active", active);
const auto& type = wallet_descriptor.descriptor->GetOutputType();
- if (active && type != nullopt) {
+ if (active && type) {
spk.pushKV("internal", wallet->GetScriptPubKeyMan(*type, true) == desc_spk_man);
}
if (wallet_descriptor.descriptor->IsRange()) {
diff --git a/src/wallet/rpcsigner.cpp b/src/wallet/rpcsigner.cpp
index 607b778c68..696c74d665 100644
--- a/src/wallet/rpcsigner.cpp
+++ b/src/wallet/rpcsigner.cpp
@@ -32,9 +32,6 @@ static RPCHelpMan enumeratesigners()
},
RPCExamples{""},
[](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue {
- std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
- if (!wallet) return NullUniValue;
-
const std::string command = gArgs.GetArg("-signer", "");
if (command == "") throw JSONRPCError(RPC_WALLET_ERROR, "Error: restart bitcoind with -signer=<cmd>");
std::string chain = gArgs.GetChainName();
diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp
index 1b9071a712..6dc8d1de42 100644
--- a/src/wallet/rpcwallet.cpp
+++ b/src/wallet/rpcwallet.cpp
@@ -8,7 +8,6 @@
#include <interfaces/chain.h>
#include <key_io.h>
#include <node/context.h>
-#include <optional.h>
#include <outputtype.h>
#include <policy/feerate.h>
#include <policy/fees.h>
@@ -38,6 +37,7 @@
#include <wallet/walletdb.h>
#include <wallet/walletutil.h>
+#include <optional>
#include <stdint.h>
#include <univalue.h>
@@ -219,7 +219,7 @@ static void SetFeeEstimateMode(const CWallet& wallet, CCoinControl& cc, const Un
cc.m_feerate = CFeeRate(AmountFromValue(fee_rate), COIN);
if (override_min_fee) cc.fOverrideFeeRate = true;
// Default RBF to true for explicit fee_rate, if unset.
- if (cc.m_signal_bip125_rbf == nullopt) cc.m_signal_bip125_rbf = true;
+ if (!cc.m_signal_bip125_rbf) cc.m_signal_bip125_rbf = true;
return;
}
if (!estimate_mode.isNull() && !FeeModeFromString(estimate_mode.get_str(), cc.m_fee_mode)) {
@@ -1564,8 +1564,8 @@ static RPCHelpMan listsinceblock()
LOCK(wallet.cs_wallet);
- Optional<int> height; // Height of the specified block or the common ancestor, if the block provided was in a deactivated chain.
- Optional<int> altheight; // Height of the specified block, even if it's in a deactivated chain.
+ std::optional<int> height; // Height of the specified block or the common ancestor, if the block provided was in a deactivated chain.
+ std::optional<int> altheight; // Height of the specified block, even if it's in a deactivated chain.
int target_confirms = 1;
isminefilter filter = ISMINE_SPENDABLE;
@@ -2590,7 +2590,7 @@ static RPCHelpMan loadwallet()
options.require_existing = true;
bilingual_str error;
std::vector<bilingual_str> warnings;
- Optional<bool> load_on_start = request.params[1].isNull() ? nullopt : Optional<bool>(request.params[1].get_bool());
+ std::optional<bool> load_on_start = request.params[1].isNull() ? std::nullopt : std::optional<bool>(request.params[1].get_bool());
std::shared_ptr<CWallet> const wallet = LoadWallet(*context.chain, name, load_on_start, options, status, error, warnings);
if (!wallet) {
// Map bad format to not found, since bad format is returned when the
@@ -2764,7 +2764,7 @@ static RPCHelpMan createwallet()
options.create_flags = flags;
options.create_passphrase = passphrase;
bilingual_str error;
- Optional<bool> load_on_start = request.params[6].isNull() ? nullopt : Optional<bool>(request.params[6].get_bool());
+ std::optional<bool> load_on_start = request.params[6].isNull() ? std::nullopt : std::optional<bool>(request.params[6].get_bool());
std::shared_ptr<CWallet> wallet = CreateWallet(*context.chain, request.params[0].get_str(), load_on_start, options, status, error, warnings);
if (!wallet) {
RPCErrorCode code = status == DatabaseStatus::FAILED_ENCRYPT ? RPC_WALLET_ENCRYPTION_FAILED : RPC_WALLET_ERROR;
@@ -2816,7 +2816,7 @@ static RPCHelpMan unloadwallet()
// Note that any attempt to load the same wallet would fail until the wallet
// is destroyed (see CheckUniqueFileid).
std::vector<bilingual_str> warnings;
- Optional<bool> load_on_start = request.params[1].isNull() ? nullopt : Optional<bool>(request.params[1].get_bool());
+ std::optional<bool> load_on_start = request.params[1].isNull() ? std::nullopt : std::optional<bool>(request.params[1].get_bool());
if (!RemoveWallet(wallet, load_on_start, warnings)) {
throw JSONRPCError(RPC_MISC_ERROR, "Requested wallet already unloaded");
}
@@ -3587,7 +3587,7 @@ static RPCHelpMan rescanblockchain()
}
int start_height = 0;
- Optional<int> stop_height;
+ std::optional<int> stop_height;
uint256 start_block;
{
LOCK(pwallet->cs_wallet);
diff --git a/src/wallet/scriptpubkeyman.cpp b/src/wallet/scriptpubkeyman.cpp
index a8200981d8..54319ca662 100644
--- a/src/wallet/scriptpubkeyman.cpp
+++ b/src/wallet/scriptpubkeyman.cpp
@@ -16,6 +16,8 @@
#include <wallet/external_signer.h>
#include <wallet/scriptpubkeyman.h>
+#include <optional>
+
//! Value for the first BIP 32 hardened derivation. Can be used as a bit mask and as a value. See BIP 32 for more details.
const uint32_t BIP32_HARDENED_KEY_LIMIT = 0x80000000;
@@ -1607,7 +1609,7 @@ bool DescriptorScriptPubKeyMan::GetNewDestination(const OutputType type, CTxDest
{
LOCK(cs_desc_man);
assert(m_wallet_descriptor.descriptor->IsSingleType()); // This is a combo descriptor which should not be an active descriptor
- Optional<OutputType> desc_addr_type = m_wallet_descriptor.descriptor->GetOutputType();
+ std::optional<OutputType> desc_addr_type = m_wallet_descriptor.descriptor->GetOutputType();
assert(desc_addr_type);
if (type != *desc_addr_type) {
throw std::runtime_error(std::string(__func__) + ": Types are inconsistent");
@@ -1629,7 +1631,7 @@ bool DescriptorScriptPubKeyMan::GetNewDestination(const OutputType type, CTxDest
return false;
}
- Optional<OutputType> out_script_type = m_wallet_descriptor.descriptor->GetOutputType();
+ std::optional<OutputType> out_script_type = m_wallet_descriptor.descriptor->GetOutputType();
if (out_script_type && out_script_type == type) {
ExtractDestination(scripts_temp[0], dest);
} else {
diff --git a/src/wallet/test/coinselector_tests.cpp b/src/wallet/test/coinselector_tests.cpp
index 0e9f3819eb..7eff6e592d 100644
--- a/src/wallet/test/coinselector_tests.cpp
+++ b/src/wallet/test/coinselector_tests.cpp
@@ -35,7 +35,10 @@ static CAmount balance = 0;
CoinEligibilityFilter filter_standard(1, 6, 0);
CoinEligibilityFilter filter_confirmed(1, 1, 0);
CoinEligibilityFilter filter_standard_extra(6, 6, 0);
-CoinSelectionParams coin_selection_params(false, 0, 0, CFeeRate(0), 0, false);
+CoinSelectionParams coin_selection_params(/* use_bnb= */ false, /* change_output_size= */ 0,
+ /* change_spend_size= */ 0, /* effective_feerate= */ CFeeRate(0),
+ /* long_term_feerate= */ CFeeRate(0), /* discard_feerate= */ CFeeRate(0),
+ /* tx_no_inputs_size= */ 0, /* avoid_partial= */ false);
static void add_coin(const CAmount& nValue, int nInput, std::vector<CInputCoin>& set)
{
@@ -269,7 +272,10 @@ BOOST_AUTO_TEST_CASE(bnb_search_test)
}
// Make sure that effective value is working in SelectCoinsMinConf when BnB is used
- CoinSelectionParams coin_selection_params_bnb(true, 0, 0, CFeeRate(3000), 0, false);
+ CoinSelectionParams coin_selection_params_bnb(/* use_bnb= */ true, /* change_output_size= */ 0,
+ /* change_spend_size= */ 0, /* effective_feerate= */ CFeeRate(3000),
+ /* long_term_feerate= */ CFeeRate(1000), /* discard_feerate= */ CFeeRate(1000),
+ /* tx_no_inputs_size= */ 0, /* avoid_partial= */ false);
CoinSet setCoinsRet;
CAmount nValueRet;
bool bnb_used;
@@ -301,7 +307,7 @@ BOOST_AUTO_TEST_CASE(bnb_search_test)
CCoinControl coin_control;
coin_control.fAllowOtherInputs = true;
coin_control.Select(COutPoint(vCoins.at(0).tx->GetHash(), vCoins.at(0).i));
- coin_selection_params_bnb.effective_fee = CFeeRate(0);
+ coin_selection_params_bnb.m_effective_feerate = CFeeRate(0);
BOOST_CHECK(wallet->SelectCoins(vCoins, 10 * CENT, setCoinsRet, nValueRet, coin_control, coin_selection_params_bnb, bnb_used));
BOOST_CHECK(bnb_used);
BOOST_CHECK(coin_selection_params_bnb.use_bnb);
@@ -639,8 +645,14 @@ BOOST_AUTO_TEST_CASE(SelectCoins_test)
CAmount target = rand.randrange(balance - 1000) + 1000;
// Perform selection
- CoinSelectionParams coin_selection_params_knapsack(false, 34, 148, CFeeRate(0), 0, false);
- CoinSelectionParams coin_selection_params_bnb(true, 34, 148, CFeeRate(0), 0, false);
+ CoinSelectionParams coin_selection_params_knapsack(/* use_bnb= */ false, /* change_output_size= */ 34,
+ /* change_spend_size= */ 148, /* effective_feerate= */ CFeeRate(0),
+ /* long_term_feerate= */ CFeeRate(0), /* discard_feerate= */ CFeeRate(0),
+ /* tx_no_inputs_size= */ 0, /* avoid_partial= */ false);
+ CoinSelectionParams coin_selection_params_bnb(/* use_bnb= */ true, /* change_output_size= */ 34,
+ /* change_spend_size= */ 148, /* effective_feerate= */ CFeeRate(0),
+ /* long_term_feerate= */ CFeeRate(0), /* discard_feerate= */ CFeeRate(0),
+ /* tx_no_inputs_size= */ 0, /* avoid_partial= */ false);
CoinSet out_set;
CAmount out_value = 0;
bool bnb_used = false;
diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp
index 4598999b3c..30cc452065 100644
--- a/src/wallet/test/wallet_tests.cpp
+++ b/src/wallet/test/wallet_tests.cpp
@@ -228,7 +228,7 @@ BOOST_FIXTURE_TEST_CASE(importmulti_rescan, TestChain100Setup)
"downloading and rescanning the relevant blocks (see -reindex and -rescan "
"options).\"}},{\"success\":true}]",
0, oldTip->GetBlockTimeMax(), TIMESTAMP_WINDOW));
- RemoveWallet(wallet, nullopt);
+ RemoveWallet(wallet, std::nullopt);
}
}
@@ -271,7 +271,7 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup)
request.params.push_back(backup_file);
::dumpwallet().HandleRequest(request);
- RemoveWallet(wallet, nullopt);
+ RemoveWallet(wallet, std::nullopt);
}
// Call importwallet RPC and verify all blocks with timestamps >= BLOCK_TIME
@@ -288,7 +288,7 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup)
AddWallet(wallet);
wallet->SetLastBlockProcessed(::ChainActive().Height(), ::ChainActive().Tip()->GetBlockHash());
::importwallet().HandleRequest(request);
- RemoveWallet(wallet, nullopt);
+ RemoveWallet(wallet, std::nullopt);
BOOST_CHECK_EQUAL(wallet->mapWallet.size(), 3U);
BOOST_CHECK_EQUAL(m_coinbase_txns.size(), 103U);
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index ac1b2a4c0a..d04279ab5e 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -13,7 +13,6 @@
#include <interfaces/wallet.h>
#include <key.h>
#include <key_io.h>
-#include <optional.h>
#include <outputtype.h>
#include <policy/fees.h>
#include <policy/policy.h>
@@ -40,6 +39,7 @@
#include <algorithm>
#include <assert.h>
+#include <optional>
#include <boost/algorithm/string/replace.hpp>
@@ -84,10 +84,10 @@ bool RemoveWalletSetting(interfaces::Chain& chain, const std::string& wallet_nam
static void UpdateWalletSetting(interfaces::Chain& chain,
const std::string& wallet_name,
- Optional<bool> load_on_startup,
+ std::optional<bool> load_on_startup,
std::vector<bilingual_str>& warnings)
{
- if (load_on_startup == nullopt) return;
+ if (!load_on_startup) return;
if (load_on_startup.value() && !AddWalletSetting(chain, wallet_name)) {
warnings.emplace_back(Untranslated("Wallet load on startup setting could not be updated, so wallet may not be loaded next node startup."));
} else if (!load_on_startup.value() && !RemoveWalletSetting(chain, wallet_name)) {
@@ -107,7 +107,7 @@ bool AddWallet(const std::shared_ptr<CWallet>& wallet)
return true;
}
-bool RemoveWallet(const std::shared_ptr<CWallet>& wallet, Optional<bool> load_on_start, std::vector<bilingual_str>& warnings)
+bool RemoveWallet(const std::shared_ptr<CWallet>& wallet, std::optional<bool> load_on_start, std::vector<bilingual_str>& warnings)
{
assert(wallet);
@@ -127,7 +127,7 @@ bool RemoveWallet(const std::shared_ptr<CWallet>& wallet, Optional<bool> load_on
return true;
}
-bool RemoveWallet(const std::shared_ptr<CWallet>& wallet, Optional<bool> load_on_start)
+bool RemoveWallet(const std::shared_ptr<CWallet>& wallet, std::optional<bool> load_on_start)
{
std::vector<bilingual_str> warnings;
return RemoveWallet(wallet, load_on_start, warnings);
@@ -204,7 +204,7 @@ void UnloadWallet(std::shared_ptr<CWallet>&& wallet)
}
namespace {
-std::shared_ptr<CWallet> LoadWalletInternal(interfaces::Chain& chain, const std::string& name, Optional<bool> load_on_start, const DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error, std::vector<bilingual_str>& warnings)
+std::shared_ptr<CWallet> LoadWalletInternal(interfaces::Chain& chain, const std::string& name, std::optional<bool> load_on_start, const DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error, std::vector<bilingual_str>& warnings)
{
try {
std::unique_ptr<WalletDatabase> database = MakeWalletDatabase(name, options, status, error);
@@ -234,7 +234,7 @@ std::shared_ptr<CWallet> LoadWalletInternal(interfaces::Chain& chain, const std:
}
} // namespace
-std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const std::string& name, Optional<bool> load_on_start, const DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error, std::vector<bilingual_str>& warnings)
+std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const std::string& name, std::optional<bool> load_on_start, const DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error, std::vector<bilingual_str>& warnings)
{
auto result = WITH_LOCK(g_loading_wallet_mutex, return g_loading_wallet_set.insert(name));
if (!result.second) {
@@ -247,7 +247,7 @@ std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const std::string&
return wallet;
}
-std::shared_ptr<CWallet> CreateWallet(interfaces::Chain& chain, const std::string& name, Optional<bool> load_on_start, DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error, std::vector<bilingual_str>& warnings)
+std::shared_ptr<CWallet> CreateWallet(interfaces::Chain& chain, const std::string& name, std::optional<bool> load_on_start, DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error, std::vector<bilingual_str>& warnings)
{
uint64_t wallet_creation_flags = options.create_flags;
const SecureString& passphrase = options.create_passphrase;
@@ -1771,7 +1771,7 @@ int64_t CWallet::RescanFromTime(int64_t startTime, const WalletRescanReserver& r
* the main chain after to the addition of any new keys you want to detect
* transactions for.
*/
-CWallet::ScanResult CWallet::ScanForWalletTransactions(const uint256& start_block, int start_height, Optional<int> max_height, const WalletRescanReserver& reserver, bool fUpdate)
+CWallet::ScanResult CWallet::ScanForWalletTransactions(const uint256& start_block, int start_height, std::optional<int> max_height, const WalletRescanReserver& reserver, bool fUpdate)
{
int64_t nNow = GetTime();
int64_t start_time = GetTimeMillis();
@@ -2399,26 +2399,20 @@ bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, const CoinEligibil
nValueRet = 0;
if (coin_selection_params.use_bnb) {
- // Get long term estimate
- FeeCalculation feeCalc;
- CCoinControl temp;
- temp.m_confirm_target = 1008;
- CFeeRate long_term_feerate = GetMinimumFeeRate(*this, temp, &feeCalc);
-
// Get the feerate for effective value.
// When subtracting the fee from the outputs, we want the effective feerate to be 0
CFeeRate effective_feerate{0};
if (!coin_selection_params.m_subtract_fee_outputs) {
- effective_feerate = coin_selection_params.effective_fee;
+ effective_feerate = coin_selection_params.m_effective_feerate;
}
- std::vector<OutputGroup> groups = GroupOutputs(coins, !coin_selection_params.m_avoid_partial_spends, effective_feerate, long_term_feerate, eligibility_filter, true /* positive_only */);
+ std::vector<OutputGroup> groups = GroupOutputs(coins, !coin_selection_params.m_avoid_partial_spends, effective_feerate, coin_selection_params.m_long_term_feerate, eligibility_filter, true /* positive_only */);
// Calculate cost of change
- CAmount cost_of_change = GetDiscardRate(*this).GetFee(coin_selection_params.change_spend_size) + coin_selection_params.effective_fee.GetFee(coin_selection_params.change_output_size);
+ CAmount cost_of_change = coin_selection_params.m_discard_feerate.GetFee(coin_selection_params.change_spend_size) + coin_selection_params.m_effective_feerate.GetFee(coin_selection_params.change_output_size);
// Calculate the fees for things that aren't inputs
- CAmount not_input_fees = coin_selection_params.effective_fee.GetFee(coin_selection_params.tx_noinputs_size);
+ CAmount not_input_fees = coin_selection_params.m_effective_feerate.GetFee(coin_selection_params.tx_noinputs_size);
bnb_used = true;
return SelectCoinsBnB(groups, nTargetValue, cost_of_change, setCoinsRet, nValueRet, not_input_fees);
} else {
@@ -2472,7 +2466,7 @@ bool CWallet::SelectCoins(const std::vector<COutput>& vAvailableCoins, const CAm
if (coin.m_input_bytes <= 0) {
return false; // Not solvable, can't estimate size for fee
}
- coin.effective_value = coin.txout.nValue - coin_selection_params.effective_fee.GetFee(coin.m_input_bytes);
+ coin.effective_value = coin.txout.nValue - coin_selection_params.m_effective_feerate.GetFee(coin.m_input_bytes);
if (coin_selection_params.use_bnb) {
value_to_select -= coin.effective_value;
} else {
@@ -2733,7 +2727,7 @@ static uint32_t GetLocktimeForNewTransaction(interfaces::Chain& chain, const uin
return locktime;
}
-OutputType CWallet::TransactionChangeType(const Optional<OutputType>& change_type, const std::vector<CRecipient>& vecSend) const
+OutputType CWallet::TransactionChangeType(const std::optional<OutputType>& change_type, const std::vector<CRecipient>& vecSend) const
{
// If -changetype is specified, always use that change type.
if (change_type) {
@@ -2840,17 +2834,28 @@ bool CWallet::CreateTransactionInternal(
CTxOut change_prototype_txout(0, scriptChange);
coin_selection_params.change_output_size = GetSerializeSize(change_prototype_txout);
- CFeeRate discard_rate = GetDiscardRate(*this);
+ // Set discard feerate
+ coin_selection_params.m_discard_feerate = GetDiscardRate(*this);
// Get the fee rate to use effective values in coin selection
- CFeeRate nFeeRateNeeded = GetMinimumFeeRate(*this, coin_control, &feeCalc);
+ coin_selection_params.m_effective_feerate = GetMinimumFeeRate(*this, coin_control, &feeCalc);
// Do not, ever, assume that it's fine to change the fee rate if the user has explicitly
// provided one
- if (coin_control.m_feerate && nFeeRateNeeded > *coin_control.m_feerate) {
- error = strprintf(_("Fee rate (%s) is lower than the minimum fee rate setting (%s)"), coin_control.m_feerate->ToString(FeeEstimateMode::SAT_VB), nFeeRateNeeded.ToString(FeeEstimateMode::SAT_VB));
+ if (coin_control.m_feerate && coin_selection_params.m_effective_feerate > *coin_control.m_feerate) {
+ error = strprintf(_("Fee rate (%s) is lower than the minimum fee rate setting (%s)"), coin_control.m_feerate->ToString(FeeEstimateMode::SAT_VB), coin_selection_params.m_effective_feerate.ToString(FeeEstimateMode::SAT_VB));
+ return false;
+ }
+ if (feeCalc.reason == FeeReason::FALLBACK && !m_allow_fallback_fee) {
+ // eventually allow a fallback fee
+ error = _("Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.");
return false;
}
+ // Get long term estimate
+ CCoinControl cc_temp;
+ cc_temp.m_confirm_target = chain().estimateMaxBlocks();
+ coin_selection_params.m_long_term_feerate = GetMinimumFeeRate(*this, cc_temp, nullptr);
+
nFeeRet = 0;
bool pick_new_inputs = true;
CAmount nValueIn = 0;
@@ -2924,7 +2929,6 @@ bool CWallet::CreateTransactionInternal(
} else {
coin_selection_params.change_spend_size = (size_t)change_spend_size;
}
- coin_selection_params.effective_fee = nFeeRateNeeded;
if (!SelectCoins(vAvailableCoins, nValueToSelect, setCoins, nValueIn, coin_control, coin_selection_params, bnb_used))
{
// If BnB was used, it was the first pass. No longer the first pass and continue loop with knapsack.
@@ -2950,7 +2954,7 @@ bool CWallet::CreateTransactionInternal(
// Never create dust outputs; if we would, just
// add the dust to the fee.
// The nChange when BnB is used is always going to go to fees.
- if (IsDust(newTxOut, discard_rate) || bnb_used)
+ if (IsDust(newTxOut, coin_selection_params.m_discard_feerate) || bnb_used)
{
nChangePosInOut = -1;
nFeeRet += nChange;
@@ -2988,13 +2992,7 @@ bool CWallet::CreateTransactionInternal(
return false;
}
- nFeeNeeded = GetMinimumFee(*this, nBytes, coin_control, &feeCalc);
- if (feeCalc.reason == FeeReason::FALLBACK && !m_allow_fallback_fee) {
- // eventually allow a fallback fee
- error = _("Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.");
- return false;
- }
-
+ nFeeNeeded = coin_selection_params.m_effective_feerate.GetFee(nBytes);
if (nFeeRet >= nFeeNeeded) {
// Reduce fee to only the needed amount if possible. This
// prevents potential overpayment in fees if the coins
@@ -3008,8 +3006,8 @@ bool CWallet::CreateTransactionInternal(
// change output. Only try this once.
if (nChangePosInOut == -1 && nSubtractFeeFromAmount == 0 && pick_new_inputs) {
unsigned int tx_size_with_change = nBytes + coin_selection_params.change_output_size + 2; // Add 2 as a buffer in case increasing # of outputs changes compact size
- CAmount fee_needed_with_change = GetMinimumFee(*this, tx_size_with_change, coin_control, nullptr);
- CAmount minimum_value_for_change = GetDustThreshold(change_prototype_txout, discard_rate);
+ CAmount fee_needed_with_change = coin_selection_params.m_effective_feerate.GetFee(tx_size_with_change);
+ CAmount minimum_value_for_change = GetDustThreshold(change_prototype_txout, coin_selection_params.m_discard_feerate);
if (nFeeRet >= fee_needed_with_change + minimum_value_for_change) {
pick_new_inputs = false;
nFeeRet = fee_needed_with_change;
@@ -4075,13 +4073,13 @@ std::shared_ptr<CWallet> CWallet::Create(interfaces::Chain& chain, const std::st
WalletBatch batch(walletInstance->GetDatabase());
CBlockLocator locator;
if (batch.ReadBestBlock(locator)) {
- if (const Optional<int> fork_height = chain.findLocatorFork(locator)) {
+ if (const std::optional<int> fork_height = chain.findLocatorFork(locator)) {
rescan_height = *fork_height;
}
}
}
- const Optional<int> tip_height = chain.getHeight();
+ const std::optional<int> tip_height = chain.getHeight();
if (tip_height) {
walletInstance->m_last_block_processed = chain.getBlockHash(*tip_height);
walletInstance->m_last_block_processed_height = *tip_height;
@@ -4115,7 +4113,7 @@ std::shared_ptr<CWallet> CWallet::Create(interfaces::Chain& chain, const std::st
// No need to read and scan block if block was created before
// our wallet birthday (as adjusted for block time variability)
- Optional<int64_t> time_first_key;
+ std::optional<int64_t> time_first_key;
for (auto spk_man : walletInstance->GetAllScriptPubKeyMans()) {
int64_t time = spk_man->GetTimeFirstKey();
if (!time_first_key || time < *time_first_key) time_first_key = time;
diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h
index 3a76163dd2..6031d36b97 100644
--- a/src/wallet/wallet.h
+++ b/src/wallet/wallet.h
@@ -30,6 +30,7 @@
#include <atomic>
#include <map>
#include <memory>
+#include <optional>
#include <set>
#include <stdexcept>
#include <stdint.h>
@@ -51,12 +52,12 @@ struct bilingual_str;
void UnloadWallet(std::shared_ptr<CWallet>&& wallet);
bool AddWallet(const std::shared_ptr<CWallet>& wallet);
-bool RemoveWallet(const std::shared_ptr<CWallet>& wallet, Optional<bool> load_on_start, std::vector<bilingual_str>& warnings);
-bool RemoveWallet(const std::shared_ptr<CWallet>& wallet, Optional<bool> load_on_start);
+bool RemoveWallet(const std::shared_ptr<CWallet>& wallet, std::optional<bool> load_on_start, std::vector<bilingual_str>& warnings);
+bool RemoveWallet(const std::shared_ptr<CWallet>& wallet, std::optional<bool> load_on_start);
std::vector<std::shared_ptr<CWallet>> GetWallets();
std::shared_ptr<CWallet> GetWallet(const std::string& name);
-std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const std::string& name, Optional<bool> load_on_start, const DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error, std::vector<bilingual_str>& warnings);
-std::shared_ptr<CWallet> CreateWallet(interfaces::Chain& chain, const std::string& name, Optional<bool> load_on_start, DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error, std::vector<bilingual_str>& warnings);
+std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const std::string& name, std::optional<bool> load_on_start, const DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error, std::vector<bilingual_str>& warnings);
+std::shared_ptr<CWallet> CreateWallet(interfaces::Chain& chain, const std::string& name, std::optional<bool> load_on_start, DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error, std::vector<bilingual_str>& warnings);
std::unique_ptr<interfaces::Handler> HandleLoadWallet(LoadWalletFn load_wallet);
std::unique_ptr<WalletDatabase> MakeWalletDatabase(const std::string& name, const DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error);
@@ -608,17 +609,22 @@ struct CoinSelectionParams
bool use_bnb = true;
size_t change_output_size = 0;
size_t change_spend_size = 0;
- CFeeRate effective_fee = CFeeRate(0);
+ CFeeRate m_effective_feerate;
+ CFeeRate m_long_term_feerate;
+ CFeeRate m_discard_feerate;
size_t tx_noinputs_size = 0;
//! Indicate that we are subtracting the fee from outputs
bool m_subtract_fee_outputs = false;
bool m_avoid_partial_spends = false;
- CoinSelectionParams(bool use_bnb, size_t change_output_size, size_t change_spend_size, CFeeRate effective_fee, size_t tx_noinputs_size, bool avoid_partial) :
+ CoinSelectionParams(bool use_bnb, size_t change_output_size, size_t change_spend_size, CFeeRate effective_feerate,
+ CFeeRate long_term_feerate, CFeeRate discard_feerate, size_t tx_noinputs_size, bool avoid_partial) :
use_bnb(use_bnb),
change_output_size(change_output_size),
change_spend_size(change_spend_size),
- effective_fee(effective_fee),
+ m_effective_feerate(effective_feerate),
+ m_long_term_feerate(long_term_feerate),
+ m_discard_feerate(discard_feerate),
tx_noinputs_size(tx_noinputs_size),
m_avoid_partial_spends(avoid_partial)
{}
@@ -923,7 +929,7 @@ public:
//! Unset if no blocks were scanned due to read errors or the chain
//! being empty.
uint256 last_scanned_block;
- Optional<int> last_scanned_height;
+ std::optional<int> last_scanned_height;
//! Height of the most recent block that could not be scanned due to
//! read errors or pruning. Will be set if status is FAILURE, unset if
@@ -931,7 +937,7 @@ public:
//! USER_ABORT.
uint256 last_failed_block;
};
- ScanResult ScanForWalletTransactions(const uint256& start_block, int start_height, Optional<int> max_height, const WalletRescanReserver& reserver, bool fUpdate);
+ ScanResult ScanForWalletTransactions(const uint256& start_block, int start_height, std::optional<int> max_height, const WalletRescanReserver& reserver, bool fUpdate);
void transactionRemovedFromMempool(const CTransactionRef& tx, MemPoolRemovalReason reason, uint64_t mempool_sequence) override;
void ReacceptWalletTransactions() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
void ResendWalletTransactions();
@@ -946,7 +952,7 @@ public:
Balance GetBalance(int min_depth = 0, bool avoid_reuse = true) const;
CAmount GetAvailableBalance(const CCoinControl* coinControl = nullptr) const;
- OutputType TransactionChangeType(const Optional<OutputType>& change_type, const std::vector<CRecipient>& vecSend) const;
+ OutputType TransactionChangeType(const std::optional<OutputType>& change_type, const std::vector<CRecipient>& vecSend) const;
/**
* Insert additional inputs into the transaction by
@@ -1031,7 +1037,7 @@ public:
* (see -changetype option documentation and implementation in
* CWallet::TransactionChangeType for details).
*/
- Optional<OutputType> m_default_change_type{};
+ std::optional<OutputType> m_default_change_type{};
/** Absolute maximum transaction fee (in satoshis) used by default for the wallet */
CAmount m_default_max_tx_fee{DEFAULT_TRANSACTION_MAXFEE};
diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp
index a5a454f9a8..3d9248009f 100644
--- a/src/wallet/walletdb.cpp
+++ b/src/wallet/walletdb.cpp
@@ -23,6 +23,7 @@
#include <wallet/wallet.h>
#include <atomic>
+#include <optional>
#include <string>
namespace DBKeys {
@@ -1015,7 +1016,7 @@ std::unique_ptr<WalletDatabase> MakeDatabase(const fs::path& path, const Databas
return nullptr;
}
- Optional<DatabaseFormat> format;
+ std::optional<DatabaseFormat> format;
if (exists) {
if (IsBDBFile(BDBDataFile(path))) {
format = DatabaseFormat::BERKELEY;
diff --git a/test/functional/rpc_fundrawtransaction.py b/test/functional/rpc_fundrawtransaction.py
index 6b300e7231..8c9755cc8c 100755
--- a/test/functional/rpc_fundrawtransaction.py
+++ b/test/functional/rpc_fundrawtransaction.py
@@ -32,6 +32,7 @@ class RawTransactionsTest(BitcoinTestFramework):
# This test isn't testing tx relay. Set whitelist on the peers for
# instant tx relay.
self.extra_args = [['-whitelist=noban@127.0.0.1']] * self.num_nodes
+ self.rpc_timeout = 90 # to prevent timeouts in `test_transaction_too_large`
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
@@ -910,22 +911,23 @@ class RawTransactionsTest(BitcoinTestFramework):
def test_transaction_too_large(self):
self.log.info("Test fundrawtx where BnB solution would result in a too large transaction, but Knapsack would not")
-
self.nodes[0].createwallet("large")
wallet = self.nodes[0].get_wallet_rpc(self.default_wallet_name)
recipient = self.nodes[0].get_wallet_rpc("large")
outputs = {}
rawtx = recipient.createrawtransaction([], {wallet.getnewaddress(): 147.99899260})
- # Make 1500 0.1 BTC outputs
- # The amount that we target for funding is in the BnB range when these outputs are used.
- # However if these outputs are selected, the transaction will end up being too large, so it shouldn't use BnB and instead fallback to Knapsack
- # but that behavior is not implemented yet. For now we just check that we get an error.
- for i in range(0, 1500):
+ # Make 1500 0.1 BTC outputs. The amount that we target for funding is in
+ # the BnB range when these outputs are used. However if these outputs
+ # are selected, the transaction will end up being too large, so it
+ # shouldn't use BnB and instead fall back to Knapsack but that behavior
+ # is not implemented yet. For now we just check that we get an error.
+ for _ in range(1500):
outputs[recipient.getnewaddress()] = 0.1
wallet.sendmany("", outputs)
self.nodes[0].generate(10)
assert_raises_rpc_error(-4, "Transaction too large", recipient.fundrawtransaction, rawtx)
+
if __name__ == '__main__':
RawTransactionsTest().main()