diff --git a/ci/lint/04_install.sh b/ci/lint/04_install.sh
index 8113500fb2..b160406392 100755
--- a/ci/lint/04_install.sh
+++ b/ci/lint/04_install.sh
@@ -18,7 +18,7 @@ ${CI_RETRY_EXE} apt-get install -y curl xz-utils git gpg
PYTHON_PATH="/python_build"
if [ ! -d "${PYTHON_PATH}/bin" ]; then
(
- git clone https://github.com/pyenv/pyenv.git
+ ${CI_RETRY_EXE} git clone https://github.com/pyenv/pyenv.git
cd pyenv/plugins/python-build || exit 1
./install.sh
)
diff --git a/ci/test/01_base_install.sh b/ci/test/01_base_install.sh
index 68b701f3ca..a0b054ab40 100755
--- a/ci/test/01_base_install.sh
+++ b/ci/test/01_base_install.sh
@@ -31,14 +31,8 @@ elif [ "$CI_OS_NAME" != "macos" ]; then
fi
if [ -n "$PIP_PACKAGES" ]; then
- if [ "$CI_OS_NAME" == "macos" ]; then
- sudo -H pip3 install --upgrade pip
- # shellcheck disable=SC2086
- IN_GETOPT_BIN="$(brew --prefix gnu-getopt)/bin/getopt" ${CI_RETRY_EXE} pip3 install --user $PIP_PACKAGES
- else
- # shellcheck disable=SC2086
- ${CI_RETRY_EXE} pip3 install --user $PIP_PACKAGES
- fi
+ # shellcheck disable=SC2086
+ ${CI_RETRY_EXE} pip3 install --user $PIP_PACKAGES
fi
if [[ ${USE_MEMORY_SANITIZER} == "true" ]]; then
diff --git a/ci/test/02_run_container.sh b/ci/test/02_run_container.sh
index a74226b089..c8c54267e7 100755
--- a/ci/test/02_run_container.sh
+++ b/ci/test/02_run_container.sh
@@ -61,6 +61,11 @@ else
mkdir -p "${PREVIOUS_RELEASES_DIR}"
fi
+if [ "$CI_OS_NAME" == "macos" ]; then
+ IN_GETOPT_BIN="$(brew --prefix gnu-getopt)/bin/getopt"
+ export IN_GETOPT_BIN
+fi
+
CI_EXEC () {
$CI_EXEC_CMD_PREFIX bash -c "export PATH=${BINS_SCRATCH_DIR}:${BASE_ROOT_DIR}/ci/retry:\$PATH && cd \"${BASE_ROOT_DIR}\" && $*"
}
diff --git a/ci/test/06_script_b.sh b/ci/test/06_script_b.sh
index 4d5f31b956..20464c3aea 100755
--- a/ci/test/06_script_b.sh
+++ b/ci/test/06_script_b.sh
@@ -56,7 +56,7 @@ index 65e31724bc..f61b471953 100644
if [ "$RUN_FUZZ_TESTS" = "true" ]; then
export DIR_FUZZ_IN=${DIR_QA_ASSETS}/fuzz_seed_corpus/
if [ ! -d "$DIR_FUZZ_IN" ]; then
- git clone --depth=1 https://github.com/bitcoin-core/qa-assets "${DIR_QA_ASSETS}"
+ ${CI_RETRY_EXE} git clone --depth=1 https://github.com/bitcoin-core/qa-assets "${DIR_QA_ASSETS}"
fi
(
cd "${DIR_QA_ASSETS}"
diff --git a/configure.ac b/configure.ac
index 60acb4883d..2f81d7b2aa 100644
--- a/configure.ac
+++ b/configure.ac
@@ -471,6 +471,12 @@ fi
dnl Don't allow extended (non-ASCII) symbols in identifiers. This is easier for code review.
AX_CHECK_COMPILE_FLAG([-fno-extended-identifiers], [CORE_CXXFLAGS="$CORE_CXXFLAGS -fno-extended-identifiers"], [], [$CXXFLAG_WERROR])
+dnl Currently all versions of gcc are subject to a class of bugs, see the
+dnl gccbug_90348 test case (only reproduces on GCC 11 and earlier) and
+dnl https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111843. To work around that, set
+dnl -fstack-reuse=none for all gcc builds. (Only gcc understands this flag)
+AX_CHECK_COMPILE_FLAG([-fstack-reuse=none], [CORE_CXXFLAGS="$CORE_CXXFLAGS -fstack-reuse=none"])
+
enable_arm_crc=no
enable_arm_shani=no
enable_sse42=no
@@ -941,11 +947,6 @@ if test "$TARGET_OS" != "windows"; then
AX_CHECK_COMPILE_FLAG([-fPIC], [PIC_FLAGS="-fPIC"])
fi
-dnl Currently all versions of gcc are subject to a class of bugs, see the
-dnl gccbug_90348 test case (only reproduces on GCC 11 and earlier) and the related bugs of
-dnl https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90348. To work around that, set
-dnl -fstack-reuse=none for all gcc builds. (Only gcc understands this flag)
-AX_CHECK_COMPILE_FLAG([-fstack-reuse=none], [HARDENED_CXXFLAGS="$HARDENED_CXXFLAGS -fstack-reuse=none"])
if test "$use_hardening" != "no"; then
use_hardening=yes
AX_CHECK_COMPILE_FLAG([-Wstack-protector], [HARDENED_CXXFLAGS="$HARDENED_CXXFLAGS -Wstack-protector"])
diff --git a/contrib/devtools/symbol-check.py b/contrib/devtools/symbol-check.py
index c5f0a761f1..a3d00bec95 100755
--- a/contrib/devtools/symbol-check.py
+++ b/contrib/devtools/symbol-check.py
@@ -240,6 +240,11 @@ def check_MACHO_sdk(binary) -> bool:
return True
return False
+def check_MACHO_ld64(binary) -> bool:
+ if binary.build_version.tools[0].version == [711, 0, 0]:
+ return True
+ return False
+
def check_PE_libraries(binary) -> bool:
ok: bool = True
for dylib in binary.libraries:
@@ -278,6 +283,7 @@ def check_ELF_ABI(binary) -> bool:
('DYNAMIC_LIBRARIES', check_MACHO_libraries),
('MIN_OS', check_MACHO_min_os),
('SDK', check_MACHO_sdk),
+ ('LD64', check_MACHO_ld64),
],
lief.EXE_FORMATS.PE: [
('DYNAMIC_LIBRARIES', check_PE_libraries),
diff --git a/contrib/devtools/test_utxo_snapshots.sh b/contrib/devtools/test_utxo_snapshots.sh
index f5918d7738..93a4cd1683 100755
--- a/contrib/devtools/test_utxo_snapshots.sh
+++ b/contrib/devtools/test_utxo_snapshots.sh
@@ -11,13 +11,16 @@
# loaded. We see the background validation chainstate removed after validation
# completes.
#
+# The shellcheck rule SC2086 (quoted variables) disablements are necessary
+# since this rule needs to be violated in order to get bitcoind to pick up on
+# $EARLY_IBD_FLAGS for the script to work.
export LC_ALL=C
set -e
BASE_HEIGHT=${1:-30000}
INCREMENTAL_HEIGHT=20000
-FINAL_HEIGHT=$(($BASE_HEIGHT + $INCREMENTAL_HEIGHT))
+FINAL_HEIGHT=$((BASE_HEIGHT + INCREMENTAL_HEIGHT))
SERVER_DATADIR="$(pwd)/utxodemo-data-server-$BASE_HEIGHT"
CLIENT_DATADIR="$(pwd)/utxodemo-data-client-$BASE_HEIGHT"
@@ -107,12 +110,14 @@ read -p "Press [enter] to continue" _
echo
echo "-- IBDing the blocks (height=$BASE_HEIGHT) required to the server node..."
+# shellcheck disable=SC2086
./src/bitcoind -logthreadnames=1 $SERVER_PORTS \
-datadir="$SERVER_DATADIR" $EARLY_IBD_FLAGS -stopatheight="$BASE_HEIGHT" >/dev/null
echo
echo "-- Creating snapshot at ~ height $BASE_HEIGHT ($UTXO_DAT_FILE)..."
server_sleep_til_shutdown # wait for stopatheight to be hit
+# shellcheck disable=SC2086
./src/bitcoind -logthreadnames=1 $SERVER_PORTS \
-datadir="$SERVER_DATADIR" $EARLY_IBD_FLAGS -connect=0 -listen=0 >/dev/null &
SERVER_PID="$!"
@@ -137,11 +142,13 @@ echo " {${RPC_BASE_HEIGHT}, AssumeutxoHash{uint256S(\"0x${RPC_AU}\")}, ${RPC_N
echo
echo
echo "-- IBDing more blocks to the server node (height=$FINAL_HEIGHT) so there is a diff between snapshot and tip..."
+# shellcheck disable=SC2086
./src/bitcoind $SERVER_PORTS -logthreadnames=1 -datadir="$SERVER_DATADIR" \
$EARLY_IBD_FLAGS -stopatheight="$FINAL_HEIGHT" >/dev/null
echo
echo "-- Starting the server node to provide blocks to the client node..."
+# shellcheck disable=SC2086
./src/bitcoind $SERVER_PORTS -logthreadnames=1 -debug=net -datadir="$SERVER_DATADIR" \
$EARLY_IBD_FLAGS -connect=0 -listen=1 >/dev/null &
SERVER_PID="$!"
@@ -165,6 +172,7 @@ read -p "When you're ready for all this, hit [enter]" _
echo
echo "-- Starting the client node to get headers from the server, then load the snapshot..."
+# shellcheck disable=SC2086
./src/bitcoind $CLIENT_PORTS $ALL_INDEXES -logthreadnames=1 -datadir="$CLIENT_DATADIR" \
-connect=0 -addnode=127.0.0.1:$SERVER_PORT -debug=net $EARLY_IBD_FLAGS >/dev/null &
CLIENT_PID="$!"
@@ -189,6 +197,7 @@ echo
read -p "Press [enter] to continue"
client_sleep_til_boot
+# shellcheck disable=SC2086
./src/bitcoind $CLIENT_PORTS $ALL_INDEXES -logthreadnames=1 -datadir="$CLIENT_DATADIR" -connect=0 \
-addnode=127.0.0.1:$SERVER_PORT "$EARLY_IBD_FLAGS" >/dev/null &
CLIENT_PID="$!"
diff --git a/depends/hosts/darwin.mk b/depends/hosts/darwin.mk
index fa6d6d4b8b..ecd45540cf 100644
--- a/depends/hosts/darwin.mk
+++ b/depends/hosts/darwin.mk
@@ -2,7 +2,7 @@ OSX_MIN_VERSION=11.0
OSX_SDK_VERSION=11.0
XCODE_VERSION=12.2
XCODE_BUILD_ID=12B45b
-LD64_VERSION=609
+LD64_VERSION=711
OSX_SDK=$(SDK_PATH)/Xcode-$(XCODE_VERSION)-$(XCODE_BUILD_ID)-extracted-SDK-with-libcxx-headers
diff --git a/doc/developer-notes.md b/doc/developer-notes.md
index 3c3f612053..322fa987ae 100644
--- a/doc/developer-notes.md
+++ b/doc/developer-notes.md
@@ -488,7 +488,9 @@ To enable LCOV report generation during test runs:
make
make cov
-# A coverage report will now be accessible at `./test_bitcoin.coverage/index.html`.
+# A coverage report will now be accessible at `./test_bitcoin.coverage/index.html`,
+# which covers unit tests, and `./total.coverage/index.html`, which covers
+# unit and functional tests.
```
### Performance profiling with perf
diff --git a/doc/release-notes-123.md b/doc/release-notes-123.md
new file mode 100644
index 0000000000..fffd211f37
--- /dev/null
+++ b/doc/release-notes-123.md
@@ -0,0 +1,5 @@
+Tools and Utilities
+---
+
+- A new `bitcoinconsensus_verify_script_with_spent_outputs` function is available in libconsensus which optionally accepts the spent outputs of the transaction being verified.
+- A new `bitcoinconsensus_SCRIPT_FLAGS_VERIFY_TAPROOT` flag is available in libconsensus that will verify scripts with the Taproot spending rules.
\ No newline at end of file
diff --git a/doc/release-notes-27460.md b/doc/release-notes-27460.md
new file mode 100644
index 0000000000..d663ec0baf
--- /dev/null
+++ b/doc/release-notes-27460.md
@@ -0,0 +1,7 @@
+- A new `importmempool` RPC has been added. It loads a valid `mempool.dat` file and attempts to
+ add its contents to the mempool. This can be useful to import mempool data from another node
+ without having to modify the datadir contents and without having to restart the node. (#27460)
+ - Warning: Importing untrusted files is dangerous, especially if metadata from the file is taken over.
+ - If you want to apply fee deltas, it is recommended to use the `getprioritisedtransactions` and
+ `prioritisetransaction` RPCs instead of the `apply_fee_delta_priority` option to avoid
+ double-prioritising any already-prioritised transactions in the mempool.
diff --git a/doc/release-notes/release-notes-25.1.md b/doc/release-notes/release-notes-25.1.md
new file mode 100644
index 0000000000..bfdbee4e76
--- /dev/null
+++ b/doc/release-notes/release-notes-25.1.md
@@ -0,0 +1,108 @@
+25.1 Release Notes
+==================
+
+Bitcoin Core version 25.1 is now available from:
+
+
+
+This release includes various bug fixes and performance
+improvements, as well as updated translations.
+
+Please report bugs using the issue tracker at GitHub:
+
+
+
+To receive security and update notifications, please subscribe to:
+
+
+
+How to Upgrade
+==============
+
+If you are running an older version, shut it down. Wait until it has completely
+shut down (which might take a few minutes in some cases), then run the
+installer (on Windows) or just copy over `/Applications/Bitcoin-Qt` (on macOS)
+or `bitcoind`/`bitcoin-qt` (on Linux).
+
+Upgrading directly from a version of Bitcoin Core that has reached its EOL is
+possible, but it might take some time if the data directory needs to be migrated. Old
+wallet versions of Bitcoin Core are generally supported.
+
+Compatibility
+==============
+
+Bitcoin Core is supported and extensively tested on operating systems
+using the Linux kernel, macOS 10.15+, and Windows 7 and newer. Bitcoin
+Core should also work on most other Unix-like systems but is not as
+frequently tested on them. It is not recommended to use Bitcoin Core on
+unsupported systems.
+
+Notable changes
+===============
+
+### P2P
+
+- #27626 Parallel compact block downloads, take 3
+- #27743 p2p: Unconditionally return when compact block status == READ_STATUS_FAILED
+
+### Fees
+
+- #27622 Fee estimation: avoid serving stale fee estimate
+
+### RPC
+
+- #27727 rpc: Fix invalid bech32 address handling
+
+### Rest
+
+- #27853 rest: fix crash error when calling /deploymentinfo
+- #28551 http: bugfix: allow server shutdown in case of remote client disconnection
+
+### Wallet
+
+- #28038 wallet: address book migration bug fixes
+- #28067 descriptors: do not return top-level only funcs as sub descriptors
+- #28125 wallet: bugfix, disallow migration of invalid scripts
+- #28542 wallet: Check for uninitialized last processed and conflicting heights in MarkConflicted
+
+### Build
+
+- #27724 build: disable boost multi index safe mode in debug mode
+- #28097 depends: xcb-proto 1.15.2
+- #28543 build, macos: Fix qt package build with new Xcode 15 linker
+- #28571 depends: fix unusable memory_resource in macos qt build
+
+### Gui
+
+- gui#751 macOS, do not process actions during shutdown
+
+### Miscellaneous
+
+- #28452 Do not use std::vector = {} to release memory
+
+### CI
+
+- #27777 ci: Prune dangling images on RESTART_CI_DOCKER_BEFORE_RUN
+- #27834 ci: Nuke Android APK task, Use credits for tsan
+- #27844 ci: Use podman stop over podman kill
+- #27886 ci: Switch to amd64 container in "ARM" task
+
+Credits
+=======
+
+Thanks to everyone who directly contributed to this release:
+
+- Abubakar Sadiq Ismail
+- Andrew Chow
+- Bruno Garcia
+- Gregory Sanders
+- Hennadii Stepanov
+- MacroFake
+- Matias Furszyfer
+- Michael Ford
+- Pieter Wuille
+- stickies-v
+- Will Clark
+
+As well as to everyone that helped with translations on
+[Transifex](https://www.transifex.com/bitcoin/bitcoin/).
\ No newline at end of file
diff --git a/doc/release-notes/release-notes-27511.md b/doc/release-notes/release-notes-27511.md
new file mode 100644
index 0000000000..b5c0847e31
--- /dev/null
+++ b/doc/release-notes/release-notes-27511.md
@@ -0,0 +1,6 @@
+New RPCs
+--------
+
+- A new RPC `getaddrmaninfo` has been added to view the distribution of addresses in the new and tried table of the
+ node's address manager across different networks(ipv4, ipv6, onion, i2p, cjdns). The RPC returns count of addresses
+ in new and tried table as well as their sum for all networks. (#27511)
diff --git a/doc/shared-libraries.md b/doc/shared-libraries.md
index 147e223711..07aee46f0b 100644
--- a/doc/shared-libraries.md
+++ b/doc/shared-libraries.md
@@ -11,13 +11,14 @@ The interface is defined in the C header `bitcoinconsensus.h` located in `src/sc
#### Version
-`bitcoinconsensus_version` returns an `unsigned int` with the API version *(currently `1`)*.
+`bitcoinconsensus_version` returns an `unsigned int` with the API version *(currently `2`)*.
#### Script Validation
-`bitcoinconsensus_verify_script` returns an `int` with the status of the verification. It will be `1` if the input script correctly spends the previous output `scriptPubKey`.
+`bitcoinconsensus_verify_script`, `bitcoinconsensus_verify_script_with_amount` and `bitcoinconsensus_verify_script_with_spent_outputs` return an `int` with the status of the verification. It will be `1` if the input script correctly spends the previous output `scriptPubKey`.
##### Parameters
+###### bitcoinconsensus_verify_script
- `const unsigned char *scriptPubKey` - The previous output script that encumbers spending.
- `unsigned int scriptPubKeyLen` - The number of bytes for the `scriptPubKey`.
- `const unsigned char *txTo` - The transaction with the input that is spending the previous output.
@@ -26,6 +27,28 @@ The interface is defined in the C header `bitcoinconsensus.h` located in `src/sc
- `unsigned int flags` - The script validation flags *(see below)*.
- `bitcoinconsensus_error* err` - Will have the error/success code for the operation *(see below)*.
+###### bitcoinconsensus_verify_script_with_amount
+- `const unsigned char *scriptPubKey` - The previous output script that encumbers spending.
+- `unsigned int scriptPubKeyLen` - The number of bytes for the `scriptPubKey`.
+- `int64_t amount` - The amount spent in the input
+- `const unsigned char *txTo` - The transaction with the input that is spending the previous output.
+- `unsigned int txToLen` - The number of bytes for the `txTo`.
+- `unsigned int nIn` - The index of the input in `txTo` that spends the `scriptPubKey`.
+- `unsigned int flags` - The script validation flags *(see below)*.
+- `bitcoinconsensus_error* err` - Will have the error/success code for the operation *(see below)*.
+
+###### bitcoinconsensus_verify_script_with_spent_outputs
+- `const unsigned char *scriptPubKey` - The previous output script that encumbers spending.
+- `unsigned int scriptPubKeyLen` - The number of bytes for the `scriptPubKey`.
+- `int64_t amount` - The amount spent in the input
+- `const unsigned char *txTo` - The transaction with the input that is spending the previous output.
+- `unsigned int txToLen` - The number of bytes for the `txTo`.
+- `UTXO *spentOutputs` - Previous outputs spent in the transaction. `UTXO` is a struct composed by `const unsigned char *scriptPubKey`, `unsigned int scriptPubKeySize` (the number of bytes for the `scriptPubKey`) and `unsigned int value`.
+- `unsigned int spentOutputsLen` - The number of bytes for the `spentOutputs`.
+- `unsigned int nIn` - The index of the input in `txTo` that spends the `scriptPubKey`.
+- `unsigned int flags` - The script validation flags *(see below)*.
+- `bitcoinconsensus_error* err` - Will have the error/success code for the operation *(see below)*.
+
##### Script Flags
- `bitcoinconsensus_SCRIPT_FLAGS_VERIFY_NONE`
- `bitcoinconsensus_SCRIPT_FLAGS_VERIFY_P2SH` - Evaluate P2SH ([BIP16](https://github.com/bitcoin/bips/blob/master/bip-0016.mediawiki)) subscripts
@@ -34,6 +57,7 @@ The interface is defined in the C header `bitcoinconsensus.h` located in `src/sc
- `bitcoinconsensus_SCRIPT_FLAGS_VERIFY_CHECKLOCKTIMEVERIFY` - Enable CHECKLOCKTIMEVERIFY ([BIP65](https://github.com/bitcoin/bips/blob/master/bip-0065.mediawiki))
- `bitcoinconsensus_SCRIPT_FLAGS_VERIFY_CHECKSEQUENCEVERIFY` - Enable CHECKSEQUENCEVERIFY ([BIP112](https://github.com/bitcoin/bips/blob/master/bip-0112.mediawiki))
- `bitcoinconsensus_SCRIPT_FLAGS_VERIFY_WITNESS` - Enable WITNESS ([BIP141](https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki))
+- `bitcoinconsensus_SCRIPT_FLAGS_VERIFY_TAPROOT` - Enable TAPROOT ([BIP340](https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki), [BIP341](https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki), [BIP342](https://github.com/bitcoin/bips/blob/master/bip-0342.mediawiki))
##### Errors
- `bitcoinconsensus_ERR_OK` - No errors with input parameters *(see the return value of `bitcoinconsensus_verify_script` for the verification status)*
@@ -42,9 +66,12 @@ The interface is defined in the C header `bitcoinconsensus.h` located in `src/sc
- `bitcoinconsensus_ERR_DESERIALIZE` - An error deserializing `txTo`
- `bitcoinconsensus_ERR_AMOUNT_REQUIRED` - Input amount is required if WITNESS is used
- `bitcoinconsensus_ERR_INVALID_FLAGS` - Script verification `flags` are invalid (i.e. not part of the libconsensus interface)
+- `bitcoinconsensus_ERR_SPENT_OUTPUTS_REQUIRED` - Spent outputs are required if TAPROOT is used
+- `bitcoinconsensus_ERR_SPENT_OUTPUTS_MISMATCH` - Spent outputs size doesn't match tx inputs size
### Example Implementations
- [NBitcoin](https://github.com/MetacoSA/NBitcoin/blob/5e1055cd7c4186dee4227c344af8892aea54faec/NBitcoin/Script.cs#L979-#L1031) (.NET Bindings)
- [node-libbitcoinconsensus](https://github.com/bitpay/node-libbitcoinconsensus) (Node.js Bindings)
- [java-libbitcoinconsensus](https://github.com/dexX7/java-libbitcoinconsensus) (Java Bindings)
- [bitcoinconsensus-php](https://github.com/Bit-Wasp/bitcoinconsensus-php) (PHP Bindings)
+- [rust-bitcoinconsensus](https://github.com/rust-bitcoin/rust-bitcoinconsensus) (Rust Bindings)
\ No newline at end of file
diff --git a/src/.bear-tidy-config b/src/.bear-tidy-config
index 9b6b9d2cf7..0ab30a8d9d 100644
--- a/src/.bear-tidy-config
+++ b/src/.bear-tidy-config
@@ -8,6 +8,8 @@
"src/crypto/ctaes",
"src/leveldb",
"src/minisketch",
+ "src/bench/nanobench.cpp",
+ "src/bench/nanobench.h",
"src/secp256k1"
]
},
diff --git a/src/.clang-tidy b/src/.clang-tidy
index 9f16553706..0318bd01ce 100644
--- a/src/.clang-tidy
+++ b/src/.clang-tidy
@@ -5,6 +5,7 @@ bugprone-argument-comment,
bugprone-use-after-move,
misc-unused-using-decls,
modernize-use-default-member-init,
+modernize-use-emplace,
modernize-use-noexcept,
modernize-use-nullptr,
performance-*,
diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include
index 5ece8e3162..3d6c34e841 100644
--- a/src/Makefile.qt.include
+++ b/src/Makefile.qt.include
@@ -373,11 +373,14 @@ SECONDARY: $(QT_QM)
$(srcdir)/qt/bitcoinstrings.cpp: FORCE
@test -n $(XGETTEXT) || echo "xgettext is required for updating translations"
- $(AM_V_GEN) cd $(srcdir); XGETTEXT=$(XGETTEXT) COPYRIGHT_HOLDERS="$(COPYRIGHT_HOLDERS)" $(PYTHON) ../share/qt/extract_strings_qt.py $(libbitcoin_node_a_SOURCES) $(libbitcoin_wallet_a_SOURCES) $(libbitcoin_common_a_SOURCES) $(libbitcoin_zmq_a_SOURCES) $(libbitcoin_consensus_a_SOURCES) $(libbitcoin_util_a_SOURCES)
+ $(AM_V_GEN) cd $(srcdir); XGETTEXT=$(XGETTEXT) COPYRIGHT_HOLDERS="$(COPYRIGHT_HOLDERS)" $(PYTHON) ../share/qt/extract_strings_qt.py \
+ $(libbitcoin_node_a_SOURCES) $(libbitcoin_wallet_a_SOURCES) $(libbitcoin_common_a_SOURCES) \
+ $(libbitcoin_zmq_a_SOURCES) $(libbitcoin_consensus_a_SOURCES) $(libbitcoin_util_a_SOURCES) \
+ $(BITCOIN_QT_BASE_CPP) $(BITCOIN_QT_WINDOWS_CPP) $(BITCOIN_QT_WALLET_CPP) $(BITCOIN_QT_H) $(BITCOIN_MM)
# The resulted bitcoin_en.xlf source file should follow Transifex requirements.
# See: https://docs.transifex.com/formats/xliff#how-to-distinguish-between-a-source-file-and-a-translation-file
-translate: $(srcdir)/qt/bitcoinstrings.cpp $(QT_FORMS_UI) $(QT_FORMS_UI) $(BITCOIN_QT_BASE_CPP) qt/bitcoin.cpp $(BITCOIN_QT_WINDOWS_CPP) $(BITCOIN_QT_WALLET_CPP) $(BITCOIN_QT_H) $(BITCOIN_MM)
+translate: $(srcdir)/qt/bitcoinstrings.cpp $(QT_FORMS_UI) $(QT_FORMS_UI) $(BITCOIN_QT_BASE_CPP) $(BITCOIN_QT_WINDOWS_CPP) $(BITCOIN_QT_WALLET_CPP) $(BITCOIN_QT_H) $(BITCOIN_MM)
@test -n $(LUPDATE) || echo "lupdate is required for updating translations"
$(AM_V_GEN) QT_SELECT=$(QT_SELECT) $(LUPDATE) -no-obsolete -I $(srcdir) -locations relative $^ -ts $(srcdir)/qt/locale/bitcoin_en.ts
@test -n $(LCONVERT) || echo "lconvert is required for updating translations"
diff --git a/src/Makefile.test.include b/src/Makefile.test.include
index 289b0b60c1..987863be8a 100644
--- a/src/Makefile.test.include
+++ b/src/Makefile.test.include
@@ -286,7 +286,6 @@ test_fuzz_fuzz_SOURCES = \
test/fuzz/headerssync.cpp \
test/fuzz/hex.cpp \
test/fuzz/http_request.cpp \
- test/fuzz/i2p.cpp \
test/fuzz/integer.cpp \
test/fuzz/key.cpp \
test/fuzz/key_io.cpp \
diff --git a/src/addrman.cpp b/src/addrman.cpp
index 6ce9c81c63..b001365ab3 100644
--- a/src/addrman.cpp
+++ b/src/addrman.cpp
@@ -854,7 +854,7 @@ std::vector> AddrManImpl::GetEntries_(bool
/*multiplicity_in=*/from_tried ? 1 : info.nRefCount,
bucket,
position);
- infos.push_back(std::make_pair(info, location));
+ infos.emplace_back(info, location);
}
}
}
diff --git a/src/bench/block_assemble.cpp b/src/bench/block_assemble.cpp
index 0737144b84..ba8ec16119 100644
--- a/src/bench/block_assemble.cpp
+++ b/src/bench/block_assemble.cpp
@@ -28,7 +28,7 @@ static void AssembleBlock(benchmark::Bench& bench)
std::array txs;
for (size_t b{0}; b < NUM_BLOCKS; ++b) {
CMutableTransaction tx;
- tx.vin.push_back(CTxIn{MineBlock(test_setup->m_node, P2WSH_OP_TRUE)});
+ tx.vin.emplace_back(MineBlock(test_setup->m_node, P2WSH_OP_TRUE));
tx.vin.back().scriptWitness = witness;
tx.vout.emplace_back(1337, P2WSH_OP_TRUE);
if (NUM_BLOCKS - b >= COINBASE_MATURITY)
diff --git a/src/bench/disconnected_transactions.cpp b/src/bench/disconnected_transactions.cpp
index 0a7344b248..264c0aa1e8 100644
--- a/src/bench/disconnected_transactions.cpp
+++ b/src/bench/disconnected_transactions.cpp
@@ -36,8 +36,8 @@ static BlockTxns CreateRandomTransactions(size_t num_txns)
CScript spk = CScript() << OP_TRUE;
for (uint32_t i = 0; i < num_txns; ++i) {
CMutableTransaction tx;
- tx.vin.emplace_back(CTxIn{COutPoint{prevout_hash, 0}});
- tx.vout.emplace_back(CTxOut{CENT, spk});
+ tx.vin.emplace_back(COutPoint{prevout_hash, 0});
+ tx.vout.emplace_back(CENT, spk);
auto ptx{MakeTransactionRef(tx)};
txns.emplace_back(ptx);
prevout_hash = ptx->GetHash();
diff --git a/src/bench/wallet_loading.cpp b/src/bench/wallet_loading.cpp
index 5453238728..b17c7fe05a 100644
--- a/src/bench/wallet_loading.cpp
+++ b/src/bench/wallet_loading.cpp
@@ -20,8 +20,8 @@ namespace wallet{
static void AddTx(CWallet& wallet)
{
CMutableTransaction mtx;
- mtx.vout.push_back({COIN, GetScriptForDestination(*Assert(wallet.GetNewDestination(OutputType::BECH32, "")))});
- mtx.vin.push_back(CTxIn());
+ mtx.vout.emplace_back(COIN, GetScriptForDestination(*Assert(wallet.GetNewDestination(OutputType::BECH32, ""))));
+ mtx.vin.emplace_back();
wallet.AddToWallet(MakeTransactionRef(mtx), TxStateInactive{});
}
diff --git a/src/common/args.cpp b/src/common/args.cpp
index d50c4b4649..4076b3c0af 100644
--- a/src/common/args.cpp
+++ b/src/common/args.cpp
@@ -216,7 +216,7 @@ bool ArgsManager::ParseParameters(int argc, const char* const argv[], std::strin
m_command.push_back(key);
while (++i < argc) {
// The remaining args are command args
- m_command.push_back(argv[i]);
+ m_command.emplace_back(argv[i]);
}
break;
}
diff --git a/src/external_signer.cpp b/src/external_signer.cpp
index 6b1e1f0241..102c58b56a 100644
--- a/src/external_signer.cpp
+++ b/src/external_signer.cpp
@@ -54,7 +54,7 @@ bool ExternalSigner::Enumerate(const std::string& command, std::vector
#include
#include
+#include
#include
#include
#include
@@ -153,27 +154,59 @@ bool Session::Listen(Connection& conn)
bool Session::Accept(Connection& conn)
{
- try {
- while (!*m_interrupt) {
- Sock::Event occurred;
- if (!conn.sock->Wait(MAX_WAIT_FOR_IO, Sock::RECV, &occurred)) {
- throw std::runtime_error("wait on socket failed");
- }
+ AssertLockNotHeld(m_mutex);
- if (occurred == 0) {
- // Timeout, no incoming connections or errors within MAX_WAIT_FOR_IO.
- continue;
- }
+ std::string errmsg;
+ bool disconnect{false};
- const std::string& peer_dest =
- conn.sock->RecvUntilTerminator('\n', MAX_WAIT_FOR_IO, *m_interrupt, MAX_MSG_SIZE);
+ while (!*m_interrupt) {
+ Sock::Event occurred;
+ if (!conn.sock->Wait(MAX_WAIT_FOR_IO, Sock::RECV, &occurred)) {
+ errmsg = "wait on socket failed";
+ break;
+ }
- conn.peer = CService(DestB64ToAddr(peer_dest), I2P_SAM31_PORT);
+ if (occurred == 0) {
+ // Timeout, no incoming connections or errors within MAX_WAIT_FOR_IO.
+ continue;
+ }
- return true;
+ std::string peer_dest;
+ try {
+ peer_dest = conn.sock->RecvUntilTerminator('\n', MAX_WAIT_FOR_IO, *m_interrupt, MAX_MSG_SIZE);
+ } catch (const std::runtime_error& e) {
+ errmsg = e.what();
+ break;
}
- } catch (const std::runtime_error& e) {
- Log("Error accepting: %s", e.what());
+
+ CNetAddr peer_addr;
+ try {
+ peer_addr = DestB64ToAddr(peer_dest);
+ } catch (const std::runtime_error& e) {
+ // The I2P router is expected to send the Base64 of the connecting peer,
+ // but it may happen that something like this is sent instead:
+ // STREAM STATUS RESULT=I2P_ERROR MESSAGE="Session was closed"
+ // In that case consider the session damaged and close it right away,
+ // even if the control socket is alive.
+ if (peer_dest.find("RESULT=I2P_ERROR") != std::string::npos) {
+ errmsg = strprintf("unexpected reply that hints the session is unusable: %s", peer_dest);
+ disconnect = true;
+ } else {
+ errmsg = e.what();
+ }
+ break;
+ }
+
+ conn.peer = CService(peer_addr, I2P_SAM31_PORT);
+
+ return true;
+ }
+
+ Log("Error accepting%s: %s", disconnect ? " (will close the session)" : "", errmsg);
+ if (disconnect) {
+ LOCK(m_mutex);
+ Disconnect();
+ } else {
CheckControlSock();
}
return false;
diff --git a/src/i2p.h b/src/i2p.h
index cb9da64816..375abaccfc 100644
--- a/src/i2p.h
+++ b/src/i2p.h
@@ -105,7 +105,7 @@ class Session
* completion the `peer` member will be set to the address of the incoming peer.
* @return true on success
*/
- bool Accept(Connection& conn);
+ bool Accept(Connection& conn) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex);
/**
* Connect to an I2P peer.
diff --git a/src/init.cpp b/src/init.cpp
index 6c269226db..ef027fc9cf 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -1340,30 +1340,24 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
}
if (args.IsArgSet("-onlynet")) {
- std::set nets;
+ g_reachable_nets.RemoveAll();
for (const std::string& snet : args.GetArgs("-onlynet")) {
enum Network net = ParseNetwork(snet);
if (net == NET_UNROUTABLE)
return InitError(strprintf(_("Unknown network specified in -onlynet: '%s'"), snet));
- nets.insert(net);
- }
- for (int n = 0; n < NET_MAX; n++) {
- enum Network net = (enum Network)n;
- assert(IsReachable(net));
- if (!nets.count(net))
- SetReachable(net, false);
+ g_reachable_nets.Add(net);
}
}
if (!args.IsArgSet("-cjdnsreachable")) {
- if (args.IsArgSet("-onlynet") && IsReachable(NET_CJDNS)) {
+ if (args.IsArgSet("-onlynet") && g_reachable_nets.Contains(NET_CJDNS)) {
return InitError(
_("Outbound connections restricted to CJDNS (-onlynet=cjdns) but "
"-cjdnsreachable is not provided"));
}
- SetReachable(NET_CJDNS, false);
+ g_reachable_nets.Remove(NET_CJDNS);
}
- // Now IsReachable(NET_CJDNS) is true if:
+ // Now g_reachable_nets.Contains(NET_CJDNS) is true if:
// 1. -cjdnsreachable is given and
// 2.1. -onlynet is not given or
// 2.2. -onlynet=cjdns is given
@@ -1371,7 +1365,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
// Requesting DNS seeds entails connecting to IPv4/IPv6, which -onlynet options may prohibit:
// If -dnsseed=1 is explicitly specified, abort. If it's left unspecified by the user, we skip
// the DNS seeds by adjusting -dnsseed in InitParameterInteraction.
- if (args.GetBoolArg("-dnsseed") == true && !IsReachable(NET_IPV4) && !IsReachable(NET_IPV6)) {
+ if (args.GetBoolArg("-dnsseed") == true && !g_reachable_nets.Contains(NET_IPV4) && !g_reachable_nets.Contains(NET_IPV6)) {
return InitError(strprintf(_("Incompatible options: -dnsseed=1 was explicitly specified, but -onlynet forbids connections to IPv4/IPv6")));
};
@@ -1401,7 +1395,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
onion_proxy = addrProxy;
}
- const bool onlynet_used_with_onion{args.IsArgSet("-onlynet") && IsReachable(NET_ONION)};
+ const bool onlynet_used_with_onion{args.IsArgSet("-onlynet") && g_reachable_nets.Contains(NET_ONION)};
// -onion can be used to set only a proxy for .onion, or override normal proxy for .onion addresses
// -noonion (or -onion=0) disables connecting to .onion entirely
@@ -1436,7 +1430,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
"reaching the Tor network is not provided: none of -proxy, -onion or "
"-listenonion is given"));
}
- SetReachable(NET_ONION, false);
+ g_reachable_nets.Remove(NET_ONION);
}
for (const std::string& strAddr : args.GetArgs("-externalip")) {
@@ -1921,12 +1915,12 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
}
SetProxy(NET_I2P, Proxy{addr.value()});
} else {
- if (args.IsArgSet("-onlynet") && IsReachable(NET_I2P)) {
+ if (args.IsArgSet("-onlynet") && g_reachable_nets.Contains(NET_I2P)) {
return InitError(
_("Outbound connections restricted to i2p (-onlynet=i2p) but "
"-i2psam is not provided"));
}
- SetReachable(NET_I2P, false);
+ g_reachable_nets.Remove(NET_I2P);
}
connOptions.m_i2p_accept_incoming = args.GetBoolArg("-i2pacceptincoming", DEFAULT_I2P_ACCEPT_INCOMING);
diff --git a/src/net.cpp b/src/net.cpp
index 994abd986d..09a3d8617a 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -115,7 +115,6 @@ bool fDiscover = true;
bool fListen = true;
GlobalMutex g_maplocalhost_mutex;
std::map mapLocalHost GUARDED_BY(g_maplocalhost_mutex);
-static bool vfLimited[NET_MAX] GUARDED_BY(g_maplocalhost_mutex) = {};
std::string strSubVersion;
size_t CSerializedNetMsg::GetMemoryUsage() const noexcept
@@ -232,7 +231,7 @@ static int GetnScore(const CService& addr)
{
CService addrLocal = pnode->GetAddrLocal();
return fDiscover && pnode->addr.IsRoutable() && addrLocal.IsRoutable() &&
- IsReachable(addrLocal.GetNetwork());
+ g_reachable_nets.Contains(addrLocal);
}
std::optional GetLocalAddrForPeer(CNode& node)
@@ -270,22 +269,6 @@ std::optional GetLocalAddrForPeer(CNode& node)
return std::nullopt;
}
-/**
- * If an IPv6 address belongs to the address range used by the CJDNS network and
- * the CJDNS network is reachable (-cjdnsreachable config is set), then change
- * the type from NET_IPV6 to NET_CJDNS.
- * @param[in] service Address to potentially convert.
- * @return a copy of `service` either unmodified or changed to CJDNS.
- */
-CService MaybeFlipIPv6toCJDNS(const CService& service)
-{
- CService ret{service};
- if (ret.IsIPv6() && ret.HasCJDNSPrefix() && IsReachable(NET_CJDNS)) {
- ret.m_net = NET_CJDNS;
- }
- return ret;
-}
-
// learn a new local address
bool AddLocal(const CService& addr_, int nScore)
{
@@ -297,7 +280,7 @@ bool AddLocal(const CService& addr_, int nScore)
if (!fDiscover && nScore < LOCAL_MANUAL)
return false;
- if (!IsReachable(addr))
+ if (!g_reachable_nets.Contains(addr))
return false;
LogPrintf("AddLocal(%s,%i)\n", addr.ToStringAddrPort(), nScore);
@@ -327,25 +310,6 @@ void RemoveLocal(const CService& addr)
mapLocalHost.erase(addr);
}
-void SetReachable(enum Network net, bool reachable)
-{
- if (net == NET_UNROUTABLE || net == NET_INTERNAL)
- return;
- LOCK(g_maplocalhost_mutex);
- vfLimited[net] = !reachable;
-}
-
-bool IsReachable(enum Network net)
-{
- LOCK(g_maplocalhost_mutex);
- return !vfLimited[net];
-}
-
-bool IsReachable(const CNetAddr &addr)
-{
- return IsReachable(addr.GetNetwork());
-}
-
/** vote for a local address */
bool SeenLocal(const CService& addr)
{
@@ -375,17 +339,6 @@ CNode* CConnman::FindNode(const CNetAddr& ip)
return nullptr;
}
-CNode* CConnman::FindNode(const CSubNet& subNet)
-{
- LOCK(m_nodes_mutex);
- for (CNode* pnode : m_nodes) {
- if (subNet.Match(static_cast(pnode->addr))) {
- return pnode;
- }
- }
- return nullptr;
-}
-
CNode* CConnman::FindNode(const std::string& addrName)
{
LOCK(m_nodes_mutex);
@@ -2433,7 +2386,7 @@ std::unordered_set CConnman::GetReachableEmptyNetworks() const
for (int n = 0; n < NET_MAX; n++) {
enum Network net = (enum Network)n;
if (net == NET_UNROUTABLE || net == NET_INTERNAL) continue;
- if (IsReachable(net) && addrman.Size(net, std::nullopt) == 0) {
+ if (g_reachable_nets.Contains(net) && addrman.Size(net, std::nullopt) == 0) {
networks.insert(net);
}
}
@@ -2453,7 +2406,7 @@ bool CConnman::MaybePickPreferredNetwork(std::optional& network)
LOCK(m_nodes_mutex);
for (const auto net : nets) {
- if (IsReachable(net) && m_network_conn_counts[net] == 0 && addrman.Size(net) != 0) {
+ if (g_reachable_nets.Contains(net) && m_network_conn_counts[net] == 0 && addrman.Size(net) != 0) {
network = net;
return true;
}
@@ -2683,7 +2636,7 @@ void CConnman::ThreadOpenConnections(const std::vector connect)
if (anchor && !m_anchors.empty()) {
const CAddress addr = m_anchors.back();
m_anchors.pop_back();
- if (!addr.IsValid() || IsLocal(addr) || !IsReachable(addr) ||
+ if (!addr.IsValid() || IsLocal(addr) || !g_reachable_nets.Contains(addr) ||
!HasAllDesirableServiceFlags(addr.nServices) ||
outbound_ipv46_peer_netgroups.count(m_netgroupman.GetGroup(addr))) continue;
addrConnect = addr;
@@ -2738,8 +2691,9 @@ void CConnman::ThreadOpenConnections(const std::vector connect)
break;
}
- if (!IsReachable(addr))
+ if (!g_reachable_nets.Contains(addr)) {
continue;
+ }
// only consider very recently tried nodes after 30 failed attempts
if (current_time - addr_last_try < 10min && nTries < 30) {
@@ -2974,6 +2928,13 @@ void CConnman::ThreadI2PAcceptIncoming()
bool advertising_listen_addr = false;
i2p::Connection conn;
+ auto SleepOnFailure = [&]() {
+ interruptNet.sleep_for(err_wait);
+ if (err_wait < err_wait_cap) {
+ err_wait += 1s;
+ }
+ };
+
while (!interruptNet) {
if (!m_i2p_sam_session->Listen(conn)) {
@@ -2981,12 +2942,7 @@ void CConnman::ThreadI2PAcceptIncoming()
RemoveLocal(conn.me);
advertising_listen_addr = false;
}
-
- interruptNet.sleep_for(err_wait);
- if (err_wait < err_wait_cap) {
- err_wait *= 2;
- }
-
+ SleepOnFailure();
continue;
}
@@ -2996,11 +2952,14 @@ void CConnman::ThreadI2PAcceptIncoming()
}
if (!m_i2p_sam_session->Accept(conn)) {
+ SleepOnFailure();
continue;
}
CreateNodeFromAcceptedSocket(std::move(conn.sock), NetPermissionFlags::None,
CAddress{conn.me, NODE_NONE}, CAddress{conn.peer, NODE_NONE});
+
+ err_wait = err_wait_begin;
}
}
diff --git a/src/net.h b/src/net.h
index a03e413465..7f48ff5ed6 100644
--- a/src/net.h
+++ b/src/net.h
@@ -166,24 +166,12 @@ enum
/** Returns a local address that we should advertise to this peer. */
std::optional GetLocalAddrForPeer(CNode& node);
-/**
- * Mark a network as reachable or unreachable (no automatic connects to it)
- * @note Networks are reachable by default
- */
-void SetReachable(enum Network net, bool reachable);
-/** @returns true if the network is reachable, false otherwise */
-bool IsReachable(enum Network net);
-/** @returns true if the address is in a reachable network, false otherwise */
-bool IsReachable(const CNetAddr& addr);
-
bool AddLocal(const CService& addr, int nScore = LOCAL_NONE);
bool AddLocal(const CNetAddr& addr, int nScore = LOCAL_NONE);
void RemoveLocal(const CService& addr);
bool SeenLocal(const CService& addr);
bool IsLocal(const CService& addr);
CService GetLocalAddress(const CNode& peer);
-CService MaybeFlipIPv6toCJDNS(const CService& service);
-
extern bool fDiscover;
extern bool fListen;
@@ -1347,7 +1335,6 @@ class CConnman
uint64_t CalculateKeyedNetGroup(const CAddress& ad) const;
CNode* FindNode(const CNetAddr& ip);
- CNode* FindNode(const CSubNet& subNet);
CNode* FindNode(const std::string& addrName);
CNode* FindNode(const CService& addr);
diff --git a/src/net_permissions.cpp b/src/net_permissions.cpp
index 23226bbb4f..cf6b58e08d 100644
--- a/src/net_permissions.cpp
+++ b/src/net_permissions.cpp
@@ -71,13 +71,13 @@ bool TryParsePermissionFlags(const std::string& str, NetPermissionFlags& output,
std::vector NetPermissions::ToStrings(NetPermissionFlags flags)
{
std::vector strings;
- if (NetPermissions::HasFlag(flags, NetPermissionFlags::BloomFilter)) strings.push_back("bloomfilter");
- if (NetPermissions::HasFlag(flags, NetPermissionFlags::NoBan)) strings.push_back("noban");
- if (NetPermissions::HasFlag(flags, NetPermissionFlags::ForceRelay)) strings.push_back("forcerelay");
- if (NetPermissions::HasFlag(flags, NetPermissionFlags::Relay)) strings.push_back("relay");
- if (NetPermissions::HasFlag(flags, NetPermissionFlags::Mempool)) strings.push_back("mempool");
- if (NetPermissions::HasFlag(flags, NetPermissionFlags::Download)) strings.push_back("download");
- if (NetPermissions::HasFlag(flags, NetPermissionFlags::Addr)) strings.push_back("addr");
+ if (NetPermissions::HasFlag(flags, NetPermissionFlags::BloomFilter)) strings.emplace_back("bloomfilter");
+ if (NetPermissions::HasFlag(flags, NetPermissionFlags::NoBan)) strings.emplace_back("noban");
+ if (NetPermissions::HasFlag(flags, NetPermissionFlags::ForceRelay)) strings.emplace_back("forcerelay");
+ if (NetPermissions::HasFlag(flags, NetPermissionFlags::Relay)) strings.emplace_back("relay");
+ if (NetPermissions::HasFlag(flags, NetPermissionFlags::Mempool)) strings.emplace_back("mempool");
+ if (NetPermissions::HasFlag(flags, NetPermissionFlags::Download)) strings.emplace_back("download");
+ if (NetPermissions::HasFlag(flags, NetPermissionFlags::Addr)) strings.emplace_back("addr");
return strings;
}
diff --git a/src/net_processing.cpp b/src/net_processing.cpp
index 260c404c16..fbcbc9b841 100644
--- a/src/net_processing.cpp
+++ b/src/net_processing.cpp
@@ -2375,7 +2375,7 @@ void PeerManagerImpl::ProcessGetBlockData(CNode& pfrom, Peer& peer, const CInv&
// and we want it right after the last block so they don't
// wait for other stuff first.
std::vector vInv;
- vInv.push_back(CInv(MSG_BLOCK, m_chainman.ActiveChain().Tip()->GetBlockHash()));
+ vInv.emplace_back(MSG_BLOCK, m_chainman.ActiveChain().Tip()->GetBlockHash());
m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::INV, vInv));
peer.m_continuation_block.SetNull();
}
@@ -2800,7 +2800,7 @@ void PeerManagerImpl::HeadersDirectFetchBlocks(CNode& pfrom, const Peer& peer, c
break;
}
uint32_t nFetchFlags = GetFetchFlags(peer);
- vGetData.push_back(CInv(MSG_BLOCK | nFetchFlags, pindex->GetBlockHash()));
+ vGetData.emplace_back(MSG_BLOCK | nFetchFlags, pindex->GetBlockHash());
BlockRequested(pfrom.GetId(), *pindex);
LogPrint(BCLog::NET, "Requesting block %s from peer=%d\n",
pindex->GetBlockHash().ToString(), pfrom.GetId());
@@ -3349,7 +3349,7 @@ void PeerManagerImpl::ProcessCompactBlockTxns(CNode& pfrom, Peer& peer, const Bl
if (first_in_flight) {
// Might have collided, fall back to getdata now :(
std::vector invs;
- invs.push_back(CInv(MSG_BLOCK | GetFetchFlags(peer), block_transactions.blockhash));
+ invs.emplace_back(MSG_BLOCK | GetFetchFlags(peer), block_transactions.blockhash);
m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::GETDATA, invs));
} else {
RemoveBlockRequest(block_transactions.blockhash, pfrom.GetId());
@@ -3880,14 +3880,15 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
continue;
}
++num_proc;
- bool fReachable = IsReachable(addr);
+ const bool reachable{g_reachable_nets.Contains(addr)};
if (addr.nTime > current_a_time - 10min && !peer->m_getaddr_sent && vAddr.size() <= 10 && addr.IsRoutable()) {
// Relay to a limited number of other nodes
- RelayAddress(pfrom.GetId(), addr, fReachable);
+ RelayAddress(pfrom.GetId(), addr, reachable);
}
// Do not store addresses outside our network
- if (fReachable)
+ if (reachable) {
vAddrOk.push_back(addr);
+ }
}
peer->m_addr_processed += num_proc;
peer->m_addr_rate_limited += num_rate_limit;
@@ -4213,7 +4214,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
++nCount;
nSize += GetSerializeSize(header, PROTOCOL_VERSION);
- vHeaders.push_back(header);
+ vHeaders.emplace_back(header);
if (nCount >= MAX_HEADERS_RESULTS
|| pindex->GetBlockHash() == hashStop)
break;
@@ -5731,14 +5732,14 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
pBestIndex = pindex;
if (fFoundStartingHeader) {
// add this to the headers message
- vHeaders.push_back(pindex->GetBlockHeader(m_chainman.m_blockman));
+ vHeaders.emplace_back(pindex->GetBlockHeader(m_chainman.m_blockman));
} else if (PeerHasHeader(&state, pindex)) {
continue; // keep looking for the first new block
} else if (pindex->pprev == nullptr || PeerHasHeader(&state, pindex->pprev)) {
// Peer doesn't have this header but they do have the prior one.
// Start sending headers.
fFoundStartingHeader = true;
- vHeaders.push_back(pindex->GetBlockHeader(m_chainman.m_blockman));
+ vHeaders.emplace_back(pindex->GetBlockHeader(m_chainman.m_blockman));
} else {
// Peer doesn't have this header or the prior one -- nothing will
// connect, so bail out.
@@ -5824,7 +5825,7 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
// Add blocks
for (const uint256& hash : peer->m_blocks_for_inv_relay) {
- vInv.push_back(CInv(MSG_BLOCK, hash));
+ vInv.emplace_back(MSG_BLOCK, hash);
if (vInv.size() == MAX_INV_SZ) {
m_connman.PushMessage(pto, msgMaker.Make(NetMsgType::INV, vInv));
vInv.clear();
@@ -6030,7 +6031,7 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
}
for (const CBlockIndex *pindex : vToDownload) {
uint32_t nFetchFlags = GetFetchFlags(*peer);
- vGetData.push_back(CInv(MSG_BLOCK | nFetchFlags, pindex->GetBlockHash()));
+ vGetData.emplace_back(MSG_BLOCK | nFetchFlags, pindex->GetBlockHash());
BlockRequested(pto->GetId(), *pindex);
LogPrint(BCLog::NET, "Requesting block %s (%d) peer=%d\n", pindex->GetBlockHash().ToString(),
pindex->nHeight, pto->GetId());
diff --git a/src/netaddress.h b/src/netaddress.h
index ad09f16799..08dd77c0ff 100644
--- a/src/netaddress.h
+++ b/src/netaddress.h
@@ -81,6 +81,10 @@ static const std::array INTERNAL_IN_IPV6_PREFIX{
0xFD, 0x6B, 0x88, 0xC0, 0x87, 0x24 // 0xFD + sha256("bitcoin")[0:5].
};
+/// All CJDNS addresses start with 0xFC. See
+/// https://github.com/cjdelisle/cjdns/blob/master/doc/Whitepaper.md#pulling-it-all-together
+static constexpr uint8_t CJDNS_PREFIX{0xFC};
+
/// Size of IPv4 address (in bytes).
static constexpr size_t ADDR_IPV4_SIZE = 4;
@@ -174,7 +178,7 @@ class CNetAddr
[[nodiscard]] bool IsTor() const { return m_net == NET_ONION; }
[[nodiscard]] bool IsI2P() const { return m_net == NET_I2P; }
[[nodiscard]] bool IsCJDNS() const { return m_net == NET_CJDNS; }
- [[nodiscard]] bool HasCJDNSPrefix() const { return m_addr[0] == 0xfc; }
+ [[nodiscard]] bool HasCJDNSPrefix() const { return m_addr[0] == CJDNS_PREFIX; }
bool IsLocal() const;
bool IsRoutable() const;
bool IsInternal() const;
diff --git a/src/netbase.cpp b/src/netbase.cpp
index ca1a80d72f..5e1e121bfe 100644
--- a/src/netbase.cpp
+++ b/src/netbase.cpp
@@ -32,6 +32,8 @@ bool fNameLookup = DEFAULT_NAME_LOOKUP;
std::chrono::milliseconds g_socks5_recv_timeout = 20s;
static std::atomic interruptSocks5Recv(false);
+ReachableNets g_reachable_nets;
+
std::vector WrappedGetAddrInfo(const std::string& name, bool allow_lookup)
{
addrinfo ai_hint{};
@@ -651,9 +653,10 @@ bool LookupSubNet(const std::string& subnet_str, CSubNet& subnet_out)
const size_t slash_pos{subnet_str.find_last_of('/')};
const std::string str_addr{subnet_str.substr(0, slash_pos)};
- const std::optional addr{LookupHost(str_addr, /*fAllowLookup=*/false)};
+ std::optional addr{LookupHost(str_addr, /*fAllowLookup=*/false)};
if (addr.has_value()) {
+ addr = static_cast(MaybeFlipIPv6toCJDNS(CService{addr.value(), /*port=*/0}));
if (slash_pos != subnet_str.npos) {
const std::string netmask_str{subnet_str.substr(slash_pos + 1)};
uint8_t netmask;
@@ -772,3 +775,12 @@ bool IsBadPort(uint16_t port)
}
return false;
}
+
+CService MaybeFlipIPv6toCJDNS(const CService& service)
+{
+ CService ret{service};
+ if (ret.IsIPv6() && ret.HasCJDNSPrefix() && g_reachable_nets.Contains(NET_CJDNS)) {
+ ret.m_net = NET_CJDNS;
+ }
+ return ret;
+}
diff --git a/src/netbase.h b/src/netbase.h
index 1da4f5c51d..8b7da4109f 100644
--- a/src/netbase.h
+++ b/src/netbase.h
@@ -19,6 +19,7 @@
#include
#include
#include
+#include
#include
extern int nConnectTimeout;
@@ -64,6 +65,61 @@ struct ProxyCredentials
std::string password;
};
+/**
+ * List of reachable networks. Everything is reachable by default.
+ */
+class ReachableNets {
+public:
+ void Add(Network net) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
+ {
+ AssertLockNotHeld(m_mutex);
+ LOCK(m_mutex);
+ m_reachable.insert(net);
+ }
+
+ void Remove(Network net) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
+ {
+ AssertLockNotHeld(m_mutex);
+ LOCK(m_mutex);
+ m_reachable.erase(net);
+ }
+
+ void RemoveAll() EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
+ {
+ AssertLockNotHeld(m_mutex);
+ LOCK(m_mutex);
+ m_reachable.clear();
+ }
+
+ [[nodiscard]] bool Contains(Network net) const EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
+ {
+ AssertLockNotHeld(m_mutex);
+ LOCK(m_mutex);
+ return m_reachable.count(net) > 0;
+ }
+
+ [[nodiscard]] bool Contains(const CNetAddr& addr) const EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
+ {
+ AssertLockNotHeld(m_mutex);
+ return Contains(addr.GetNetwork());
+ }
+
+private:
+ mutable Mutex m_mutex;
+
+ std::unordered_set m_reachable GUARDED_BY(m_mutex){
+ NET_UNROUTABLE,
+ NET_IPV4,
+ NET_IPV6,
+ NET_ONION,
+ NET_I2P,
+ NET_CJDNS,
+ NET_INTERNAL
+ };
+};
+
+extern ReachableNets g_reachable_nets;
+
/**
* Wrapper for getaddrinfo(3). Do not use directly: call Lookup/LookupHost/LookupNumeric/LookupSubNet.
*/
@@ -251,4 +307,13 @@ bool Socks5(const std::string& strDest, uint16_t port, const ProxyCredentials* a
*/
bool IsBadPort(uint16_t port);
+/**
+ * If an IPv6 address belongs to the address range used by the CJDNS network and
+ * the CJDNS network is reachable (-cjdnsreachable config is set), then change
+ * the type from NET_IPV6 to NET_CJDNS.
+ * @param[in] service Address to potentially convert.
+ * @return a copy of `service` either unmodified or changed to CJDNS.
+ */
+CService MaybeFlipIPv6toCJDNS(const CService& service);
+
#endif // BITCOIN_NETBASE_H
diff --git a/src/netgroup.cpp b/src/netgroup.cpp
index 2d4d231f2b..a03927b152 100644
--- a/src/netgroup.cpp
+++ b/src/netgroup.cpp
@@ -52,8 +52,8 @@ std::vector NetGroupManager::GetGroup(const CNetAddr& address) co
} else if (address.IsCJDNS()) {
// Treat in the same way as Tor and I2P because the address in all of
// them is "random" bytes (derived from a public key). However in CJDNS
- // the first byte is a constant 0xfc, so the random bytes come after it.
- // Thus skip the constant 8 bits at the start.
+ // the first byte is a constant (see CJDNS_PREFIX), so the random bytes
+ // come after it. Thus skip the constant 8 bits at the start.
nBits = 12;
} else if (address.IsHeNet()) {
// for he.net, use /36 groups
diff --git a/src/node/blockstorage.cpp b/src/node/blockstorage.cpp
index 003f6e0583..1aa47381bf 100644
--- a/src/node/blockstorage.cpp
+++ b/src/node/blockstorage.cpp
@@ -459,7 +459,7 @@ bool BlockManager::WriteBlockIndexDB()
std::vector> vFiles;
vFiles.reserve(m_dirty_fileinfo.size());
for (std::set::iterator it = m_dirty_fileinfo.begin(); it != m_dirty_fileinfo.end();) {
- vFiles.push_back(std::make_pair(*it, &m_blockfile_info[*it]));
+ vFiles.emplace_back(*it, &m_blockfile_info[*it]);
m_dirty_fileinfo.erase(it++);
}
std::vector vBlocks;
diff --git a/src/node/interfaces.cpp b/src/node/interfaces.cpp
index 4baa0da67c..f6dbe4f008 100644
--- a/src/node/interfaces.cpp
+++ b/src/node/interfaces.cpp
@@ -674,7 +674,7 @@ class ChainImpl : public Chain
if (!m_node.mempool) {
std::map bump_fees;
for (const auto& outpoint : outpoints) {
- bump_fees.emplace(std::make_pair(outpoint, 0));
+ bump_fees.emplace(outpoint, 0);
}
return bump_fees;
}
diff --git a/src/psbt.h b/src/psbt.h
index 48e0453084..5b4daafed5 100644
--- a/src/psbt.h
+++ b/src/psbt.h
@@ -874,7 +874,7 @@ struct PSBTOutput
if ((leaf_ver & ~TAPROOT_LEAF_MASK) != 0) {
throw std::ios_base::failure("Output Taproot tree has a leaf with an invalid leaf version");
}
- m_tap_tree.push_back(std::make_tuple(depth, leaf_ver, script));
+ m_tap_tree.emplace_back(depth, leaf_ver, script);
builder.Add((int)depth, script, (int)leaf_ver, /*track=*/true);
}
if (!builder.IsComplete()) {
diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp
index 278dfc2c38..a1f5f521a9 100644
--- a/src/qt/bitcoingui.cpp
+++ b/src/qt/bitcoingui.cpp
@@ -420,7 +420,7 @@ void BitcoinGUI::createActions()
connect(usedSendingAddressesAction, &QAction::triggered, walletFrame, &WalletFrame::usedSendingAddresses);
connect(usedReceivingAddressesAction, &QAction::triggered, walletFrame, &WalletFrame::usedReceivingAddresses);
connect(openAction, &QAction::triggered, this, &BitcoinGUI::openClicked);
- connect(m_open_wallet_menu, &QMenu::aboutToShow, [this] {
+ connect(m_open_wallet_menu, &QMenu::aboutToShow, m_wallet_controller, [this] {
m_open_wallet_menu->clear();
for (const std::pair& i : m_wallet_controller->listWalletDir()) {
const std::string& path = i.first;
@@ -437,7 +437,7 @@ void BitcoinGUI::createActions()
continue;
}
- connect(action, &QAction::triggered, [this, path] {
+ connect(action, &QAction::triggered, m_wallet_controller, [this, path] {
auto activity = new OpenWalletActivity(m_wallet_controller, this);
connect(activity, &OpenWalletActivity::opened, this, &BitcoinGUI::setCurrentWallet, Qt::QueuedConnection);
connect(activity, &OpenWalletActivity::opened, rpcConsole, &RPCConsole::setCurrentWallet, Qt::QueuedConnection);
@@ -449,7 +449,7 @@ void BitcoinGUI::createActions()
action->setEnabled(false);
}
});
- connect(m_restore_wallet_action, &QAction::triggered, [this] {
+ connect(m_restore_wallet_action, &QAction::triggered, m_wallet_controller, [this] {
//: Name of the wallet data file format.
QString name_data_file = tr("Wallet Data");
@@ -475,14 +475,14 @@ void BitcoinGUI::createActions()
auto backup_file_path = fs::PathFromString(backup_file.toStdString());
activity->restore(backup_file_path, wallet_name.toStdString());
});
- connect(m_close_wallet_action, &QAction::triggered, [this] {
+ connect(m_close_wallet_action, &QAction::triggered, m_wallet_controller, [this] {
m_wallet_controller->closeWallet(walletFrame->currentWalletModel(), this);
});
connect(m_create_wallet_action, &QAction::triggered, this, &BitcoinGUI::createWallet);
- connect(m_close_all_wallets_action, &QAction::triggered, [this] {
+ connect(m_close_all_wallets_action, &QAction::triggered, m_wallet_controller, [this] {
m_wallet_controller->closeAllWallets(this);
});
- connect(m_migrate_wallet_action, &QAction::triggered, [this] {
+ connect(m_migrate_wallet_action, &QAction::triggered, m_wallet_controller, [this] {
auto activity = new MigrateWalletActivity(m_wallet_controller, this);
connect(activity, &MigrateWalletActivity::migrated, this, &BitcoinGUI::setCurrentWallet);
activity->migrate(walletFrame->currentWalletModel());
@@ -680,7 +680,8 @@ void BitcoinGUI::setClientModel(ClientModel *_clientModel, interfaces::BlockAndH
m_mask_values_action->setChecked(_clientModel->getOptionsModel()->getOption(OptionsModel::OptionID::MaskValues).toBool());
} else {
- if(trayIconMenu)
+ // Shutdown requested, disable menus
+ if (trayIconMenu)
{
// Disable context menu on tray icon
trayIconMenu->clear();
@@ -694,6 +695,8 @@ void BitcoinGUI::setClientModel(ClientModel *_clientModel, interfaces::BlockAndH
}
#endif // ENABLE_WALLET
unitDisplayControl->setOptionsModel(nullptr);
+ // Disable top bar menu actions
+ appMenuBar->clear();
}
}
diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp
index 9c6d1169e8..06fceeb49d 100644
--- a/src/qt/coincontroldialog.cpp
+++ b/src/qt/coincontroldialog.cpp
@@ -421,7 +421,19 @@ void CoinControlDialog::updateLabels(CCoinControl& m_coin_control, WalletModel *
std::vector witnessprogram;
if (out.txout.scriptPubKey.IsWitnessProgram(true, witnessversion, witnessprogram))
{
- nBytesInputs += (32 + 4 + 1 + (107 / WITNESS_SCALE_FACTOR) + 4);
+ // add input skeleton bytes (outpoint, scriptSig size, nSequence)
+ nBytesInputs += (32 + 4 + 1 + 4);
+
+ if (witnessversion == 0) { // P2WPKH
+ // 1 WU (witness item count) + 72 WU (ECDSA signature with len byte) + 34 WU (pubkey with len byte)
+ nBytesInputs += 107 / WITNESS_SCALE_FACTOR;
+ } else if (witnessversion == 1) { // P2TR key-path spend
+ // 1 WU (witness item count) + 65 WU (Schnorr signature with len byte)
+ nBytesInputs += 66 / WITNESS_SCALE_FACTOR;
+ } else {
+ // not supported, should be unreachable
+ throw std::runtime_error("Trying to spend future segwit version script");
+ }
fWitness = true;
}
else if(ExtractDestination(out.txout.scriptPubKey, address))
diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp
index 998a4e5cbe..ceaa3ac46b 100644
--- a/src/qt/rpcconsole.cpp
+++ b/src/qt/rpcconsole.cpp
@@ -169,7 +169,7 @@ class PeerIdViewDelegate : public QStyledItemDelegate
bool RPCConsole::RPCParseCommandLine(interfaces::Node* node, std::string &strResult, const std::string &strCommand, const bool fExecute, std::string * const pstrFilteredOut, const WalletModel* wallet_model)
{
std::vector< std::vector > stack;
- stack.push_back(std::vector());
+ stack.emplace_back();
enum CmdParseState
{
@@ -197,7 +197,7 @@ bool RPCConsole::RPCParseCommandLine(interfaces::Node* node, std::string &strRes
}
// Make sure stack is not empty before adding something
if (stack.empty()) {
- stack.push_back(std::vector());
+ stack.emplace_back();
}
stack.back().push_back(strArg);
};
@@ -206,7 +206,7 @@ bool RPCConsole::RPCParseCommandLine(interfaces::Node* node, std::string &strRes
if (nDepthInsideSensitive) {
if (!--nDepthInsideSensitive) {
assert(filter_begin_pos);
- filter_ranges.push_back(std::make_pair(filter_begin_pos, chpos));
+ filter_ranges.emplace_back(filter_begin_pos, chpos);
filter_begin_pos = 0;
}
}
@@ -306,7 +306,7 @@ bool RPCConsole::RPCParseCommandLine(interfaces::Node* node, std::string &strRes
if (nDepthInsideSensitive) {
++nDepthInsideSensitive;
}
- stack.push_back(std::vector());
+ stack.emplace_back();
}
// don't allow commands after executed commands on baselevel
diff --git a/src/rest.cpp b/src/rest.cpp
index 95891b7474..f0fa3ed8f8 100644
--- a/src/rest.cpp
+++ b/src/rest.cpp
@@ -851,7 +851,7 @@ static bool rest_getutxos(const std::any& context, HTTPRequest* req, const std::
return RESTERR(req, HTTP_BAD_REQUEST, "Parse error");
txid.SetHex(strTxid);
- vOutPoints.push_back(COutPoint(txid, (uint32_t)nOutput));
+ vOutPoints.emplace_back(txid, (uint32_t)nOutput);
}
if (vOutPoints.size() > 0)
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp
index 343f1a8e96..40fd40976c 100644
--- a/src/rpc/blockchain.cpp
+++ b/src/rpc/blockchain.cpp
@@ -2032,7 +2032,7 @@ static RPCHelpMan getblockstats()
// New feerate uses satoshis per virtual byte instead of per serialized byte
CAmount feerate = weight ? (txfee * WITNESS_SCALE_FACTOR) / weight : 0;
if (do_feerate_percentiles) {
- feerate_array.emplace_back(std::make_pair(feerate, weight));
+ feerate_array.emplace_back(feerate, weight);
}
maxfeerate = std::max(maxfeerate, feerate);
minfeerate = std::min(minfeerate, feerate);
@@ -2839,6 +2839,7 @@ static RPCHelpMan loadtxoutset()
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
NodeContext& node = EnsureAnyNodeContext(request.context);
+ ChainstateManager& chainman = EnsureChainman(node);
fs::path path{AbsPathForConfigVal(EnsureArgsman(node), fs::u8path(request.params[0].get_str()))};
FILE* file{fsbridge::fopen(path, "rb")};
@@ -2853,14 +2854,16 @@ static RPCHelpMan loadtxoutset()
afile >> metadata;
uint256 base_blockhash = metadata.m_base_blockhash;
+ if (!chainman.GetParams().AssumeutxoForBlockhash(base_blockhash).has_value()) {
+ throw JSONRPCError(RPC_INTERNAL_ERROR, strprintf("Unable to load UTXO snapshot, "
+ "assumeutxo block hash in snapshot metadata not recognized (%s)", base_blockhash.ToString()));
+ }
int max_secs_to_wait_for_headers = 60 * 10;
CBlockIndex* snapshot_start_block = nullptr;
LogPrintf("[snapshot] waiting to see blockheader %s in headers chain before snapshot activation\n",
base_blockhash.ToString());
- ChainstateManager& chainman = EnsureChainman(node);
-
while (max_secs_to_wait_for_headers > 0) {
snapshot_start_block = WITH_LOCK(::cs_main,
return chainman.m_blockman.LookupBlockIndex(base_blockhash));
diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp
index e2d6acad09..8f096c8168 100644
--- a/src/rpc/net.cpp
+++ b/src/rpc/net.cpp
@@ -585,8 +585,8 @@ static UniValue GetNetworksInfo()
UniValue obj(UniValue::VOBJ);
GetProxy(network, proxy);
obj.pushKV("name", GetNetworkName(network));
- obj.pushKV("limited", !IsReachable(network));
- obj.pushKV("reachable", IsReachable(network));
+ obj.pushKV("limited", !g_reachable_nets.Contains(network));
+ obj.pushKV("reachable", g_reachable_nets.Contains(network));
obj.pushKV("proxy", proxy.IsValid() ? proxy.proxy.ToStringAddrPort() : std::string());
obj.pushKV("proxy_randomize_credentials", proxy.randomize_credentials);
networks.push_back(obj);
@@ -730,7 +730,7 @@ static RPCHelpMan setban()
if (!isSubnet) {
const std::optional addr{LookupHost(request.params[0].get_str(), false)};
if (addr.has_value()) {
- netAddr = addr.value();
+ netAddr = static_cast(MaybeFlipIPv6toCJDNS(CService{addr.value(), /*port=*/0}));
}
}
else
@@ -949,10 +949,7 @@ static RPCHelpMan addpeeraddress()
},
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
- NodeContext& node = EnsureAnyNodeContext(request.context);
- if (!node.addrman) {
- throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Address manager functionality missing or disabled");
- }
+ AddrMan& addrman = EnsureAnyAddrman(request.context);
const std::string& addr_string{request.params[0].get_str()};
const auto port{request.params[1].getInt()};
@@ -968,11 +965,11 @@ static RPCHelpMan addpeeraddress()
address.nTime = Now();
// The source address is set equal to the address. This is equivalent to the peer
// announcing itself.
- if (node.addrman->Add({address}, address)) {
+ if (addrman.Add({address}, address)) {
success = true;
if (tried) {
// Attempt to move the address to the tried addresses table.
- node.addrman->Good(address);
+ addrman.Good(address);
}
}
}
@@ -1033,50 +1030,40 @@ static RPCHelpMan sendmsgtopeer()
static RPCHelpMan getaddrmaninfo()
{
- return RPCHelpMan{"getaddrmaninfo",
- "\nProvides information about the node's address manager by returning the number of "
- "addresses in the `new` and `tried` tables and their sum for all networks.\n"
- "This RPC is for testing only.\n",
- {},
- RPCResult{
- RPCResult::Type::OBJ_DYN, "", "json object with network type as keys",
- {
- {RPCResult::Type::OBJ, "network", "the network (" + Join(GetNetworkNames(), ", ") + ")",
- {
- {RPCResult::Type::NUM, "new", "number of addresses in the new table, which represent potential peers the node has discovered but hasn't yet successfully connected to."},
- {RPCResult::Type::NUM, "tried", "number of addresses in the tried table, which represent peers the node has successfully connected to in the past."},
- {RPCResult::Type::NUM, "total", "total number of addresses in both new/tried tables"},
- }},
- }
- },
- RPCExamples{
- HelpExampleCli("getaddrmaninfo", "")
- + HelpExampleRpc("getaddrmaninfo", "")
- },
- [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
- {
- NodeContext& node = EnsureAnyNodeContext(request.context);
- if (!node.addrman) {
- throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Address manager functionality missing or disabled");
- }
-
- UniValue ret(UniValue::VOBJ);
- for (int n = 0; n < NET_MAX; ++n) {
- enum Network network = static_cast(n);
- if (network == NET_UNROUTABLE || network == NET_INTERNAL) continue;
- UniValue obj(UniValue::VOBJ);
- obj.pushKV("new", node.addrman->Size(network, true));
- obj.pushKV("tried", node.addrman->Size(network, false));
- obj.pushKV("total", node.addrman->Size(network));
- ret.pushKV(GetNetworkName(network), obj);
- }
- UniValue obj(UniValue::VOBJ);
- obj.pushKV("new", node.addrman->Size(std::nullopt, true));
- obj.pushKV("tried", node.addrman->Size(std::nullopt, false));
- obj.pushKV("total", node.addrman->Size());
- ret.pushKV("all_networks", obj);
- return ret;
- },
+ return RPCHelpMan{
+ "getaddrmaninfo",
+ "\nProvides information about the node's address manager by returning the number of "
+ "addresses in the `new` and `tried` tables and their sum for all networks.\n",
+ {},
+ RPCResult{
+ RPCResult::Type::OBJ_DYN, "", "json object with network type as keys", {
+ {RPCResult::Type::OBJ, "network", "the network (" + Join(GetNetworkNames(), ", ") + ", all_networks)", {
+ {RPCResult::Type::NUM, "new", "number of addresses in the new table, which represent potential peers the node has discovered but hasn't yet successfully connected to."},
+ {RPCResult::Type::NUM, "tried", "number of addresses in the tried table, which represent peers the node has successfully connected to in the past."},
+ {RPCResult::Type::NUM, "total", "total number of addresses in both new/tried tables"},
+ }},
+ }},
+ RPCExamples{HelpExampleCli("getaddrmaninfo", "") + HelpExampleRpc("getaddrmaninfo", "")},
+ [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue {
+ AddrMan& addrman = EnsureAnyAddrman(request.context);
+
+ UniValue ret(UniValue::VOBJ);
+ for (int n = 0; n < NET_MAX; ++n) {
+ enum Network network = static_cast(n);
+ if (network == NET_UNROUTABLE || network == NET_INTERNAL) continue;
+ UniValue obj(UniValue::VOBJ);
+ obj.pushKV("new", addrman.Size(network, true));
+ obj.pushKV("tried", addrman.Size(network, false));
+ obj.pushKV("total", addrman.Size(network));
+ ret.pushKV(GetNetworkName(network), obj);
+ }
+ UniValue obj(UniValue::VOBJ);
+ obj.pushKV("new", addrman.Size(std::nullopt, true));
+ obj.pushKV("tried", addrman.Size(std::nullopt, false));
+ obj.pushKV("total", addrman.Size());
+ ret.pushKV("all_networks", obj);
+ return ret;
+ },
};
}
@@ -1135,14 +1122,11 @@ static RPCHelpMan getrawaddrman()
+ HelpExampleRpc("getrawaddrman", "")
},
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue {
- NodeContext& node = EnsureAnyNodeContext(request.context);
- if (!node.addrman) {
- throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Address manager functionality missing or disabled");
- }
+ AddrMan& addrman = EnsureAnyAddrman(request.context);
UniValue ret(UniValue::VOBJ);
- ret.pushKV("new", AddrmanTableToJSON(node.addrman->GetEntries(false)));
- ret.pushKV("tried", AddrmanTableToJSON(node.addrman->GetEntries(true)));
+ ret.pushKV("new", AddrmanTableToJSON(addrman.GetEntries(false)));
+ ret.pushKV("tried", AddrmanTableToJSON(addrman.GetEntries(true)));
return ret;
},
};
@@ -1164,10 +1148,10 @@ void RegisterNetRPCCommands(CRPCTable& t)
{"network", &clearbanned},
{"network", &setnetworkactive},
{"network", &getnodeaddresses},
+ {"network", &getaddrmaninfo},
{"hidden", &addconnection},
{"hidden", &addpeeraddress},
{"hidden", &sendmsgtopeer},
- {"hidden", &getaddrmaninfo},
{"hidden", &getrawaddrman},
};
for (const auto& c : commands) {
diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp
index 27601fac85..e0471a9208 100644
--- a/src/rpc/rawtransaction.cpp
+++ b/src/rpc/rawtransaction.cpp
@@ -1583,10 +1583,10 @@ static RPCHelpMan createpsbt()
PartiallySignedTransaction psbtx;
psbtx.tx = rawTx;
for (unsigned int i = 0; i < rawTx.vin.size(); ++i) {
- psbtx.inputs.push_back(PSBTInput());
+ psbtx.inputs.emplace_back();
}
for (unsigned int i = 0; i < rawTx.vout.size(); ++i) {
- psbtx.outputs.push_back(PSBTOutput());
+ psbtx.outputs.emplace_back();
}
// Serialize the PSBT
@@ -1650,10 +1650,10 @@ static RPCHelpMan converttopsbt()
PartiallySignedTransaction psbtx;
psbtx.tx = tx;
for (unsigned int i = 0; i < tx.vin.size(); ++i) {
- psbtx.inputs.push_back(PSBTInput());
+ psbtx.inputs.emplace_back();
}
for (unsigned int i = 0; i < tx.vout.size(); ++i) {
- psbtx.outputs.push_back(PSBTOutput());
+ psbtx.outputs.emplace_back();
}
// Serialize the PSBT
diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp
index daf751111f..d3c5a19326 100644
--- a/src/rpc/server.cpp
+++ b/src/rpc/server.cpp
@@ -88,7 +88,7 @@ std::string CRPCTable::help(const std::string& strCommand, const JSONRPCRequest&
vCommands.reserve(mapCommands.size());
for (const auto& entry : mapCommands)
- vCommands.push_back(make_pair(entry.second.front()->category + entry.first, entry.second.front()));
+ vCommands.emplace_back(entry.second.front()->category + entry.first, entry.second.front());
sort(vCommands.begin(), vCommands.end());
JSONRPCRequest jreq = helpreq;
diff --git a/src/rpc/server_util.cpp b/src/rpc/server_util.cpp
index fcf3f1d659..674a1db7c5 100644
--- a/src/rpc/server_util.cpp
+++ b/src/rpc/server_util.cpp
@@ -123,3 +123,16 @@ PeerManager& EnsurePeerman(const NodeContext& node)
}
return *node.peerman;
}
+
+AddrMan& EnsureAddrman(const NodeContext& node)
+{
+ if (!node.addrman) {
+ throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Address manager functionality missing or disabled");
+ }
+ return *node.addrman;
+}
+
+AddrMan& EnsureAnyAddrman(const std::any& context)
+{
+ return EnsureAddrman(EnsureAnyNodeContext(context));
+}
diff --git a/src/rpc/server_util.h b/src/rpc/server_util.h
index 94cd158dcb..c4e69e64d9 100644
--- a/src/rpc/server_util.h
+++ b/src/rpc/server_util.h
@@ -7,6 +7,7 @@
#include
+class AddrMan;
class ArgsManager;
class CBlockPolicyEstimator;
class CConnman;
@@ -33,5 +34,7 @@ CBlockPolicyEstimator& EnsureFeeEstimator(const node::NodeContext& node);
CBlockPolicyEstimator& EnsureAnyFeeEstimator(const std::any& context);
CConnman& EnsureConnman(const node::NodeContext& node);
PeerManager& EnsurePeerman(const node::NodeContext& node);
+AddrMan& EnsureAddrman(const node::NodeContext& node);
+AddrMan& EnsureAnyAddrman(const std::any& context);
#endif // BITCOIN_RPC_SERVER_UTIL_H
diff --git a/src/script/miniscript.h b/src/script/miniscript.h
index d6bded959d..76b952350b 100644
--- a/src/script/miniscript.h
+++ b/src/script/miniscript.h
@@ -1105,13 +1105,15 @@ struct Node {
}
internal::WitnessSize CalcWitnessSize() const {
+ const uint32_t sig_size = IsTapscript(m_script_ctx) ? 1 + 65 : 1 + 72;
+ const uint32_t pubkey_size = IsTapscript(m_script_ctx) ? 1 + 32 : 1 + 33;
switch (fragment) {
case Fragment::JUST_0: return {{}, 0};
case Fragment::JUST_1:
case Fragment::OLDER:
case Fragment::AFTER: return {0, {}};
- case Fragment::PK_K: return {1 + 72, 1};
- case Fragment::PK_H: return {1 + 72 + 1 + 33, 1 + 1 + 33};
+ case Fragment::PK_K: return {sig_size, 1};
+ case Fragment::PK_H: return {sig_size + pubkey_size, 1 + pubkey_size};
case Fragment::SHA256:
case Fragment::RIPEMD160:
case Fragment::HASH256:
@@ -1131,8 +1133,8 @@ struct Node {
case Fragment::OR_C: return {subs[0]->ws.sat | (subs[0]->ws.dsat + subs[1]->ws.sat), {}};
case Fragment::OR_D: return {subs[0]->ws.sat | (subs[0]->ws.dsat + subs[1]->ws.sat), subs[0]->ws.dsat + subs[1]->ws.dsat};
case Fragment::OR_I: return {(subs[0]->ws.sat + 1 + 1) | (subs[1]->ws.sat + 1), (subs[0]->ws.dsat + 1 + 1) | (subs[1]->ws.dsat + 1)};
- case Fragment::MULTI: return {k * (1 + 72) + 1, k + 1};
- case Fragment::MULTI_A: return {k * (1 + 65) + static_cast(keys.size()) - k, static_cast(keys.size())};
+ case Fragment::MULTI: return {k * sig_size + 1, k + 1};
+ case Fragment::MULTI_A: return {k * sig_size + static_cast(keys.size()) - k, static_cast(keys.size())};
case Fragment::WRAP_A:
case Fragment::WRAP_N:
case Fragment::WRAP_S:
diff --git a/src/script/namecoinconsensus.cpp b/src/script/namecoinconsensus.cpp
index 4d7f163427..853e18e399 100644
--- a/src/script/namecoinconsensus.cpp
+++ b/src/script/namecoinconsensus.cpp
@@ -72,14 +72,34 @@ static bool verify_flags(unsigned int flags)
static int verify_script(const unsigned char *scriptPubKey, unsigned int scriptPubKeyLen, CAmount amount,
const unsigned char *txTo , unsigned int txToLen,
+ const UTXO *spentOutputs, unsigned int spentOutputsLen,
unsigned int nIn, unsigned int flags, namecoinconsensus_error* err)
{
if (!verify_flags(flags)) {
return set_error(err, namecoinconsensus_ERR_INVALID_FLAGS);
}
+
+ if (flags & namecoinconsensus_SCRIPT_FLAGS_VERIFY_TAPROOT && spentOutputs == nullptr) {
+ return set_error(err, namecoinconsensus_ERR_SPENT_OUTPUTS_REQUIRED);
+ }
+
try {
TxInputStream stream(PROTOCOL_VERSION, txTo, txToLen);
CTransaction tx(deserialize, stream);
+
+ std::vector spent_outputs;
+ if (spentOutputs != nullptr) {
+ if (spentOutputsLen != tx.vin.size()) {
+ return set_error(err, namecoinconsensus_ERR_SPENT_OUTPUTS_MISMATCH);
+ }
+ for (size_t i = 0; i < spentOutputsLen; i++) {
+ CScript spk = CScript(spentOutputs[i].scriptPubKey, spentOutputs[i].scriptPubKey + spentOutputs[i].scriptPubKeySize);
+ const CAmount& value = spentOutputs[i].value;
+ CTxOut tx_out = CTxOut(value, spk);
+ spent_outputs.push_back(tx_out);
+ }
+ }
+
if (nIn >= tx.vin.size())
return set_error(err, namecoinconsensus_ERR_TX_INDEX);
if (GetSerializeSize(tx, PROTOCOL_VERSION) != txToLen)
@@ -89,18 +109,34 @@ static int verify_script(const unsigned char *scriptPubKey, unsigned int scriptP
set_error(err, namecoinconsensus_ERR_OK);
PrecomputedTransactionData txdata(tx);
+
+ if (spentOutputs != nullptr && flags & namecoinconsensus_SCRIPT_FLAGS_VERIFY_TAPROOT) {
+ txdata.Init(tx, std::move(spent_outputs));
+ }
+
return VerifyScript(tx.vin[nIn].scriptSig, CScript(scriptPubKey, scriptPubKey + scriptPubKeyLen), &tx.vin[nIn].scriptWitness, flags, TransactionSignatureChecker(&tx, nIn, amount, txdata, MissingDataBehavior::FAIL), nullptr);
} catch (const std::exception&) {
return set_error(err, namecoinconsensus_ERR_TX_DESERIALIZE); // Error deserializing
}
}
+int namecoinconsensus_verify_script_with_spent_outputs(const unsigned char *scriptPubKey, unsigned int scriptPubKeyLen, int64_t amount,
+ const unsigned char *txTo , unsigned int txToLen,
+ const UTXO *spentOutputs, unsigned int spentOutputsLen,
+ unsigned int nIn, unsigned int flags, namecoinconsensus_error* err)
+{
+ CAmount am(amount);
+ return ::verify_script(scriptPubKey, scriptPubKeyLen, am, txTo, txToLen, spentOutputs, spentOutputsLen, nIn, flags, err);
+}
+
int namecoinconsensus_verify_script_with_amount(const unsigned char *scriptPubKey, unsigned int scriptPubKeyLen, int64_t amount,
const unsigned char *txTo , unsigned int txToLen,
unsigned int nIn, unsigned int flags, namecoinconsensus_error* err)
{
CAmount am(amount);
- return ::verify_script(scriptPubKey, scriptPubKeyLen, am, txTo, txToLen, nIn, flags, err);
+ UTXO *spentOutputs = nullptr;
+ unsigned int spentOutputsLen = 0;
+ return ::verify_script(scriptPubKey, scriptPubKeyLen, am, txTo, txToLen, spentOutputs, spentOutputsLen, nIn, flags, err);
}
@@ -113,7 +149,9 @@ int namecoinconsensus_verify_script(const unsigned char *scriptPubKey, unsigned
}
CAmount am(0);
- return ::verify_script(scriptPubKey, scriptPubKeyLen, am, txTo, txToLen, nIn, flags, err);
+ UTXO *spentOutputs = nullptr;
+ unsigned int spentOutputsLen = 0;
+ return ::verify_script(scriptPubKey, scriptPubKeyLen, am, txTo, txToLen, spentOutputs, spentOutputsLen, nIn, flags, err);
}
unsigned int namecoinconsensus_version()
diff --git a/src/script/namecoinconsensus.h b/src/script/namecoinconsensus.h
index 07f684409e..e982ec540a 100644
--- a/src/script/namecoinconsensus.h
+++ b/src/script/namecoinconsensus.h
@@ -31,7 +31,7 @@
extern "C" {
#endif
-#define NAMECOINCONSENSUS_API_VER 1
+#define NAMECOINCONSENSUS_API_VER 2
typedef enum namecoinconsensus_error_t
{
@@ -41,6 +41,8 @@ typedef enum namecoinconsensus_error_t
namecoinconsensus_ERR_TX_DESERIALIZE,
namecoinconsensus_ERR_AMOUNT_REQUIRED,
namecoinconsensus_ERR_INVALID_FLAGS,
+ namecoinconsensus_ERR_SPENT_OUTPUTS_REQUIRED,
+ namecoinconsensus_ERR_SPENT_OUTPUTS_MISMATCH
} namecoinconsensus_error;
/** Script verification flags */
@@ -53,11 +55,19 @@ enum
namecoinconsensus_SCRIPT_FLAGS_VERIFY_CHECKLOCKTIMEVERIFY = (1U << 9), // enable CHECKLOCKTIMEVERIFY (BIP65)
namecoinconsensus_SCRIPT_FLAGS_VERIFY_CHECKSEQUENCEVERIFY = (1U << 10), // enable CHECKSEQUENCEVERIFY (BIP112)
namecoinconsensus_SCRIPT_FLAGS_VERIFY_WITNESS = (1U << 11), // enable WITNESS (BIP141)
+ namecoinconsensus_SCRIPT_FLAGS_VERIFY_TAPROOT = (1U << 17), // enable TAPROOT (BIPs 341 & 342)
namecoinconsensus_SCRIPT_FLAGS_VERIFY_ALL = namecoinconsensus_SCRIPT_FLAGS_VERIFY_P2SH | namecoinconsensus_SCRIPT_FLAGS_VERIFY_DERSIG |
- namecoinconsensus_SCRIPT_FLAGS_VERIFY_NULLDUMMY | namecoinconsensus_SCRIPT_FLAGS_VERIFY_CHECKLOCKTIMEVERIFY |
- namecoinconsensus_SCRIPT_FLAGS_VERIFY_CHECKSEQUENCEVERIFY | namecoinconsensus_SCRIPT_FLAGS_VERIFY_WITNESS
+ namecoinconsensus_SCRIPT_FLAGS_VERIFY_NULLDUMMY | namecoinconsensus_SCRIPT_FLAGS_VERIFY_CHECKLOCKTIMEVERIFY |
+ namecoinconsensus_SCRIPT_FLAGS_VERIFY_CHECKSEQUENCEVERIFY | namecoinconsensus_SCRIPT_FLAGS_VERIFY_WITNESS |
+ namecoinconsensus_SCRIPT_FLAGS_VERIFY_TAPROOT
};
+typedef struct {
+ const unsigned char *scriptPubKey;
+ unsigned int scriptPubKeySize;
+ int64_t value;
+} UTXO;
+
/// Returns 1 if the input nIn of the serialized transaction pointed to by
/// txTo correctly spends the scriptPubKey pointed to by scriptPubKey under
/// the additional constraints specified by flags.
@@ -70,6 +80,11 @@ EXPORT_SYMBOL int namecoinconsensus_verify_script_with_amount(const unsigned cha
const unsigned char *txTo , unsigned int txToLen,
unsigned int nIn, unsigned int flags, namecoinconsensus_error* err);
+EXPORT_SYMBOL int namecoinconsensus_verify_script_with_spent_outputs(const unsigned char *scriptPubKey, unsigned int scriptPubKeyLen, int64_t amount,
+ const unsigned char *txTo , unsigned int txToLen,
+ const UTXO *spentOutputs, unsigned int spentOutputsLen,
+ unsigned int nIn, unsigned int flags, namecoinconsensus_error* err);
+
EXPORT_SYMBOL unsigned int namecoinconsensus_version();
#ifdef __cplusplus
diff --git a/src/script/sign.cpp b/src/script/sign.cpp
index 83d74bc336..0244ec5f17 100644
--- a/src/script/sign.cpp
+++ b/src/script/sign.cpp
@@ -433,7 +433,7 @@ static bool SignStep(const SigningProvider& provider, const BaseSignatureCreator
case TxoutType::SCRIPTHASH: {
uint160 h160{vSolutions[0]};
if (GetCScript(provider, sigdata, CScriptID{h160}, scriptRet)) {
- ret.push_back(std::vector(scriptRet.begin(), scriptRet.end()));
+ ret.emplace_back(scriptRet.begin(), scriptRet.end());
return true;
}
// Could not find redeemScript, add to missing
@@ -442,7 +442,7 @@ static bool SignStep(const SigningProvider& provider, const BaseSignatureCreator
}
case TxoutType::MULTISIG: {
size_t required = vSolutions.front()[0];
- ret.push_back(valtype()); // workaround CHECKMULTISIG bug
+ ret.emplace_back(); // workaround CHECKMULTISIG bug
for (size_t i = 1; i < vSolutions.size() - 1; ++i) {
CPubKey pubkey = CPubKey(vSolutions[i]);
// We need to always call CreateSig in order to fill sigdata with all
@@ -456,7 +456,7 @@ static bool SignStep(const SigningProvider& provider, const BaseSignatureCreator
}
bool ok = ret.size() == required + 1;
for (size_t i = 0; i + ret.size() < required + 1; ++i) {
- ret.push_back(valtype());
+ ret.emplace_back();
}
return ok;
}
@@ -466,7 +466,7 @@ static bool SignStep(const SigningProvider& provider, const BaseSignatureCreator
case TxoutType::WITNESS_V0_SCRIPTHASH:
if (GetCScript(provider, sigdata, CScriptID{RIPEMD160(vSolutions[0])}, scriptRet)) {
- ret.push_back(std::vector(scriptRet.begin(), scriptRet.end()));
+ ret.emplace_back(scriptRet.begin(), scriptRet.end());
return true;
}
// Could not find witnessScript, add to missing
@@ -544,7 +544,7 @@ bool ProduceSignature(const SigningProvider& provider, const BaseSignatureCreato
const auto ms = miniscript::FromScript(witnessscript, ms_satisfier);
solved = ms && ms->Satisfy(ms_satisfier, result) == miniscript::Availability::YES;
}
- result.push_back(std::vector(witnessscript.begin(), witnessscript.end()));
+ result.emplace_back(witnessscript.begin(), witnessscript.end());
sigdata.scriptWitness.stack = result;
sigdata.witness = true;
@@ -561,7 +561,7 @@ bool ProduceSignature(const SigningProvider& provider, const BaseSignatureCreato
if (!sigdata.witness) sigdata.scriptWitness.stack.clear();
if (P2SH) {
- result.push_back(std::vector(subscript.begin(), subscript.end()));
+ result.emplace_back(subscript.begin(), subscript.end());
}
sigdata.scriptSig = PushAll(result);
diff --git a/src/script/signingprovider.cpp b/src/script/signingprovider.cpp
index 168b3030cc..ff02ab5a12 100644
--- a/src/script/signingprovider.cpp
+++ b/src/script/signingprovider.cpp
@@ -368,6 +368,8 @@ TaprootBuilder& TaprootBuilder::Add(int depth, Span script,
/* Construct NodeInfo object with leaf hash and (if track is true) also leaf information. */
NodeInfo node;
node.hash = ComputeTapleafHash(leaf_version, script);
+ // due to bug in clang-tidy-17:
+ // NOLINTNEXTLINE(modernize-use-emplace)
if (track) node.leaves.emplace_back(LeafInfo{std::vector(script.begin(), script.end()), leaf_version, {}});
/* Insert into the branch. */
Insert(std::move(node), depth);
@@ -569,7 +571,7 @@ std::vector>> TaprootBui
assert(leaf.merkle_branch.size() <= TAPROOT_CONTROL_MAX_NODE_COUNT);
uint8_t depth = (uint8_t)leaf.merkle_branch.size();
uint8_t leaf_ver = (uint8_t)leaf.leaf_version;
- tuples.push_back(std::make_tuple(depth, leaf_ver, leaf.script));
+ tuples.emplace_back(depth, leaf_ver, leaf.script);
}
}
return tuples;
diff --git a/src/test/addrman_tests.cpp b/src/test/addrman_tests.cpp
index b01ba81c5f..bfefc3ff97 100644
--- a/src/test/addrman_tests.cpp
+++ b/src/test/addrman_tests.cpp
@@ -98,8 +98,8 @@ BOOST_AUTO_TEST_CASE(addrman_simple)
// Test: reset addrman and test AddrMan::Add multiple addresses works as expected
addrman = std::make_unique(EMPTY_NETGROUPMAN, DETERMINISTIC, GetCheckRatio(m_node));
std::vector vAddr;
- vAddr.push_back(CAddress(ResolveService("250.1.1.3", 8333), NODE_NONE));
- vAddr.push_back(CAddress(ResolveService("250.1.1.4", 8333), NODE_NONE));
+ vAddr.emplace_back(ResolveService("250.1.1.3", 8333), NODE_NONE);
+ vAddr.emplace_back(ResolveService("250.1.1.4", 8333), NODE_NONE);
BOOST_CHECK(addrman->Add(vAddr, source));
BOOST_CHECK(addrman->Size() >= 1);
}
diff --git a/src/test/bip32_tests.cpp b/src/test/bip32_tests.cpp
index fe3d8995e9..cbbec94e00 100644
--- a/src/test/bip32_tests.cpp
+++ b/src/test/bip32_tests.cpp
@@ -29,7 +29,7 @@ struct TestVector {
explicit TestVector(std::string strHexMasterIn) : strHexMaster(strHexMasterIn) {}
TestVector& operator()(std::string pub, std::string prv, unsigned int nChild) {
- vDerive.push_back(TestDerivation());
+ vDerive.emplace_back();
TestDerivation &der = vDerive.back();
der.pub = pub;
der.prv = prv;
diff --git a/src/test/fuzz/i2p.cpp b/src/test/fuzz/i2p.cpp
deleted file mode 100644
index 943595f8a4..0000000000
--- a/src/test/fuzz/i2p.cpp
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright (c) 2020-2022 The Bitcoin Core developers
-// Distributed under the MIT software license, see the accompanying
-// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-void initialize_i2p()
-{
- static const auto testing_setup = MakeNoLogFileContext<>();
-}
-
-FUZZ_TARGET(i2p, .init = initialize_i2p)
-{
- FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
-
- // Mock CreateSock() to create FuzzedSock.
- auto CreateSockOrig = CreateSock;
- CreateSock = [&fuzzed_data_provider](const CService&) {
- return std::make_unique(fuzzed_data_provider);
- };
-
- const CService sam_proxy;
- CThreadInterrupt interrupt;
-
- i2p::sam::Session sess{gArgs.GetDataDirNet() / "fuzzed_i2p_private_key", sam_proxy, &interrupt};
-
- i2p::Connection conn;
-
- if (sess.Listen(conn)) {
- if (sess.Accept(conn)) {
- try {
- (void)conn.sock->RecvUntilTerminator('\n', 10ms, interrupt, i2p::sam::MAX_MSG_SIZE);
- } catch (const std::runtime_error&) {
- }
- }
- }
-
- const CService to;
- bool proxy_error;
-
- if (sess.Connect(to, conn, proxy_error)) {
- try {
- conn.sock->SendComplete("verack\n", 10ms, interrupt);
- } catch (const std::runtime_error&) {
- }
- }
-
- CreateSock = CreateSockOrig;
-}
diff --git a/src/test/fuzz/mini_miner.cpp b/src/test/fuzz/mini_miner.cpp
index e17e2bad60..2f53943c31 100644
--- a/src/test/fuzz/mini_miner.cpp
+++ b/src/test/fuzz/mini_miner.cpp
@@ -25,7 +25,7 @@ void initialize_miner()
static const auto testing_setup = MakeNoLogFileContext();
g_setup = testing_setup.get();
for (uint32_t i = 0; i < uint32_t{100}; ++i) {
- g_available_coins.push_back(COutPoint{uint256::ZERO, i});
+ g_available_coins.emplace_back(uint256::ZERO, i);
}
}
@@ -45,11 +45,11 @@ FUZZ_TARGET(mini_miner, .init = initialize_miner)
const size_t num_outputs = fuzzed_data_provider.ConsumeIntegralInRange(1, 50);
for (size_t n{0}; n < num_inputs; ++n) {
auto prevout = available_coins.front();
- mtx.vin.push_back(CTxIn(prevout, CScript()));
+ mtx.vin.emplace_back(prevout, CScript());
available_coins.pop_front();
}
for (uint32_t n{0}; n < num_outputs; ++n) {
- mtx.vout.push_back(CTxOut(100, P2WSH_OP_TRUE));
+ mtx.vout.emplace_back(100, P2WSH_OP_TRUE);
}
CTransactionRef tx = MakeTransactionRef(mtx);
TestMemPoolEntryHelper entry;
@@ -60,14 +60,14 @@ FUZZ_TARGET(mini_miner, .init = initialize_miner)
// All outputs are available to spend
for (uint32_t n{0}; n < num_outputs; ++n) {
if (fuzzed_data_provider.ConsumeBool()) {
- available_coins.push_back(COutPoint{tx->GetHash(), n});
+ available_coins.emplace_back(tx->GetHash(), n);
}
}
if (fuzzed_data_provider.ConsumeBool() && !tx->vout.empty()) {
// Add outpoint from this tx (may or not be spent by a later tx)
- outpoints.push_back(COutPoint{tx->GetHash(),
- (uint32_t)fuzzed_data_provider.ConsumeIntegralInRange(0, tx->vout.size())});
+ outpoints.emplace_back(tx->GetHash(),
+ (uint32_t)fuzzed_data_provider.ConsumeIntegralInRange(0, tx->vout.size()));
} else {
// Add some random outpoint (will be interpreted as confirmed or not yet submitted
// to mempool).
@@ -123,11 +123,11 @@ FUZZ_TARGET(mini_miner_selection, .init = initialize_miner)
const size_t num_outputs = fuzzed_data_provider.ConsumeIntegralInRange(2, 5);
for (size_t n{0}; n < num_inputs; ++n) {
auto prevout = available_coins.at(0);
- mtx.vin.push_back(CTxIn(prevout, CScript()));
+ mtx.vin.emplace_back(prevout, CScript());
available_coins.pop_front();
}
for (uint32_t n{0}; n < num_outputs; ++n) {
- mtx.vout.push_back(CTxOut(100, P2WSH_OP_TRUE));
+ mtx.vout.emplace_back(100, P2WSH_OP_TRUE);
}
CTransactionRef tx = MakeTransactionRef(mtx);
@@ -136,9 +136,9 @@ FUZZ_TARGET(mini_miner_selection, .init = initialize_miner)
// MiniMiner interprets spent coins as to-be-replaced and excludes them.
for (uint32_t n{0}; n < num_outputs - 1; ++n) {
if (fuzzed_data_provider.ConsumeBool()) {
- available_coins.push_front(COutPoint{tx->GetHash(), n});
+ available_coins.emplace_front(tx->GetHash(), n);
} else {
- available_coins.push_back(COutPoint{tx->GetHash(), n});
+ available_coins.emplace_back(tx->GetHash(), n);
}
}
diff --git a/src/test/fuzz/miniscript.cpp b/src/test/fuzz/miniscript.cpp
index 4d054d7458..8c73edfa9d 100644
--- a/src/test/fuzz/miniscript.cpp
+++ b/src/test/fuzz/miniscript.cpp
@@ -70,6 +70,7 @@ struct TestData {
sig.push_back(1); // SIGHASH_ALL
dummy_sigs.insert({pubkey, {sig, i & 1}});
assert(privkey.SignSchnorr(MESSAGE_HASH, schnorr_sig, nullptr, EMPTY_AUX));
+ schnorr_sig.push_back(1); // Maximally-sized signature has sighash byte
schnorr_sigs.emplace(XOnlyPubKey{pubkey}, std::make_pair(std::move(schnorr_sig), i & 1));
std::vector hash;
@@ -113,7 +114,9 @@ struct TestData {
struct ParserContext {
typedef CPubKey Key;
- MsCtx script_ctx{MsCtx::P2WSH};
+ const MsCtx script_ctx;
+
+ constexpr ParserContext(MsCtx ctx) noexcept : script_ctx(ctx) {}
bool KeyCompare(const Key& a, const Key& b) const {
return a < b;
@@ -178,11 +181,13 @@ struct ParserContext {
MsCtx MsContext() const {
return script_ctx;
}
-} PARSER_CTX;
+};
//! Context that implements naive conversion from/to script only, for roundtrip testing.
struct ScriptParserContext {
- MsCtx script_ctx{MsCtx::P2WSH};
+ const MsCtx script_ctx;
+
+ constexpr ScriptParserContext(MsCtx ctx) noexcept : script_ctx(ctx) {}
//! For Script roundtrip we never need the key from a key hash.
struct Key {
@@ -228,10 +233,13 @@ struct ScriptParserContext {
MsCtx MsContext() const {
return script_ctx;
}
-} SCRIPT_PARSER_CONTEXT;
+};
//! Context to produce a satisfaction for a Miniscript node using the pre-computed data.
-struct SatisfierContext: ParserContext {
+struct SatisfierContext : ParserContext {
+
+ constexpr SatisfierContext(MsCtx ctx) noexcept : ParserContext(ctx) {}
+
// Timelock challenges satisfaction. Make the value (deterministically) vary to explore different
// paths.
bool CheckAfter(uint32_t value) const { return value % 2; }
@@ -267,12 +275,10 @@ struct SatisfierContext: ParserContext {
miniscript::Availability SatHASH160(const std::vector& hash, std::vector& preimage) const {
return LookupHash(hash, preimage, TEST_DATA.hash160_preimages);
}
-} SATISFIER_CTX;
+};
//! Context to check a satisfaction against the pre-computed data.
-struct CheckerContext: BaseSignatureChecker {
- TestData *test_data;
-
+const struct CheckerContext: BaseSignatureChecker {
// Signature checker methods. Checks the right dummy signature is used.
bool CheckECDSASignature(const std::vector& sig, const std::vector& vchPubKey,
const CScript& scriptCode, SigVersion sigversion) const override
@@ -294,7 +300,7 @@ struct CheckerContext: BaseSignatureChecker {
} CHECKER_CTX;
//! Context to check for duplicates when instancing a Node.
-struct KeyComparator {
+const struct KeyComparator {
bool KeyCompare(const CPubKey& a, const CPubKey& b) const {
return a < b;
}
@@ -1015,7 +1021,7 @@ CScript ScriptPubKey(MsCtx ctx, const CScript& script, TaprootBuilder& builder)
//! Fill the witness with the data additional to the script satisfaction.
void SatisfactionToWitness(MsCtx ctx, CScriptWitness& witness, const CScript& script, TaprootBuilder& builder) {
// For P2WSH, it's only the witness script.
- witness.stack.push_back(std::vector(script.begin(), script.end()));
+ witness.stack.emplace_back(script.begin(), script.end());
if (!miniscript::IsTapscript(ctx)) return;
// For Tapscript we also need the control block.
witness.stack.push_back(*builder.GetSpendData().scripts.begin()->second.begin());
@@ -1027,15 +1033,15 @@ void TestNode(const MsCtx script_ctx, const NodeRef& node, FuzzedDataProvider& p
if (!node) return;
// Check that it roundtrips to text representation
- PARSER_CTX.script_ctx = script_ctx;
- std::optional str{node->ToString(PARSER_CTX)};
+ const ParserContext parser_ctx{script_ctx};
+ std::optional str{node->ToString(parser_ctx)};
assert(str);
- auto parsed = miniscript::FromString(*str, PARSER_CTX);
+ auto parsed = miniscript::FromString(*str, parser_ctx);
assert(parsed);
assert(*parsed == *node);
// Check consistency between script size estimation and real size.
- auto script = node->ToScript(PARSER_CTX);
+ auto script = node->ToScript(parser_ctx);
assert(node->ScriptSize() == script.size());
// Check consistency of "x" property with the script (type K is excluded, because it can end
@@ -1049,12 +1055,12 @@ void TestNode(const MsCtx script_ctx, const NodeRef& node, FuzzedDataProvider& p
if (!node->IsValidTopLevel()) return;
// Check roundtrip to script
- auto decoded = miniscript::FromScript(script, PARSER_CTX);
+ auto decoded = miniscript::FromScript(script, parser_ctx);
assert(decoded);
// Note we can't use *decoded == *node because the miniscript representation may differ, so we check that:
// - The script corresponding to that decoded form matches exactly
// - The type matches exactly
- assert(decoded->ToScript(PARSER_CTX) == script);
+ assert(decoded->ToScript(parser_ctx) == script);
assert(decoded->GetType() == node->GetType());
// Optionally pad the script or the witness in order to increase the sensitivity of the tests of
@@ -1091,7 +1097,7 @@ void TestNode(const MsCtx script_ctx, const NodeRef& node, FuzzedDataProvider& p
}
}
- SATISFIER_CTX.script_ctx = script_ctx;
+ const SatisfierContext satisfier_ctx{script_ctx};
// Get the ScriptPubKey for this script, filling spend data if it's Taproot.
TaprootBuilder builder;
@@ -1099,11 +1105,11 @@ void TestNode(const MsCtx script_ctx, const NodeRef& node, FuzzedDataProvider& p
// Run malleable satisfaction algorithm.
std::vector> stack_mal;
- const bool mal_success = node->Satisfy(SATISFIER_CTX, stack_mal, false) == miniscript::Availability::YES;
+ const bool mal_success = node->Satisfy(satisfier_ctx, stack_mal, false) == miniscript::Availability::YES;
// Run non-malleable satisfaction algorithm.
std::vector> stack_nonmal;
- const bool nonmal_success = node->Satisfy(SATISFIER_CTX, stack_nonmal, true) == miniscript::Availability::YES;
+ const bool nonmal_success = node->Satisfy(satisfier_ctx, stack_nonmal, true) == miniscript::Availability::YES;
if (nonmal_success) {
// Non-malleable satisfactions are bounded by the satisfaction size plus:
@@ -1114,6 +1120,9 @@ void TestNode(const MsCtx script_ctx, const NodeRef& node, FuzzedDataProvider& p
// If a non-malleable satisfaction exists, the malleable one must also exist, and be identical to it.
assert(mal_success);
assert(stack_nonmal == stack_mal);
+ // Compute witness size (excluding script push, control block, and witness count encoding).
+ const size_t wit_size = GetSerializeSize(stack_nonmal, PROTOCOL_VERSION) - GetSizeOfCompactSize(stack_nonmal.size());
+ assert(wit_size <= *node->GetWitnessSize());
// Test non-malleable satisfaction.
witness_nonmal.stack.insert(witness_nonmal.stack.end(), std::make_move_iterator(stack_nonmal.begin()), std::make_move_iterator(stack_nonmal.end()));
@@ -1229,13 +1238,13 @@ FUZZ_TARGET(miniscript_string, .init = FuzzInit)
if (buffer.empty()) return;
FuzzedDataProvider provider(buffer.data(), buffer.size());
auto str = provider.ConsumeBytesAsString(provider.remaining_bytes() - 1);
- PARSER_CTX.script_ctx = (MsCtx)provider.ConsumeBool();
- auto parsed = miniscript::FromString(str, PARSER_CTX);
+ const ParserContext parser_ctx{(MsCtx)provider.ConsumeBool()};
+ auto parsed = miniscript::FromString(str, parser_ctx);
if (!parsed) return;
- const auto str2 = parsed->ToString(PARSER_CTX);
+ const auto str2 = parsed->ToString(parser_ctx);
assert(str2);
- auto parsed2 = miniscript::FromString(*str2, PARSER_CTX);
+ auto parsed2 = miniscript::FromString(*str2, parser_ctx);
assert(parsed2);
assert(*parsed == *parsed2);
}
@@ -1247,9 +1256,9 @@ FUZZ_TARGET(miniscript_script)
const std::optional script = ConsumeDeserializable(fuzzed_data_provider);
if (!script) return;
- SCRIPT_PARSER_CONTEXT.script_ctx = (MsCtx)fuzzed_data_provider.ConsumeBool();
- const auto ms = miniscript::FromScript(*script, SCRIPT_PARSER_CONTEXT);
+ const ScriptParserContext script_parser_ctx{(MsCtx)fuzzed_data_provider.ConsumeBool()};
+ const auto ms = miniscript::FromScript(*script, script_parser_ctx);
if (!ms) return;
- assert(ms->ToScript(SCRIPT_PARSER_CONTEXT) == *script);
+ assert(ms->ToScript(script_parser_ctx) == *script);
}
diff --git a/src/test/fuzz/script_bitcoin_consensus.cpp b/src/test/fuzz/script_bitcoin_consensus.cpp
index 499b28db3d..c7956fdf53 100644
--- a/src/test/fuzz/script_bitcoin_consensus.cpp
+++ b/src/test/fuzz/script_bitcoin_consensus.cpp
@@ -28,4 +28,23 @@ FUZZ_TARGET(script_bitcoin_consensus)
}
(void)namecoinconsensus_verify_script(random_bytes_1.data(), random_bytes_1.size(), random_bytes_2.data(), random_bytes_2.size(), n_in, flags, err_p);
(void)namecoinconsensus_verify_script_with_amount(random_bytes_1.data(), random_bytes_1.size(), money, random_bytes_2.data(), random_bytes_2.size(), n_in, flags, err_p);
+
+ std::vector spent_outputs;
+ std::vector> spent_spks;
+ if (n_in <= 24386) {
+ spent_outputs.reserve(n_in);
+ spent_spks.reserve(n_in);
+ for (size_t i = 0; i < n_in; ++i) {
+ spent_spks.push_back(ConsumeRandomLengthByteVector(fuzzed_data_provider));
+ const CAmount value{ConsumeMoney(fuzzed_data_provider)};
+ const auto spk_size{static_cast(spent_spks.back().size())};
+ spent_outputs.push_back({.scriptPubKey = spent_spks.back().data(), .scriptPubKeySize = spk_size, .value = value});
+ }
+ }
+
+ const auto spent_outs_size{static_cast(spent_outputs.size())};
+
+ (void)namecoinconsensus_verify_script_with_spent_outputs(
+ random_bytes_1.data(), random_bytes_1.size(), money, random_bytes_2.data(), random_bytes_2.size(),
+ spent_outputs.data(), spent_outs_size, n_in, flags, err_p);
}
diff --git a/src/test/fuzz/util/net.cpp b/src/test/fuzz/util/net.cpp
index d23e997719..5a286c05d2 100644
--- a/src/test/fuzz/util/net.cpp
+++ b/src/test/fuzz/util/net.cpp
@@ -36,7 +36,11 @@ CNetAddr ConsumeNetAddr(FuzzedDataProvider& fuzzed_data_provider) noexcept
} else if (network == Network::NET_IPV6) {
if (fuzzed_data_provider.remaining_bytes() >= 16) {
in6_addr v6_addr = {};
- memcpy(v6_addr.s6_addr, fuzzed_data_provider.ConsumeBytes(16).data(), 16);
+ auto addr_bytes = fuzzed_data_provider.ConsumeBytes(16);
+ if (addr_bytes[0] == CJDNS_PREFIX) { // Avoid generating IPv6 addresses that look like CJDNS.
+ addr_bytes[0] = 0x55; // Just an arbitrary number, anything != CJDNS_PREFIX would do.
+ }
+ memcpy(v6_addr.s6_addr, addr_bytes.data(), 16);
net_addr = CNetAddr{v6_addr, fuzzed_data_provider.ConsumeIntegral()};
}
} else if (network == Network::NET_INTERNAL) {
diff --git a/src/test/headers_sync_chainwork_tests.cpp b/src/test/headers_sync_chainwork_tests.cpp
index 41241ebee2..b710ad1801 100644
--- a/src/test/headers_sync_chainwork_tests.cpp
+++ b/src/test/headers_sync_chainwork_tests.cpp
@@ -40,7 +40,7 @@ void HeadersGeneratorSetup::GenerateHeaders(std::vector& headers,
uint256 prev_hash = starting_hash;
while (headers.size() < count) {
- headers.push_back(CBlockHeader());
+ headers.emplace_back();
CBlockHeader& next_header = headers.back();;
next_header.nVersion = nVersion;
next_header.hashPrevBlock = prev_hash;
diff --git a/src/test/i2p_tests.cpp b/src/test/i2p_tests.cpp
index b2e1ae43be..5b8b0e9215 100644
--- a/src/test/i2p_tests.cpp
+++ b/src/test/i2p_tests.cpp
@@ -16,14 +16,34 @@
#include
#include
-BOOST_FIXTURE_TEST_SUITE(i2p_tests, BasicTestingSetup)
+/// Save the log level and the value of CreateSock and restore them when the test ends.
+class EnvTestingSetup : public BasicTestingSetup
+{
+public:
+ explicit EnvTestingSetup(const ChainType chainType = ChainType::MAIN,
+ const std::vector& extra_args = {})
+ : BasicTestingSetup{chainType, extra_args},
+ m_prev_log_level{LogInstance().LogLevel()},
+ m_create_sock_orig{CreateSock}
+ {
+ LogInstance().SetLogLevel(BCLog::Level::Trace);
+ }
+
+ ~EnvTestingSetup()
+ {
+ CreateSock = m_create_sock_orig;
+ LogInstance().SetLogLevel(m_prev_log_level);
+ }
+
+private:
+ const BCLog::Level m_prev_log_level;
+ const std::function(const CService&)> m_create_sock_orig;
+};
+
+BOOST_FIXTURE_TEST_SUITE(i2p_tests, EnvTestingSetup)
BOOST_AUTO_TEST_CASE(unlimited_recv)
{
- const auto prev_log_level{LogInstance().LogLevel()};
- LogInstance().SetLogLevel(BCLog::Level::Trace);
- auto CreateSockOrig = CreateSock;
-
// Mock CreateSock() to create MockSock.
CreateSock = [](const CService&) {
return std::make_unique(std::string(i2p::sam::MAX_MSG_SIZE + 1, 'a'));
@@ -40,9 +60,69 @@ BOOST_AUTO_TEST_CASE(unlimited_recv)
bool proxy_error;
BOOST_REQUIRE(!session.Connect(CService{}, conn, proxy_error));
}
+}
+
+BOOST_AUTO_TEST_CASE(listen_ok_accept_fail)
+{
+ size_t num_sockets{0};
+ CreateSock = [&num_sockets](const CService&) {
+ // clang-format off
+ ++num_sockets;
+ // First socket is the control socket for creating the session.
+ if (num_sockets == 1) {
+ return std::make_unique(
+ // reply to HELLO
+ "HELLO REPLY RESULT=OK VERSION=3.1\n"
+ // reply to DEST GENERATE
+ "DEST REPLY PUB=WnGOLXRBqHQhdVjFlWqRxJwz9hxx~2~wGc2Vplta1KhacY4tdEGodCF1WMWVapHEnDP2HHH~b~AZzZWmW1rUqFpxji10Qah0IXVYxZVqkcScM~Yccf9v8BnNlaZbWtSoWnGOLXRBqHQhdVjFlWqRxJwz9hxx~2~wGc2Vplta1KhacY4tdEGodCF1WMWVapHEnDP2HHH~b~AZzZWmW1rUqFpxji10Qah0IXVYxZVqkcScM~Yccf9v8BnNlaZbWtSoWnGOLXRBqHQhdVjFlWqRxJwz9hxx~2~wGc2Vplta1KhacY4tdEGodCF1WMWVapHEnDP2HHH~b~AZzZWmW1rUqFpxji10Qah0IXVYxZVqkcScM~Yccf9v8BnNlaZbWtSoWnGOLXRBqHQhdVjFlWqRxJwz9hxx~2~wGc2Vplta1KhacY4tdEGodCF1WMWVapHEnDP2HHH~b~AZzZWmW1rUqLE4SD-yjT48UNI7qiTUfIPiDitCoiTTz2cr4QGfw89rBQAEAAcAAA== PRIV=WnGOLXRBqHQhdVjFlWqRxJwz9hxx~2~wGc2Vplta1KhacY4tdEGodCF1WMWVapHEnDP2HHH~b~AZzZWmW1rUqFpxji10Qah0IXVYxZVqkcScM~Yccf9v8BnNlaZbWtSoWnGOLXRBqHQhdVjFlWqRxJwz9hxx~2~wGc2Vplta1KhacY4tdEGodCF1WMWVapHEnDP2HHH~b~AZzZWmW1rUqFpxji10Qah0IXVYxZVqkcScM~Yccf9v8BnNlaZbWtSoWnGOLXRBqHQhdVjFlWqRxJwz9hxx~2~wGc2Vplta1KhacY4tdEGodCF1WMWVapHEnDP2HHH~b~AZzZWmW1rUqFpxji10Qah0IXVYxZVqkcScM~Yccf9v8BnNlaZbWtSoWnGOLXRBqHQhdVjFlWqRxJwz9hxx~2~wGc2Vplta1KhacY4tdEGodCF1WMWVapHEnDP2HHH~b~AZzZWmW1rUqLE4SD-yjT48UNI7qiTUfIPiDitCoiTTz2cr4QGfw89rBQAEAAcAAOvuCIKTyv5f~1QgGq7XQl-IqBULTB5WzB3gw5yGPtd1p0AeoADrq1ccZggLPQ4ZLUsGK-HVw373rcTfvxrcuwenqVjiN4tbbYLWtP7xXGWj6fM6HyORhU63GphrjEePpMUHDHXd3o7pWGM-ieVVQSK~1MzF9P93pQWI3Do52EeNAayz4HbpPjNhVBzG1hUEFwznfPmUZBPuaOR4-uBm1NEWEuONlNOCctE4-U0Ukh94z-Qb55U5vXjR5G4apmBblr68t6Wm1TKlzpgFHzSqLryh3stWqrOKY1H0z9eZ2z1EkHFOpD5LyF6nf51e-lV7HLMl44TYzoEHK8RRVodtLcW9lacVdBpv~tOzlZERIiDziZODPETENZMz5oy9DQ7UUw==\n"
+ // reply to SESSION CREATE
+ "SESSION STATUS RESULT=OK\n"
+ // dummy to avoid reporting EOF on the socket
+ "a"
+ );
+ }
+ // Subsequent sockets are for recreating the session or for listening and accepting incoming connections.
+ if (num_sockets % 2 == 0) {
+ // Replies to Listen() and Accept()
+ return std::make_unique(
+ // reply to HELLO
+ "HELLO REPLY RESULT=OK VERSION=3.1\n"
+ // reply to STREAM ACCEPT
+ "STREAM STATUS RESULT=OK\n"
+ // continued reply to STREAM ACCEPT, violating the protocol described at
+ // https://geti2p.net/en/docs/api/samv3#Accept%20Response
+ // should be base64, something like
+ // "IchV608baDoXbqzQKSqFDmTXPVgoDbPAhZJvNRXXxi4hyFXrTxtoOhdurNApKoUOZNc9WCgNs8CFkm81FdfGLiHIVetPG2g6F26s0CkqhQ5k1z1YKA2zwIWSbzUV18YuIchV608baDoXbqzQKSqFDmTXPVgoDbPAhZJvNRXXxi4hyFXrTxtoOhdurNApKoUOZNc9WCgNs8CFkm81FdfGLiHIVetPG2g6F26s0CkqhQ5k1z1YKA2zwIWSbzUV18YuIchV608baDoXbqzQKSqFDmTXPVgoDbPAhZJvNRXXxi4hyFXrTxtoOhdurNApKoUOZNc9WCgNs8CFkm81FdfGLiHIVetPG2g6F26s0CkqhQ5k1z1YKA2zwIWSbzUV18YuIchV608baDoXbqzQKSqFDmTXPVgoDbPAhZJvNRXXxi4hyFXrTxtoOhdurNApKoUOZNc9WCgNs8CFkm81FdfGLlSreVaCuCS5sdb-8ToWULWP7kt~lRPDeUNxQMq3cRSBBQAEAAcAAA==\n"
+ "STREAM STATUS RESULT=I2P_ERROR MESSAGE=\"Session was closed\"\n"
+ );
+ } else {
+ // Another control socket, but without creating a destination (it is cached in the session).
+ return std::make_unique(
+ // reply to HELLO
+ "HELLO REPLY RESULT=OK VERSION=3.1\n"
+ // reply to SESSION CREATE
+ "SESSION STATUS RESULT=OK\n"
+ // dummy to avoid reporting EOF on the socket
+ "a"
+ );
+ }
+ // clang-format on
+ };
- CreateSock = CreateSockOrig;
- LogInstance().SetLogLevel(prev_log_level);
+ CThreadInterrupt interrupt;
+ i2p::sam::Session session(gArgs.GetDataDirNet() / "test_i2p_private_key",
+ CService{in6_addr(IN6ADDR_LOOPBACK_INIT), /*port=*/7656},
+ &interrupt);
+
+ i2p::Connection conn;
+ for (size_t i = 0; i < 5; ++i) {
+ ASSERT_DEBUG_LOG("Creating persistent SAM session");
+ ASSERT_DEBUG_LOG("Persistent SAM session" /* ... created */);
+ ASSERT_DEBUG_LOG("Error accepting");
+ ASSERT_DEBUG_LOG("Destroying SAM session");
+ BOOST_REQUIRE(session.Listen(conn));
+ BOOST_REQUIRE(!session.Accept(conn));
+ }
}
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/miniscript_tests.cpp b/src/test/miniscript_tests.cpp
index c8a39076e2..996c379962 100644
--- a/src/test/miniscript_tests.cpp
+++ b/src/test/miniscript_tests.cpp
@@ -77,6 +77,7 @@ struct TestData {
sig.push_back(1); // sighash byte
signatures.emplace(pubkey, sig);
BOOST_CHECK(key.SignSchnorr(MESSAGE_HASH, schnorr_sig, nullptr, EMPTY_AUX));
+ schnorr_sig.push_back(1); // Maximally sized Schnorr sigs have a sighash byte.
schnorr_signatures.emplace(XOnlyPubKey{pubkey}, schnorr_sig);
// Compute various hashes
@@ -126,7 +127,9 @@ typedef std::pair Challenge;
struct KeyConverter {
typedef CPubKey Key;
- miniscript::MiniscriptContext m_script_ctx{miniscript::MiniscriptContext::P2WSH};
+ const miniscript::MiniscriptContext m_script_ctx;
+
+ constexpr KeyConverter(miniscript::MiniscriptContext ctx) noexcept : m_script_ctx{ctx} {}
bool KeyCompare(const Key& a, const Key& b) const {
return a < b;
@@ -189,14 +192,13 @@ struct KeyConverter {
miniscript::MiniscriptContext MsContext() const {
return m_script_ctx;
}
-
- void SetContext(miniscript::MiniscriptContext ctx) {
- m_script_ctx = ctx;
- }
};
/** A class that encapsulates all signing/hash revealing operations. */
struct Satisfier : public KeyConverter {
+
+ Satisfier(miniscript::MiniscriptContext ctx) noexcept : KeyConverter{ctx} {}
+
//! Which keys/timelocks/hash preimages are available.
std::set supported;
@@ -286,9 +288,6 @@ class TestSignatureChecker : public BaseSignatureChecker {
}
};
-//! Singleton instance of KeyConverter.
-KeyConverter CONVERTER;
-
//! Public key to be used as internal key for dummy Taproot spends.
const std::vector NUMS_PK{ParseHex("50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0")};
@@ -337,7 +336,7 @@ CScript ScriptPubKey(miniscript::MiniscriptContext ctx, const CScript& script, T
//! Fill the witness with the data additional to the script satisfaction.
void SatisfactionToWitness(miniscript::MiniscriptContext ctx, CScriptWitness& witness, const CScript& script, TaprootBuilder& builder) {
// For P2WSH, it's only the witness script.
- witness.stack.push_back(std::vector(script.begin(), script.end()));
+ witness.stack.emplace_back(script.begin(), script.end());
if (!miniscript::IsTapscript(ctx)) return;
// For Tapscript we also need the control block.
witness.stack.push_back(*builder.GetSpendData().scripts.begin()->second.begin());
@@ -350,8 +349,7 @@ void TestSatisfy(const KeyConverter& converter, const std::string& testcase, con
std::vector challist(challenges.begin(), challenges.end());
for (int iter = 0; iter < 3; ++iter) {
Shuffle(challist.begin(), challist.end(), g_insecure_rand_ctx);
- Satisfier satisfier;
- satisfier.SetContext(converter.MsContext());
+ Satisfier satisfier(converter.MsContext());
TestSignatureChecker checker(satisfier);
bool prev_mal_success = false, prev_nonmal_success = false;
// Go over all challenges involved in this miniscript in random order.
@@ -370,6 +368,8 @@ void TestSatisfy(const KeyConverter& converter, const std::string& testcase, con
// Run non-malleable satisfaction algorithm.
CScriptWitness witness_nonmal;
const bool nonmal_success = node->Satisfy(satisfier, witness_nonmal.stack, true) == miniscript::Availability::YES;
+ // Compute witness size (excluding script push, control block, and witness count encoding).
+ const size_t wit_size = GetSerializeSize(witness_nonmal.stack, PROTOCOL_VERSION) - GetSizeOfCompactSize(witness_nonmal.stack.size());
SatisfactionToWitness(converter.MsContext(), witness_nonmal, script, builder);
if (nonmal_success) {
@@ -381,6 +381,7 @@ void TestSatisfy(const KeyConverter& converter, const std::string& testcase, con
// If a non-malleable satisfaction exists, the malleable one must also exist, and be identical to it.
BOOST_CHECK(mal_success);
BOOST_CHECK(witness_nonmal.stack == witness_mal.stack);
+ assert(wit_size <= *node->GetWitnessSize());
// Test non-malleable satisfaction.
ScriptError serror;
@@ -473,14 +474,23 @@ void Test(const std::string& ms, const std::string& hexscript, int mode, const K
}
void Test(const std::string& ms, const std::string& hexscript, const std::string& hextapscript, int mode,
- int opslimit = -1, int stacklimit = -1, std::optional max_wit_size = std::nullopt,
- std::optional stack_exec = {})
+ int opslimit, int stacklimit, std::optional max_wit_size,
+ std::optional max_tap_wit_size,
+ std::optional stack_exec)
+{
+ KeyConverter wsh_converter(miniscript::MiniscriptContext::P2WSH);
+ Test(ms, hexscript, mode, wsh_converter, opslimit, stacklimit, max_wit_size, stack_exec);
+ KeyConverter tap_converter(miniscript::MiniscriptContext::TAPSCRIPT);
+ Test(ms, hextapscript == "=" ? hexscript : hextapscript, mode, tap_converter, opslimit, stacklimit, max_tap_wit_size, stack_exec);
+}
+
+void Test(const std::string& ms, const std::string& hexscript, const std::string& hextapscript, int mode)
{
- CONVERTER.SetContext(miniscript::MiniscriptContext::P2WSH);
- Test(ms, hexscript, mode, CONVERTER, opslimit, stacklimit, max_wit_size, stack_exec);
- CONVERTER.SetContext(miniscript::MiniscriptContext::TAPSCRIPT);
- Test(ms, hextapscript == "=" ? hexscript : hextapscript, mode, CONVERTER, opslimit, stacklimit, max_wit_size, stack_exec);
+ Test(ms, hexscript, hextapscript, mode,
+ /*opslimit=*/-1, /*stacklimit=*/-1,
+ /*max_wit_size=*/std::nullopt, /*max_tap_wit_size=*/std::nullopt, /*stack_exec=*/std::nullopt);
}
+
} // namespace
BOOST_FIXTURE_TEST_SUITE(miniscript_tests, BasicTestingSetup)
@@ -545,53 +555,54 @@ BOOST_AUTO_TEST_CASE(fixed_tests)
Test("pk(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65)", "2103d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65ac", "20d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65ac", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG); // alias to c:pk_k
Test("pkh(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65)", "76a914fcd35ddacad9f2d5be5e464639441c6065e6955d88ac", "76a914fd1690c37fa3b0f04395ddc9415b220ab1ccc59588ac", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG); // alias to c:pk_h
-
// Randomly generated test set that covers the majority of type and node type combinations
- Test("lltvln:after(1231488000)", "6300676300676300670400046749b1926869516868", "=", TESTMODE_VALID | TESTMODE_NONMAL, 12, 3, 3, 3);
- Test("uuj:and_v(v:multi(2,03d01115d548e7561b15c38f004d734633687cf4419620095bc5b0f47070afe85a,025601570cb47f238d2b0286db4a990fa0f3ba28d1a319f5e7cf55c2a2444da7cc),after(1231488000))", "6363829263522103d01115d548e7561b15c38f004d734633687cf4419620095bc5b0f47070afe85a21025601570cb47f238d2b0286db4a990fa0f3ba28d1a319f5e7cf55c2a2444da7cc52af0400046749b168670068670068", "?", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG | TESTMODE_TAPSCRIPT_INVALID, 14, 5, 2 + 2 + 1 + 2 * 73, 7);
- Test("or_b(un:multi(2,03daed4f2be3a8bf278e70132fb0beb7522f570e144bf615c07e996d443dee8729,024ce119c96e2fa357200b559b2f7dd5a5f02d5290aff74b03f3e471b273211c97),al:older(16))", "63522103daed4f2be3a8bf278e70132fb0beb7522f570e144bf615c07e996d443dee872921024ce119c96e2fa357200b559b2f7dd5a5f02d5290aff74b03f3e471b273211c9752ae926700686b63006760b2686c9b", "?", TESTMODE_VALID | TESTMODE_TAPSCRIPT_INVALID, 14, 5, 2 + 1 + 2 * 73 + 2, 8);
- Test("j:and_v(vdv:after(1567547623),older(2016))", "829263766304e7e06e5db169686902e007b268", "=", TESTMODE_VALID | TESTMODE_NONMAL, 11, 1, 2, 2);
- Test("t:and_v(vu:hash256(131772552c01444cd81360818376a040b7c3b2b7b0a53550ee3edde216cec61b),v:sha256(ec4916dd28fc4c10d78e287ca5d9cc51ee1ae73cbfde08c6b37324cbfaac8bc5))", "6382012088aa20131772552c01444cd81360818376a040b7c3b2b7b0a53550ee3edde216cec61b876700686982012088a820ec4916dd28fc4c10d78e287ca5d9cc51ee1ae73cbfde08c6b37324cbfaac8bc58851", "6382012088aa20131772552c01444cd81360818376a040b7c3b2b7b0a53550ee3edde216cec61b876700686982012088a820ec4916dd28fc4c10d78e287ca5d9cc51ee1ae73cbfde08c6b37324cbfaac8bc58851", TESTMODE_VALID | TESTMODE_NONMAL, 12, 3, 2 + 33 + 33, 4);
- Test("t:andor(multi(3,02d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e,03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556,02e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13),v:older(4194305),v:sha256(9267d3dbed802941483f1afa2a6bc68de5f653128aca9bf1461c5d0a3ad36ed2))", "532102d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e2103fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a14602975562102e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd1353ae6482012088a8209267d3dbed802941483f1afa2a6bc68de5f653128aca9bf1461c5d0a3ad36ed2886703010040b2696851", "?", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_TAPSCRIPT_INVALID, 13, 5, 1 + 3 * 73, 10);
- Test("or_d(multi(1,02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9),or_b(multi(3,022f01e5e15cca351daff3843fb70f3c2f0a1bdd05e5af888a67784ef3e10a2a01,032fa2104d6b38d11b0230010559879124e42ab8dfeff5ff29dc9cdadd4ecacc3f,03d01115d548e7561b15c38f004d734633687cf4419620095bc5b0f47070afe85a),su:after(500000)))", "512102f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f951ae73645321022f01e5e15cca351daff3843fb70f3c2f0a1bdd05e5af888a67784ef3e10a2a0121032fa2104d6b38d11b0230010559879124e42ab8dfeff5ff29dc9cdadd4ecacc3f2103d01115d548e7561b15c38f004d734633687cf4419620095bc5b0f47070afe85a53ae7c630320a107b16700689b68", "?", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_TAPSCRIPT_INVALID, 15, 7, 2 + 1 + 3 * 73 + 1, 10);
- Test("or_d(sha256(38df1c1f64a24a77b23393bca50dff872e31edc4f3b5aa3b90ad0b82f4f089b6),and_n(un:after(499999999),older(4194305)))", "82012088a82038df1c1f64a24a77b23393bca50dff872e31edc4f3b5aa3b90ad0b82f4f089b68773646304ff64cd1db19267006864006703010040b26868", "82012088a82038df1c1f64a24a77b23393bca50dff872e31edc4f3b5aa3b90ad0b82f4f089b68773646304ff64cd1db19267006864006703010040b26868", TESTMODE_VALID, 16, 1, 33, 3);
- Test("and_v(or_i(v:multi(2,02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5,03774ae7f858a9411e5ef4246b70c65aac5649980be5c17891bbec17895da008cb),v:multi(2,03e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a,025cbdf0646e5db4eaa398f365f2ea7a0e3d419b7e0330e39ce92bddedcac4f9bc)),sha256(d1ec675902ef1633427ca360b290b0b3045a0d9058ddb5e648b4c3c3224c5c68))", "63522102c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee52103774ae7f858a9411e5ef4246b70c65aac5649980be5c17891bbec17895da008cb52af67522103e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a21025cbdf0646e5db4eaa398f365f2ea7a0e3d419b7e0330e39ce92bddedcac4f9bc52af6882012088a820d1ec675902ef1633427ca360b290b0b3045a0d9058ddb5e648b4c3c3224c5c6887", "?", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG | TESTMODE_TAPSCRIPT_INVALID, 11, 5, 2 + 1 + 2 * 73 + 33, 8);
- Test("j:and_b(multi(2,0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798,024ce119c96e2fa357200b559b2f7dd5a5f02d5290aff74b03f3e471b273211c97),s:or_i(older(1),older(4252898)))", "82926352210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179821024ce119c96e2fa357200b559b2f7dd5a5f02d5290aff74b03f3e471b273211c9752ae7c6351b26703e2e440b2689a68", "?", TESTMODE_VALID | TESTMODE_NEEDSIG | TESTMODE_TAPSCRIPT_INVALID, 14, 4, 1 + 2 * 73 + 2, 8);
- Test("and_b(older(16),s:or_d(sha256(e38990d0c7fc009880a9c07c23842e886c6bbdc964ce6bdd5817ad357335ee6f),n:after(1567547623)))", "60b27c82012088a820e38990d0c7fc009880a9c07c23842e886c6bbdc964ce6bdd5817ad357335ee6f87736404e7e06e5db192689a", "=", TESTMODE_VALID, 12, 1, 33, 4);
- Test("j:and_v(v:hash160(20195b5a3d650c17f0f29f91c33f8f6335193d07),or_d(sha256(96de8fc8c256fa1e1556d41af431cace7dca68707c78dd88c3acab8b17164c47),older(16)))", "82926382012088a91420195b5a3d650c17f0f29f91c33f8f6335193d078882012088a82096de8fc8c256fa1e1556d41af431cace7dca68707c78dd88c3acab8b17164c4787736460b26868", "=", TESTMODE_VALID, 16, 2, 33 + 33, 4);
- Test("and_b(hash256(32ba476771d01e37807990ead8719f08af494723de1d228f2c2c07cc0aa40bac),a:and_b(hash256(131772552c01444cd81360818376a040b7c3b2b7b0a53550ee3edde216cec61b),a:older(1)))", "82012088aa2032ba476771d01e37807990ead8719f08af494723de1d228f2c2c07cc0aa40bac876b82012088aa20131772552c01444cd81360818376a040b7c3b2b7b0a53550ee3edde216cec61b876b51b26c9a6c9a", "=", TESTMODE_VALID | TESTMODE_NONMAL, 15, 2, 33 + 33, 4);
- Test("thresh(2,multi(2,03a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7,036d2b085e9e382ed10b69fc311a03f8641ccfff21574de0927513a49d9a688a00),a:multi(1,036d2b085e9e382ed10b69fc311a03f8641ccfff21574de0927513a49d9a688a00),ac:pk_k(022f01e5e15cca351daff3843fb70f3c2f0a1bdd05e5af888a67784ef3e10a2a01))", "522103a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c721036d2b085e9e382ed10b69fc311a03f8641ccfff21574de0927513a49d9a688a0052ae6b5121036d2b085e9e382ed10b69fc311a03f8641ccfff21574de0927513a49d9a688a0051ae6c936b21022f01e5e15cca351daff3843fb70f3c2f0a1bdd05e5af888a67784ef3e10a2a01ac6c935287", "?", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG | TESTMODE_TAPSCRIPT_INVALID, 13, 6, 1 + 2 * 73 + 1 + 73 + 1, 10);
- Test("and_n(sha256(d1ec675902ef1633427ca360b290b0b3045a0d9058ddb5e648b4c3c3224c5c68),t:or_i(v:older(4252898),v:older(144)))", "82012088a820d1ec675902ef1633427ca360b290b0b3045a0d9058ddb5e648b4c3c3224c5c68876400676303e2e440b26967029000b269685168", "=", TESTMODE_VALID, 14, 2, 33 + 2, 4);
- Test("or_d(nd:and_v(v:older(4252898),v:older(4252898)),sha256(38df1c1f64a24a77b23393bca50dff872e31edc4f3b5aa3b90ad0b82f4f089b6))", "766303e2e440b26903e2e440b2696892736482012088a82038df1c1f64a24a77b23393bca50dff872e31edc4f3b5aa3b90ad0b82f4f089b68768", "=", TESTMODE_VALID, 15, 2, 1 + 33, 3);
- Test("c:and_v(or_c(sha256(9267d3dbed802941483f1afa2a6bc68de5f653128aca9bf1461c5d0a3ad36ed2),v:multi(1,02c44d12c7065d812e8acf28d7cbb19f9011ecd9e9fdf281b0e6a3b5e87d22e7db)),pk_k(03acd484e2f0c7f65309ad178a9f559abde09796974c57e714c35f110dfc27ccbe))", "82012088a8209267d3dbed802941483f1afa2a6bc68de5f653128aca9bf1461c5d0a3ad36ed28764512102c44d12c7065d812e8acf28d7cbb19f9011ecd9e9fdf281b0e6a3b5e87d22e7db51af682103acd484e2f0c7f65309ad178a9f559abde09796974c57e714c35f110dfc27ccbeac", "?", TESTMODE_VALID | TESTMODE_NEEDSIG | TESTMODE_TAPSCRIPT_INVALID, 8, 2, 33 + 73, 4);
- Test("c:and_v(or_c(multi(2,036d2b085e9e382ed10b69fc311a03f8641ccfff21574de0927513a49d9a688a00,02352bbf4a4cdd12564f93fa332ce333301d9ad40271f8107181340aef25be59d5),v:ripemd160(1b0f3c404d12075c68c938f9f60ebea4f74941a0)),pk_k(03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556))", "5221036d2b085e9e382ed10b69fc311a03f8641ccfff21574de0927513a49d9a688a002102352bbf4a4cdd12564f93fa332ce333301d9ad40271f8107181340aef25be59d552ae6482012088a6141b0f3c404d12075c68c938f9f60ebea4f74941a088682103fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556ac", "?", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG | TESTMODE_TAPSCRIPT_INVALID, 10, 5, 1 + 2 * 73 + 73, 9);
- Test("and_v(andor(hash256(8a35d9ca92a48eaade6f53a64985e9e2afeb74dcf8acb4c3721e0dc7e4294b25),v:hash256(939894f70e6c3a25da75da0cc2071b4076d9b006563cf635986ada2e93c0d735),v:older(50000)),after(499999999))", "82012088aa208a35d9ca92a48eaade6f53a64985e9e2afeb74dcf8acb4c3721e0dc7e4294b2587640350c300b2696782012088aa20939894f70e6c3a25da75da0cc2071b4076d9b006563cf635986ada2e93c0d735886804ff64cd1db1", "=", TESTMODE_VALID, 14, 2, 33 + 33, 4);
- Test("andor(hash256(5f8d30e655a7ba0d7596bb3ddfb1d2d20390d23b1845000e1e118b3be1b3f040),j:and_v(v:hash160(3a2bff0da9d96868e66abc4427bea4691cf61ccd),older(4194305)),ripemd160(44d90e2d3714c8663b632fcf0f9d5f22192cc4c8))", "82012088aa205f8d30e655a7ba0d7596bb3ddfb1d2d20390d23b1845000e1e118b3be1b3f040876482012088a61444d90e2d3714c8663b632fcf0f9d5f22192cc4c8876782926382012088a9143a2bff0da9d96868e66abc4427bea4691cf61ccd8803010040b26868", "=", TESTMODE_VALID, 20, 2, 33 + 33, 4);
- Test("or_i(c:and_v(v:after(500000),pk_k(02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5)),sha256(d9147961436944f43cd99d28b2bbddbf452ef872b30c8279e255e7daafc7f946))", "630320a107b1692102c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5ac6782012088a820d9147961436944f43cd99d28b2bbddbf452ef872b30c8279e255e7daafc7f9468768", "630320a107b16920c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5ac6782012088a820d9147961436944f43cd99d28b2bbddbf452ef872b30c8279e255e7daafc7f9468768", TESTMODE_VALID | TESTMODE_NONMAL, 10, 2, 2 + 73, 3);
- Test("thresh(2,c:pk_h(025cbdf0646e5db4eaa398f365f2ea7a0e3d419b7e0330e39ce92bddedcac4f9bc),s:sha256(e38990d0c7fc009880a9c07c23842e886c6bbdc964ce6bdd5817ad357335ee6f),a:hash160(dd69735817e0e3f6f826a9238dc2e291184f0131))", "76a9145dedfbf9ea599dd4e3ca6a80b333c472fd0b3f6988ac7c82012088a820e38990d0c7fc009880a9c07c23842e886c6bbdc964ce6bdd5817ad357335ee6f87936b82012088a914dd69735817e0e3f6f826a9238dc2e291184f0131876c935287", "76a9141a7ac36cfa8431ab2395d701b0050045ae4a37d188ac7c82012088a820e38990d0c7fc009880a9c07c23842e886c6bbdc964ce6bdd5817ad357335ee6f87936b82012088a914dd69735817e0e3f6f826a9238dc2e291184f0131876c935287", TESTMODE_VALID, 18, 4, 1 + 34 + 33 + 33, 6);
- Test("and_n(sha256(9267d3dbed802941483f1afa2a6bc68de5f653128aca9bf1461c5d0a3ad36ed2),uc:and_v(v:older(144),pk_k(03fe72c435413d33d48ac09c9161ba8b09683215439d62b7940502bda8b202e6ce)))", "82012088a8209267d3dbed802941483f1afa2a6bc68de5f653128aca9bf1461c5d0a3ad36ed28764006763029000b2692103fe72c435413d33d48ac09c9161ba8b09683215439d62b7940502bda8b202e6ceac67006868", "82012088a8209267d3dbed802941483f1afa2a6bc68de5f653128aca9bf1461c5d0a3ad36ed28764006763029000b26920fe72c435413d33d48ac09c9161ba8b09683215439d62b7940502bda8b202e6ceac67006868", TESTMODE_VALID | TESTMODE_NEEDSIG, 13, 3, 33 + 2 + 73, 5);
- Test("and_n(c:pk_k(03daed4f2be3a8bf278e70132fb0beb7522f570e144bf615c07e996d443dee8729),and_b(l:older(4252898),a:older(16)))", "2103daed4f2be3a8bf278e70132fb0beb7522f570e144bf615c07e996d443dee8729ac64006763006703e2e440b2686b60b26c9a68", "20daed4f2be3a8bf278e70132fb0beb7522f570e144bf615c07e996d443dee8729ac64006763006703e2e440b2686b60b26c9a68", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG | TESTMODE_TIMELOCKMIX, 12, 2, 73 + 1, 3);
- Test("c:or_i(and_v(v:older(16),pk_h(02d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e)),pk_h(026a245bf6dc698504c89a20cfded60853152b695336c28063b61c65cbd269e6b4))", "6360b26976a9149fc5dbe5efdce10374a4dd4053c93af540211718886776a9142fbd32c8dd59ee7c17e66cb6ebea7e9846c3040f8868ac", "6360b26976a9144d4421361c3289bdad06441ffaee8be8e786f1ad886776a91460d4a7bcbd08f58e58bd208d1069837d7adb16ae8868ac", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG, 12, 3, 2 + 34 + 73, 4);
- Test("or_d(c:pk_h(02e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13),andor(c:pk_k(024ce119c96e2fa357200b559b2f7dd5a5f02d5290aff74b03f3e471b273211c97),older(2016),after(1567547623)))", "76a914c42e7ef92fdb603af844d064faad95db9bcdfd3d88ac736421024ce119c96e2fa357200b559b2f7dd5a5f02d5290aff74b03f3e471b273211c97ac6404e7e06e5db16702e007b26868", "76a91421ab1a140d0d305b8ff62bdb887d9fef82c9899e88ac7364204ce119c96e2fa357200b559b2f7dd5a5f02d5290aff74b03f3e471b273211c97ac6404e7e06e5db16702e007b26868", TESTMODE_VALID | TESTMODE_NONMAL, 13, 3, 1 + 34 + 73, 5);
- Test("c:andor(ripemd160(6ad07d21fd5dfc646f0b30577045ce201616b9ba),pk_h(02d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e),and_v(v:hash256(8a35d9ca92a48eaade6f53a64985e9e2afeb74dcf8acb4c3721e0dc7e4294b25),pk_h(03d01115d548e7561b15c38f004d734633687cf4419620095bc5b0f47070afe85a)))", "82012088a6146ad07d21fd5dfc646f0b30577045ce201616b9ba876482012088aa208a35d9ca92a48eaade6f53a64985e9e2afeb74dcf8acb4c3721e0dc7e4294b258876a914dd100be7d9aea5721158ebde6d6a1fd8fff93bb1886776a9149fc5dbe5efdce10374a4dd4053c93af5402117188868ac", "82012088a6146ad07d21fd5dfc646f0b30577045ce201616b9ba876482012088aa208a35d9ca92a48eaade6f53a64985e9e2afeb74dcf8acb4c3721e0dc7e4294b258876a914a63d1e4d2ed109246c600ec8c19cce546b65b1cc886776a9144d4421361c3289bdad06441ffaee8be8e786f1ad8868ac", TESTMODE_VALID | TESTMODE_NEEDSIG, 18, 3, 33 + 34 + 73, 5);
- Test("c:andor(u:ripemd160(6ad07d21fd5dfc646f0b30577045ce201616b9ba),pk_h(03daed4f2be3a8bf278e70132fb0beb7522f570e144bf615c07e996d443dee8729),or_i(pk_h(022f01e5e15cca351daff3843fb70f3c2f0a1bdd05e5af888a67784ef3e10a2a01),pk_h(0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798)))", "6382012088a6146ad07d21fd5dfc646f0b30577045ce201616b9ba87670068646376a9149652d86bedf43ad264362e6e6eba6eb764508127886776a914751e76e8199196d454941c45d1b3a323f1433bd688686776a91420d637c1a6404d2227f3561fdbaff5a680dba6488868ac", "6382012088a6146ad07d21fd5dfc646f0b30577045ce201616b9ba87670068646376a914ceedcb44b38bdbcb614d872223964fd3dca8a434886776a914f678d9b79045452c8c64e9309d0f0046056e26c588686776a914a2a75e1819afa208f6c89ae0da43021116dfcb0c8868ac", TESTMODE_VALID | TESTMODE_NEEDSIG, 23, 4, 2 + 33 + 34 + 73, 5);
- Test("c:or_i(andor(c:pk_h(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65),pk_h(022f01e5e15cca351daff3843fb70f3c2f0a1bdd05e5af888a67784ef3e10a2a01),pk_h(02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5)),pk_k(02d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e))", "6376a914fcd35ddacad9f2d5be5e464639441c6065e6955d88ac6476a91406afd46bcdfd22ef94ac122aa11f241244a37ecc886776a9149652d86bedf43ad264362e6e6eba6eb7645081278868672102d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e68ac", "6376a914fd1690c37fa3b0f04395ddc9415b220ab1ccc59588ac6476a9149b652a14674a506079f574d20ca7daef6f9a66bb886776a914ceedcb44b38bdbcb614d872223964fd3dca8a43488686720d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e68ac", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG, 17, 5, 2 + 34 + 73 + 34 + 73, 6);
- Test("thresh(1,c:pk_k(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65),altv:after(1000000000),altv:after(100))", "2103d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65ac6b6300670400ca9a3bb16951686c936b6300670164b16951686c935187", "20d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65ac6b6300670400ca9a3bb16951686c936b6300670164b16951686c935187", TESTMODE_VALID, 18, 3, 73 + 2 + 2, 4);
- Test("thresh(2,c:pk_k(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65),ac:pk_k(03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556),altv:after(1000000000),altv:after(100))", "2103d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65ac6b2103fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556ac6c936b6300670400ca9a3bb16951686c936b6300670164b16951686c935287", "20d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65ac6b20fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556ac6c936b6300670400ca9a3bb16951686c936b6300670164b16951686c935287", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_TIMELOCKMIX, 22, 4, 73 + 73 + 2 + 2, 5);
+ Test("lltvln:after(1231488000)", "6300676300676300670400046749b1926869516868", "=", TESTMODE_VALID | TESTMODE_NONMAL, 12, 3, 3, 3, 3);
+ Test("uuj:and_v(v:multi(2,03d01115d548e7561b15c38f004d734633687cf4419620095bc5b0f47070afe85a,025601570cb47f238d2b0286db4a990fa0f3ba28d1a319f5e7cf55c2a2444da7cc),after(1231488000))", "6363829263522103d01115d548e7561b15c38f004d734633687cf4419620095bc5b0f47070afe85a21025601570cb47f238d2b0286db4a990fa0f3ba28d1a319f5e7cf55c2a2444da7cc52af0400046749b168670068670068", "?", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG | TESTMODE_TAPSCRIPT_INVALID, 14, 5, 2 + 2 + 1 + 2 * 73, 0, 7);
+ Test("or_b(un:multi(2,03daed4f2be3a8bf278e70132fb0beb7522f570e144bf615c07e996d443dee8729,024ce119c96e2fa357200b559b2f7dd5a5f02d5290aff74b03f3e471b273211c97),al:older(16))", "63522103daed4f2be3a8bf278e70132fb0beb7522f570e144bf615c07e996d443dee872921024ce119c96e2fa357200b559b2f7dd5a5f02d5290aff74b03f3e471b273211c9752ae926700686b63006760b2686c9b", "?", TESTMODE_VALID | TESTMODE_TAPSCRIPT_INVALID, 14, 5, 2 + 1 + 2 * 73 + 2, 0, 8);
+ Test("j:and_v(vdv:after(1567547623),older(2016))", "829263766304e7e06e5db169686902e007b268", "=", TESTMODE_VALID | TESTMODE_NONMAL, 11, 1, 2, 2, 2);
+ Test("t:and_v(vu:hash256(131772552c01444cd81360818376a040b7c3b2b7b0a53550ee3edde216cec61b),v:sha256(ec4916dd28fc4c10d78e287ca5d9cc51ee1ae73cbfde08c6b37324cbfaac8bc5))", "6382012088aa20131772552c01444cd81360818376a040b7c3b2b7b0a53550ee3edde216cec61b876700686982012088a820ec4916dd28fc4c10d78e287ca5d9cc51ee1ae73cbfde08c6b37324cbfaac8bc58851", "6382012088aa20131772552c01444cd81360818376a040b7c3b2b7b0a53550ee3edde216cec61b876700686982012088a820ec4916dd28fc4c10d78e287ca5d9cc51ee1ae73cbfde08c6b37324cbfaac8bc58851", TESTMODE_VALID | TESTMODE_NONMAL, 12, 3, 2 + 33 + 33, 2 + 33 + 33, 4);
+ Test("t:andor(multi(3,02d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e,03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556,02e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13),v:older(4194305),v:sha256(9267d3dbed802941483f1afa2a6bc68de5f653128aca9bf1461c5d0a3ad36ed2))", "532102d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e2103fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a14602975562102e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd1353ae6482012088a8209267d3dbed802941483f1afa2a6bc68de5f653128aca9bf1461c5d0a3ad36ed2886703010040b2696851", "?", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_TAPSCRIPT_INVALID, 13, 5, 1 + 3 * 73, 0, 10);
+ Test("or_d(multi(1,02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9),or_b(multi(3,022f01e5e15cca351daff3843fb70f3c2f0a1bdd05e5af888a67784ef3e10a2a01,032fa2104d6b38d11b0230010559879124e42ab8dfeff5ff29dc9cdadd4ecacc3f,03d01115d548e7561b15c38f004d734633687cf4419620095bc5b0f47070afe85a),su:after(500000)))", "512102f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f951ae73645321022f01e5e15cca351daff3843fb70f3c2f0a1bdd05e5af888a67784ef3e10a2a0121032fa2104d6b38d11b0230010559879124e42ab8dfeff5ff29dc9cdadd4ecacc3f2103d01115d548e7561b15c38f004d734633687cf4419620095bc5b0f47070afe85a53ae7c630320a107b16700689b68", "?", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_TAPSCRIPT_INVALID, 15, 7, 2 + 1 + 3 * 73 + 1, 0, 10);
+ Test("or_d(sha256(38df1c1f64a24a77b23393bca50dff872e31edc4f3b5aa3b90ad0b82f4f089b6),and_n(un:after(499999999),older(4194305)))", "82012088a82038df1c1f64a24a77b23393bca50dff872e31edc4f3b5aa3b90ad0b82f4f089b68773646304ff64cd1db19267006864006703010040b26868", "82012088a82038df1c1f64a24a77b23393bca50dff872e31edc4f3b5aa3b90ad0b82f4f089b68773646304ff64cd1db19267006864006703010040b26868", TESTMODE_VALID, 16, 1, 33, 33, 3);
+ Test("and_v(or_i(v:multi(2,02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5,03774ae7f858a9411e5ef4246b70c65aac5649980be5c17891bbec17895da008cb),v:multi(2,03e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a,025cbdf0646e5db4eaa398f365f2ea7a0e3d419b7e0330e39ce92bddedcac4f9bc)),sha256(d1ec675902ef1633427ca360b290b0b3045a0d9058ddb5e648b4c3c3224c5c68))", "63522102c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee52103774ae7f858a9411e5ef4246b70c65aac5649980be5c17891bbec17895da008cb52af67522103e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a21025cbdf0646e5db4eaa398f365f2ea7a0e3d419b7e0330e39ce92bddedcac4f9bc52af6882012088a820d1ec675902ef1633427ca360b290b0b3045a0d9058ddb5e648b4c3c3224c5c6887", "?", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG | TESTMODE_TAPSCRIPT_INVALID, 11, 5, 2 + 1 + 2 * 73 + 33, 0, 8);
+ Test("j:and_b(multi(2,0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798,024ce119c96e2fa357200b559b2f7dd5a5f02d5290aff74b03f3e471b273211c97),s:or_i(older(1),older(4252898)))", "82926352210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179821024ce119c96e2fa357200b559b2f7dd5a5f02d5290aff74b03f3e471b273211c9752ae7c6351b26703e2e440b2689a68", "?", TESTMODE_VALID | TESTMODE_NEEDSIG | TESTMODE_TAPSCRIPT_INVALID, 14, 4, 1 + 2 * 73 + 2, 0, 8);
+ Test("and_b(older(16),s:or_d(sha256(e38990d0c7fc009880a9c07c23842e886c6bbdc964ce6bdd5817ad357335ee6f),n:after(1567547623)))", "60b27c82012088a820e38990d0c7fc009880a9c07c23842e886c6bbdc964ce6bdd5817ad357335ee6f87736404e7e06e5db192689a", "=", TESTMODE_VALID, 12, 1, 33, 33, 4);
+ Test("j:and_v(v:hash160(20195b5a3d650c17f0f29f91c33f8f6335193d07),or_d(sha256(96de8fc8c256fa1e1556d41af431cace7dca68707c78dd88c3acab8b17164c47),older(16)))", "82926382012088a91420195b5a3d650c17f0f29f91c33f8f6335193d078882012088a82096de8fc8c256fa1e1556d41af431cace7dca68707c78dd88c3acab8b17164c4787736460b26868", "=", TESTMODE_VALID, 16, 2, 33 + 33, 33 + 33, 4);
+ Test("and_b(hash256(32ba476771d01e37807990ead8719f08af494723de1d228f2c2c07cc0aa40bac),a:and_b(hash256(131772552c01444cd81360818376a040b7c3b2b7b0a53550ee3edde216cec61b),a:older(1)))", "82012088aa2032ba476771d01e37807990ead8719f08af494723de1d228f2c2c07cc0aa40bac876b82012088aa20131772552c01444cd81360818376a040b7c3b2b7b0a53550ee3edde216cec61b876b51b26c9a6c9a", "=", TESTMODE_VALID | TESTMODE_NONMAL, 15, 2, 33 + 33, 33 + 33, 4);
+ Test("thresh(2,multi(2,03a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7,036d2b085e9e382ed10b69fc311a03f8641ccfff21574de0927513a49d9a688a00),a:multi(1,036d2b085e9e382ed10b69fc311a03f8641ccfff21574de0927513a49d9a688a00),ac:pk_k(022f01e5e15cca351daff3843fb70f3c2f0a1bdd05e5af888a67784ef3e10a2a01))", "522103a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c721036d2b085e9e382ed10b69fc311a03f8641ccfff21574de0927513a49d9a688a0052ae6b5121036d2b085e9e382ed10b69fc311a03f8641ccfff21574de0927513a49d9a688a0051ae6c936b21022f01e5e15cca351daff3843fb70f3c2f0a1bdd05e5af888a67784ef3e10a2a01ac6c935287", "?", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG | TESTMODE_TAPSCRIPT_INVALID, 13, 6, 1 + 2 * 73 + 1 + 73 + 1, 0, 10);
+ Test("and_n(sha256(d1ec675902ef1633427ca360b290b0b3045a0d9058ddb5e648b4c3c3224c5c68),t:or_i(v:older(4252898),v:older(144)))", "82012088a820d1ec675902ef1633427ca360b290b0b3045a0d9058ddb5e648b4c3c3224c5c68876400676303e2e440b26967029000b269685168", "=", TESTMODE_VALID, 14, 2, 33 + 2, 33 + 2, 4);
+ Test("or_d(nd:and_v(v:older(4252898),v:older(4252898)),sha256(38df1c1f64a24a77b23393bca50dff872e31edc4f3b5aa3b90ad0b82f4f089b6))", "766303e2e440b26903e2e440b2696892736482012088a82038df1c1f64a24a77b23393bca50dff872e31edc4f3b5aa3b90ad0b82f4f089b68768", "=", TESTMODE_VALID, 15, 2, 1 + 33, 1 + 33, 3);
+ Test("c:and_v(or_c(sha256(9267d3dbed802941483f1afa2a6bc68de5f653128aca9bf1461c5d0a3ad36ed2),v:multi(1,02c44d12c7065d812e8acf28d7cbb19f9011ecd9e9fdf281b0e6a3b5e87d22e7db)),pk_k(03acd484e2f0c7f65309ad178a9f559abde09796974c57e714c35f110dfc27ccbe))", "82012088a8209267d3dbed802941483f1afa2a6bc68de5f653128aca9bf1461c5d0a3ad36ed28764512102c44d12c7065d812e8acf28d7cbb19f9011ecd9e9fdf281b0e6a3b5e87d22e7db51af682103acd484e2f0c7f65309ad178a9f559abde09796974c57e714c35f110dfc27ccbeac", "?", TESTMODE_VALID | TESTMODE_NEEDSIG | TESTMODE_TAPSCRIPT_INVALID, 8, 2, 33 + 73, 0, 4);
+ Test("c:and_v(or_c(multi(2,036d2b085e9e382ed10b69fc311a03f8641ccfff21574de0927513a49d9a688a00,02352bbf4a4cdd12564f93fa332ce333301d9ad40271f8107181340aef25be59d5),v:ripemd160(1b0f3c404d12075c68c938f9f60ebea4f74941a0)),pk_k(03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556))", "5221036d2b085e9e382ed10b69fc311a03f8641ccfff21574de0927513a49d9a688a002102352bbf4a4cdd12564f93fa332ce333301d9ad40271f8107181340aef25be59d552ae6482012088a6141b0f3c404d12075c68c938f9f60ebea4f74941a088682103fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556ac", "?", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG | TESTMODE_TAPSCRIPT_INVALID, 10, 5, 1 + 2 * 73 + 73, 0, 9);
+ Test("and_v(andor(hash256(8a35d9ca92a48eaade6f53a64985e9e2afeb74dcf8acb4c3721e0dc7e4294b25),v:hash256(939894f70e6c3a25da75da0cc2071b4076d9b006563cf635986ada2e93c0d735),v:older(50000)),after(499999999))", "82012088aa208a35d9ca92a48eaade6f53a64985e9e2afeb74dcf8acb4c3721e0dc7e4294b2587640350c300b2696782012088aa20939894f70e6c3a25da75da0cc2071b4076d9b006563cf635986ada2e93c0d735886804ff64cd1db1", "=", TESTMODE_VALID, 14, 2, 33 + 33, 33 + 33, 4);
+ Test("andor(hash256(5f8d30e655a7ba0d7596bb3ddfb1d2d20390d23b1845000e1e118b3be1b3f040),j:and_v(v:hash160(3a2bff0da9d96868e66abc4427bea4691cf61ccd),older(4194305)),ripemd160(44d90e2d3714c8663b632fcf0f9d5f22192cc4c8))", "82012088aa205f8d30e655a7ba0d7596bb3ddfb1d2d20390d23b1845000e1e118b3be1b3f040876482012088a61444d90e2d3714c8663b632fcf0f9d5f22192cc4c8876782926382012088a9143a2bff0da9d96868e66abc4427bea4691cf61ccd8803010040b26868", "=", TESTMODE_VALID, 20, 2, 33 + 33, 33 + 33, 4);
+ Test("or_i(c:and_v(v:after(500000),pk_k(02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5)),sha256(d9147961436944f43cd99d28b2bbddbf452ef872b30c8279e255e7daafc7f946))", "630320a107b1692102c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5ac6782012088a820d9147961436944f43cd99d28b2bbddbf452ef872b30c8279e255e7daafc7f9468768", "630320a107b16920c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5ac6782012088a820d9147961436944f43cd99d28b2bbddbf452ef872b30c8279e255e7daafc7f9468768", TESTMODE_VALID | TESTMODE_NONMAL, 10, 2, 2 + 73, 2 + 66, 3);
+ Test("thresh(2,c:pk_h(025cbdf0646e5db4eaa398f365f2ea7a0e3d419b7e0330e39ce92bddedcac4f9bc),s:sha256(e38990d0c7fc009880a9c07c23842e886c6bbdc964ce6bdd5817ad357335ee6f),a:hash160(dd69735817e0e3f6f826a9238dc2e291184f0131))", "76a9145dedfbf9ea599dd4e3ca6a80b333c472fd0b3f6988ac7c82012088a820e38990d0c7fc009880a9c07c23842e886c6bbdc964ce6bdd5817ad357335ee6f87936b82012088a914dd69735817e0e3f6f826a9238dc2e291184f0131876c935287", "76a9141a7ac36cfa8431ab2395d701b0050045ae4a37d188ac7c82012088a820e38990d0c7fc009880a9c07c23842e886c6bbdc964ce6bdd5817ad357335ee6f87936b82012088a914dd69735817e0e3f6f826a9238dc2e291184f0131876c935287", TESTMODE_VALID, 18, 4, 1 + 34 + 33 + 33, 1 + 33 + 33 + 33, 6);
+ Test("and_n(sha256(9267d3dbed802941483f1afa2a6bc68de5f653128aca9bf1461c5d0a3ad36ed2),uc:and_v(v:older(144),pk_k(03fe72c435413d33d48ac09c9161ba8b09683215439d62b7940502bda8b202e6ce)))", "82012088a8209267d3dbed802941483f1afa2a6bc68de5f653128aca9bf1461c5d0a3ad36ed28764006763029000b2692103fe72c435413d33d48ac09c9161ba8b09683215439d62b7940502bda8b202e6ceac67006868", "82012088a8209267d3dbed802941483f1afa2a6bc68de5f653128aca9bf1461c5d0a3ad36ed28764006763029000b26920fe72c435413d33d48ac09c9161ba8b09683215439d62b7940502bda8b202e6ceac67006868", TESTMODE_VALID | TESTMODE_NEEDSIG, 13, 3, 33 + 2 + 73, 33 + 2 + 66, 5);
+ Test("and_n(c:pk_k(03daed4f2be3a8bf278e70132fb0beb7522f570e144bf615c07e996d443dee8729),and_b(l:older(4252898),a:older(16)))", "2103daed4f2be3a8bf278e70132fb0beb7522f570e144bf615c07e996d443dee8729ac64006763006703e2e440b2686b60b26c9a68", "20daed4f2be3a8bf278e70132fb0beb7522f570e144bf615c07e996d443dee8729ac64006763006703e2e440b2686b60b26c9a68", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG | TESTMODE_TIMELOCKMIX, 12, 2, 73 + 1, 66 + 1, 3);
+ Test("c:or_i(and_v(v:older(16),pk_h(02d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e)),pk_h(026a245bf6dc698504c89a20cfded60853152b695336c28063b61c65cbd269e6b4))", "6360b26976a9149fc5dbe5efdce10374a4dd4053c93af540211718886776a9142fbd32c8dd59ee7c17e66cb6ebea7e9846c3040f8868ac", "6360b26976a9144d4421361c3289bdad06441ffaee8be8e786f1ad886776a91460d4a7bcbd08f58e58bd208d1069837d7adb16ae8868ac", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG, 12, 3, 2 + 34 + 73, 2 + 33 + 66, 4);
+ Test("or_d(c:pk_h(02e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13),andor(c:pk_k(024ce119c96e2fa357200b559b2f7dd5a5f02d5290aff74b03f3e471b273211c97),older(2016),after(1567547623)))", "76a914c42e7ef92fdb603af844d064faad95db9bcdfd3d88ac736421024ce119c96e2fa357200b559b2f7dd5a5f02d5290aff74b03f3e471b273211c97ac6404e7e06e5db16702e007b26868", "76a91421ab1a140d0d305b8ff62bdb887d9fef82c9899e88ac7364204ce119c96e2fa357200b559b2f7dd5a5f02d5290aff74b03f3e471b273211c97ac6404e7e06e5db16702e007b26868", TESTMODE_VALID | TESTMODE_NONMAL, 13, 3, 1 + 34 + 73, 1 + 33 + 66, 5);
+ Test("c:andor(ripemd160(6ad07d21fd5dfc646f0b30577045ce201616b9ba),pk_h(02d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e),and_v(v:hash256(8a35d9ca92a48eaade6f53a64985e9e2afeb74dcf8acb4c3721e0dc7e4294b25),pk_h(03d01115d548e7561b15c38f004d734633687cf4419620095bc5b0f47070afe85a)))", "82012088a6146ad07d21fd5dfc646f0b30577045ce201616b9ba876482012088aa208a35d9ca92a48eaade6f53a64985e9e2afeb74dcf8acb4c3721e0dc7e4294b258876a914dd100be7d9aea5721158ebde6d6a1fd8fff93bb1886776a9149fc5dbe5efdce10374a4dd4053c93af5402117188868ac", "82012088a6146ad07d21fd5dfc646f0b30577045ce201616b9ba876482012088aa208a35d9ca92a48eaade6f53a64985e9e2afeb74dcf8acb4c3721e0dc7e4294b258876a914a63d1e4d2ed109246c600ec8c19cce546b65b1cc886776a9144d4421361c3289bdad06441ffaee8be8e786f1ad8868ac", TESTMODE_VALID | TESTMODE_NEEDSIG, 18, 3, 33 + 34 + 73, 33 + 33 + 66, 5);
+ Test("c:andor(u:ripemd160(6ad07d21fd5dfc646f0b30577045ce201616b9ba),pk_h(03daed4f2be3a8bf278e70132fb0beb7522f570e144bf615c07e996d443dee8729),or_i(pk_h(022f01e5e15cca351daff3843fb70f3c2f0a1bdd05e5af888a67784ef3e10a2a01),pk_h(0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798)))", "6382012088a6146ad07d21fd5dfc646f0b30577045ce201616b9ba87670068646376a9149652d86bedf43ad264362e6e6eba6eb764508127886776a914751e76e8199196d454941c45d1b3a323f1433bd688686776a91420d637c1a6404d2227f3561fdbaff5a680dba6488868ac", "6382012088a6146ad07d21fd5dfc646f0b30577045ce201616b9ba87670068646376a914ceedcb44b38bdbcb614d872223964fd3dca8a434886776a914f678d9b79045452c8c64e9309d0f0046056e26c588686776a914a2a75e1819afa208f6c89ae0da43021116dfcb0c8868ac", TESTMODE_VALID | TESTMODE_NEEDSIG, 23, 4, 2 + 33 + 34 + 73, 2 + 33 + 33 + 66, 5);
+ Test("c:or_i(andor(c:pk_h(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65),pk_h(022f01e5e15cca351daff3843fb70f3c2f0a1bdd05e5af888a67784ef3e10a2a01),pk_h(02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5)),pk_k(02d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e))", "6376a914fcd35ddacad9f2d5be5e464639441c6065e6955d88ac6476a91406afd46bcdfd22ef94ac122aa11f241244a37ecc886776a9149652d86bedf43ad264362e6e6eba6eb7645081278868672102d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e68ac", "6376a914fd1690c37fa3b0f04395ddc9415b220ab1ccc59588ac6476a9149b652a14674a506079f574d20ca7daef6f9a66bb886776a914ceedcb44b38bdbcb614d872223964fd3dca8a43488686720d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e68ac", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG, 17, 5, 2 + 34 + 73 + 34 + 73, 2 + 33 + 66 + 33 + 66, 6);
+ Test("thresh(1,c:pk_k(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65),altv:after(1000000000),altv:after(100))", "2103d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65ac6b6300670400ca9a3bb16951686c936b6300670164b16951686c935187", "20d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65ac6b6300670400ca9a3bb16951686c936b6300670164b16951686c935187", TESTMODE_VALID, 18, 3, 73 + 2 + 2, 66 + 2 + 2, 4);
+ Test("thresh(2,c:pk_k(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65),ac:pk_k(03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556),altv:after(1000000000),altv:after(100))", "2103d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65ac6b2103fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556ac6c936b6300670400ca9a3bb16951686c936b6300670164b16951686c935287", "20d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65ac6b20fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556ac6c936b6300670400ca9a3bb16951686c936b6300670164b16951686c935287", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_TIMELOCKMIX, 22, 4, 73 + 73 + 2 + 2, 66 + 66 + 2 + 2, 5);
// Additional Tapscript-related tests
// Edge cases when parsing multi_a from script:
// - no pubkey at all
// - no pubkey before a CHECKSIGADD
// - no pubkey before the CHECKSIG
+ constexpr KeyConverter tap_converter{miniscript::MiniscriptContext::TAPSCRIPT};
+ constexpr KeyConverter wsh_converter{miniscript::MiniscriptContext::P2WSH};
const auto no_pubkey{ParseHex("ac519c")};
- BOOST_CHECK(miniscript::FromScript({no_pubkey.begin(), no_pubkey.end()}, CONVERTER) == nullptr);
+ BOOST_CHECK(miniscript::FromScript({no_pubkey.begin(), no_pubkey.end()}, tap_converter) == nullptr);
const auto incomplete_multi_a{ParseHex("ba20c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5ba519c")};
- BOOST_CHECK(miniscript::FromScript({incomplete_multi_a.begin(), incomplete_multi_a.end()}, CONVERTER) == nullptr);
+ BOOST_CHECK(miniscript::FromScript({incomplete_multi_a.begin(), incomplete_multi_a.end()}, tap_converter) == nullptr);
const auto incomplete_multi_a_2{ParseHex("ac2079be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ac20c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5ba519c")};
- BOOST_CHECK(miniscript::FromScript({incomplete_multi_a_2.begin(), incomplete_multi_a_2.end()}, CONVERTER) == nullptr);
+ BOOST_CHECK(miniscript::FromScript({incomplete_multi_a_2.begin(), incomplete_multi_a_2.end()}, tap_converter) == nullptr);
// Can use multi_a under Tapscript but not P2WSH.
- Test("and_v(v:multi_a(2,03d01115d548e7561b15c38f004d734633687cf4419620095bc5b0f47070afe85a,025601570cb47f238d2b0286db4a990fa0f3ba28d1a319f5e7cf55c2a2444da7cc),after(1231488000))", "?", "20d01115d548e7561b15c38f004d734633687cf4419620095bc5b0f47070afe85aac205601570cb47f238d2b0286db4a990fa0f3ba28d1a319f5e7cf55c2a2444da7ccba529d0400046749b1", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG | TESTMODE_P2WSH_INVALID, 4, 2, {}, 3);
+ Test("and_v(v:multi_a(2,03d01115d548e7561b15c38f004d734633687cf4419620095bc5b0f47070afe85a,025601570cb47f238d2b0286db4a990fa0f3ba28d1a319f5e7cf55c2a2444da7cc),after(1231488000))", "?", "20d01115d548e7561b15c38f004d734633687cf4419620095bc5b0f47070afe85aac205601570cb47f238d2b0286db4a990fa0f3ba28d1a319f5e7cf55c2a2444da7ccba529d0400046749b1", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG | TESTMODE_P2WSH_INVALID, 4, 2, {}, {}, 3);
// Can use more than 20 keys in a multi_a.
std::string ms_str_multi_a{"multi_a(1,"};
for (size_t i = 0; i < 21; ++i) {
@@ -599,9 +610,9 @@ BOOST_AUTO_TEST_CASE(fixed_tests)
if (i < 20) ms_str_multi_a += ",";
}
ms_str_multi_a += ")";
- Test(ms_str_multi_a, "?", "2079be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ac20c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5ba20f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9ba20e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13ba202f8bde4d1a07209355b4a7250a5c5128e88b84bddc619ab7cba8d569b240efe4ba20fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556ba205cbdf0646e5db4eaa398f365f2ea7a0e3d419b7e0330e39ce92bddedcac4f9bcba202f01e5e15cca351daff3843fb70f3c2f0a1bdd05e5af888a67784ef3e10a2a01ba20acd484e2f0c7f65309ad178a9f559abde09796974c57e714c35f110dfc27ccbeba20a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7ba20774ae7f858a9411e5ef4246b70c65aac5649980be5c17891bbec17895da008cbba20d01115d548e7561b15c38f004d734633687cf4419620095bc5b0f47070afe85aba20f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8ba20499fdf9e895e719cfd64e67f07d38e3226aa7b63678949e6e49b241a60e823e4ba20d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080eba20e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0aba20defdea4cdb677750a420fee807eacf21eb9898ae79b9768766e4faa04a2d4a34ba205601570cb47f238d2b0286db4a990fa0f3ba28d1a319f5e7cf55c2a2444da7ccba202b4ea0a797a443d293ef5cff444f4979f06acfebd7e86d277475656138385b6cba204ce119c96e2fa357200b559b2f7dd5a5f02d5290aff74b03f3e471b273211c97ba20352bbf4a4cdd12564f93fa332ce333301d9ad40271f8107181340aef25be59d5ba519c", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG | TESTMODE_P2WSH_INVALID, 22, 21, {}, 22);
+ Test(ms_str_multi_a, "?", "2079be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ac20c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5ba20f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9ba20e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13ba202f8bde4d1a07209355b4a7250a5c5128e88b84bddc619ab7cba8d569b240efe4ba20fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556ba205cbdf0646e5db4eaa398f365f2ea7a0e3d419b7e0330e39ce92bddedcac4f9bcba202f01e5e15cca351daff3843fb70f3c2f0a1bdd05e5af888a67784ef3e10a2a01ba20acd484e2f0c7f65309ad178a9f559abde09796974c57e714c35f110dfc27ccbeba20a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7ba20774ae7f858a9411e5ef4246b70c65aac5649980be5c17891bbec17895da008cbba20d01115d548e7561b15c38f004d734633687cf4419620095bc5b0f47070afe85aba20f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8ba20499fdf9e895e719cfd64e67f07d38e3226aa7b63678949e6e49b241a60e823e4ba20d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080eba20e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0aba20defdea4cdb677750a420fee807eacf21eb9898ae79b9768766e4faa04a2d4a34ba205601570cb47f238d2b0286db4a990fa0f3ba28d1a319f5e7cf55c2a2444da7ccba202b4ea0a797a443d293ef5cff444f4979f06acfebd7e86d277475656138385b6cba204ce119c96e2fa357200b559b2f7dd5a5f02d5290aff74b03f3e471b273211c97ba20352bbf4a4cdd12564f93fa332ce333301d9ad40271f8107181340aef25be59d5ba519c", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG | TESTMODE_P2WSH_INVALID, 22, 21, {}, {}, 22);
// Since 'd:' is 'u' we can use it directly inside a thresh. But we can't under P2WSH.
- Test("thresh(2,dv:older(42),s:pk(025cbdf0646e5db4eaa398f365f2ea7a0e3d419b7e0330e39ce92bddedcac4f9bc),s:pk(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65))", "?", "7663012ab269687c205cbdf0646e5db4eaa398f365f2ea7a0e3d419b7e0330e39ce92bddedcac4f9bcac937c20d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65ac935287", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG | TESTMODE_P2WSH_INVALID, 12, 3, {}, 4);
+ Test("thresh(2,dv:older(42),s:pk(025cbdf0646e5db4eaa398f365f2ea7a0e3d419b7e0330e39ce92bddedcac4f9bc),s:pk(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65))", "?", "7663012ab269687c205cbdf0646e5db4eaa398f365f2ea7a0e3d419b7e0330e39ce92bddedcac4f9bcac937c20d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65ac935287", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG | TESTMODE_P2WSH_INVALID, 12, 3, {}, {}, 4);
// We can have a script that has more than 201 ops (n = 99), that needs a stack size > 100 (n = 110), or has a
// script that is larger than 3600 bytes (n = 200). All that can't be under P2WSH.
for (const auto pk_count: {99, 110, 200}) {
@@ -611,7 +622,7 @@ BOOST_AUTO_TEST_CASE(fixed_tests)
}
ms_str_large += "pk(" + HexStr(g_testdata->pubkeys[pk_count - 1]) + ")";
ms_str_large.insert(ms_str_large.end(), pk_count - 1, ')');
- Test(ms_str_large, "?", "?", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG | TESTMODE_P2WSH_INVALID, pk_count + (pk_count - 1) * 3, pk_count, {}, pk_count + 1);
+ Test(ms_str_large, "?", "?", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG | TESTMODE_P2WSH_INVALID, pk_count + (pk_count - 1) * 3, pk_count, {}, {}, pk_count + 1);
}
// We can have a script that reaches a stack size of 1000 during execution.
std::string ms_stack_limit;
@@ -621,25 +632,27 @@ BOOST_AUTO_TEST_CASE(fixed_tests)
}
ms_stack_limit += "pk(" + HexStr(g_testdata->pubkeys[0]) + ")";
ms_stack_limit.insert(ms_stack_limit.end(), count, ')');
- const auto ms_stack_ok{miniscript::FromString(ms_stack_limit, CONVERTER)};
+ const auto ms_stack_ok{miniscript::FromString(ms_stack_limit, tap_converter)};
BOOST_CHECK(ms_stack_ok && ms_stack_ok->CheckStackSize());
- Test(ms_stack_limit, "?", "?", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG | TESTMODE_P2WSH_INVALID, 4 * count + 1, 1, {}, 1 + count + 1);
+ Test(ms_stack_limit, "?", "?", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG | TESTMODE_P2WSH_INVALID, 4 * count + 1, 1, {}, {}, 1 + count + 1);
// But one more element on the stack during execution will make it fail. And we'd detect that.
count++;
ms_stack_limit = "and_b(older(1),a:" + ms_stack_limit + ")";
- const auto ms_stack_nok{miniscript::FromString(ms_stack_limit, CONVERTER)};
+ const auto ms_stack_nok{miniscript::FromString(ms_stack_limit, tap_converter)};
BOOST_CHECK(ms_stack_nok && !ms_stack_nok->CheckStackSize());
- Test(ms_stack_limit, "?", "?", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG | TESTMODE_P2WSH_INVALID, 4 * count + 1, 1, {}, 1 + count + 1);
+ Test(ms_stack_limit, "?", "?", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG | TESTMODE_P2WSH_INVALID, 4 * count + 1, 1, {}, {}, 1 + count + 1);
// Misc unit tests
// A Script with a non minimal push is invalid
std::vector nonminpush = ParseHex("0000210232780000feff00ffffffffffff21ff005f00ae21ae00000000060602060406564c2102320000060900fe00005f00ae21ae00100000060606060606000000000000000000000000000000000000000000000000000000000000000000");
const CScript nonminpush_script(nonminpush.begin(), nonminpush.end());
- BOOST_CHECK(miniscript::FromScript(nonminpush_script, CONVERTER) == nullptr);
+ BOOST_CHECK(miniscript::FromScript(nonminpush_script, wsh_converter) == nullptr);
+ BOOST_CHECK(miniscript::FromScript(nonminpush_script, tap_converter) == nullptr);
// A non-minimal VERIFY ( CHECKSIG VERIFY 1)
std::vector nonminverify = ParseHex("2103a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7ac6951");
const CScript nonminverify_script(nonminverify.begin(), nonminverify.end());
- BOOST_CHECK(miniscript::FromScript(nonminverify_script, CONVERTER) == nullptr);
+ BOOST_CHECK(miniscript::FromScript(nonminverify_script, wsh_converter) == nullptr);
+ BOOST_CHECK(miniscript::FromScript(nonminverify_script, tap_converter) == nullptr);
// A threshold as large as the number of subs is valid.
Test("thresh(2,c:pk_k(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65),altv:after(100))", "2103d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65ac6b6300670164b16951686c935287", "20d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65ac6b6300670164b16951686c935287", TESTMODE_VALID | TESTMODE_NEEDSIG | TESTMODE_NONMAL);
// A threshold of 1 is valid.
@@ -649,8 +662,7 @@ BOOST_AUTO_TEST_CASE(fixed_tests)
// A threshold with a k null is invalid
Test("thresh(0,c:pk_k(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65),sc:pk_k(03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556))", "2103d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65ac7c2103fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556ac935187", "=", TESTMODE_INVALID);
// For CHECKMULTISIG the OP cost is the number of keys, but the stack size is the number of sigs (+1)
- CONVERTER.SetContext(miniscript::MiniscriptContext::P2WSH);
- const auto ms_multi = miniscript::FromString("multi(1,03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65,03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556,0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798)", CONVERTER);
+ const auto ms_multi = miniscript::FromString("multi(1,03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65,03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556,0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798)", wsh_converter);
BOOST_CHECK(ms_multi);
BOOST_CHECK_EQUAL(*ms_multi->GetOps(), 4); // 3 pubkeys + CMS
BOOST_CHECK_EQUAL(*ms_multi->GetStackSize(), 2); // 1 sig + dummy elem
@@ -661,33 +673,33 @@ BOOST_AUTO_TEST_CASE(fixed_tests)
// Unfortunately, this rule is consensus for Taproot but only policy for P2WSH. Therefore we can't
// (for now) have 'd:' be 'u'. This tests we can't use a 'd:' wrapper for a thresh, which requires
// its subs to all be 'u' (taken from https://github.com/rust-bitcoin/rust-miniscript/discussions/341).
- const auto ms_minimalif = miniscript::FromString("thresh(3,c:pk_k(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65),sc:pk_k(03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556),sc:pk_k(0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798),sdv:older(32))", CONVERTER);
+ const auto ms_minimalif = miniscript::FromString("thresh(3,c:pk_k(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65),sc:pk_k(03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556),sc:pk_k(0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798),sdv:older(32))", wsh_converter);
BOOST_CHECK(ms_minimalif && !ms_minimalif->IsValid());
// A Miniscript with duplicate keys is not sane
- const auto ms_dup1 = miniscript::FromString("and_v(v:pk(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65),pk(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65))", CONVERTER);
+ const auto ms_dup1 = miniscript::FromString("and_v(v:pk(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65),pk(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65))", wsh_converter);
BOOST_CHECK(ms_dup1);
BOOST_CHECK(!ms_dup1->IsSane() && !ms_dup1->CheckDuplicateKey());
// Same with a disjunction, and different key nodes (pk and pkh)
- const auto ms_dup2 = miniscript::FromString("or_b(c:pk_k(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65),ac:pk_h(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65))", CONVERTER);
+ const auto ms_dup2 = miniscript::FromString("or_b(c:pk_k(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65),ac:pk_h(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65))", wsh_converter);
BOOST_CHECK(ms_dup2 && !ms_dup2->IsSane() && !ms_dup2->CheckDuplicateKey());
// Same when the duplicates are leaves or a larger tree
- const auto ms_dup3 = miniscript::FromString("or_i(and_b(pk(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65),s:pk(03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556)),and_b(older(1),s:pk(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65)))", CONVERTER);
+ const auto ms_dup3 = miniscript::FromString("or_i(and_b(pk(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65),s:pk(03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556)),and_b(older(1),s:pk(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65)))", wsh_converter);
BOOST_CHECK(ms_dup3 && !ms_dup3->IsSane() && !ms_dup3->CheckDuplicateKey());
// Same when the duplicates are on different levels in the tree
- const auto ms_dup4 = miniscript::FromString("thresh(2,pkh(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65),s:pk(03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556),a:and_b(dv:older(1),s:pk(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65)))", CONVERTER);
+ const auto ms_dup4 = miniscript::FromString("thresh(2,pkh(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65),s:pk(03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556),a:and_b(dv:older(1),s:pk(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65)))", wsh_converter);
BOOST_CHECK(ms_dup4 && !ms_dup4->IsSane() && !ms_dup4->CheckDuplicateKey());
// Sanity check the opposite is true, too. An otherwise sane Miniscript with no duplicate keys is sane.
- const auto ms_nondup = miniscript::FromString("pk(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65)", CONVERTER);
+ const auto ms_nondup = miniscript::FromString("pk(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65)", wsh_converter);
BOOST_CHECK(ms_nondup && ms_nondup->CheckDuplicateKey() && ms_nondup->IsSane());
// Test we find the first insane sub closer to be a leaf node. This fragment is insane for two reasons:
// 1. It can be spent without a signature
// 2. It contains timelock mixes
// We'll report the timelock mix error, as it's "deeper" (closer to be a leaf node) than the "no 's' property"
// error is.
- const auto ms_ins = miniscript::FromString("or_i(and_b(after(1),a:after(1000000000)),pk(03cdabb7f2dce7bfbd8a0b9570c6fd1e712e5d64045e9d6b517b3d5072251dc204))", CONVERTER);
+ const auto ms_ins = miniscript::FromString("or_i(and_b(after(1),a:after(1000000000)),pk(03cdabb7f2dce7bfbd8a0b9570c6fd1e712e5d64045e9d6b517b3d5072251dc204))", wsh_converter);
BOOST_CHECK(ms_ins && ms_ins->IsValid() && !ms_ins->IsSane());
const auto insane_sub = ms_ins->FindInsaneSub();
- BOOST_CHECK(insane_sub && *insane_sub->ToString(CONVERTER) == "and_b(after(1),a:after(1000000000))");
+ BOOST_CHECK(insane_sub && *insane_sub->ToString(wsh_converter) == "and_b(after(1),a:after(1000000000))");
// Timelock tests
Test("after(100)", "?", "?", TESTMODE_VALID | TESTMODE_NONMAL); // only heightlock
diff --git a/src/test/net_tests.cpp b/src/test/net_tests.cpp
index d3a87fdd89..3d2d193dc8 100644
--- a/src/test/net_tests.cpp
+++ b/src/test/net_tests.cpp
@@ -718,47 +718,55 @@ BOOST_AUTO_TEST_CASE(get_local_addr_for_peer_port)
BOOST_AUTO_TEST_CASE(LimitedAndReachable_Network)
{
- BOOST_CHECK(IsReachable(NET_IPV4));
- BOOST_CHECK(IsReachable(NET_IPV6));
- BOOST_CHECK(IsReachable(NET_ONION));
- BOOST_CHECK(IsReachable(NET_I2P));
- BOOST_CHECK(IsReachable(NET_CJDNS));
-
- SetReachable(NET_IPV4, false);
- SetReachable(NET_IPV6, false);
- SetReachable(NET_ONION, false);
- SetReachable(NET_I2P, false);
- SetReachable(NET_CJDNS, false);
-
- BOOST_CHECK(!IsReachable(NET_IPV4));
- BOOST_CHECK(!IsReachable(NET_IPV6));
- BOOST_CHECK(!IsReachable(NET_ONION));
- BOOST_CHECK(!IsReachable(NET_I2P));
- BOOST_CHECK(!IsReachable(NET_CJDNS));
-
- SetReachable(NET_IPV4, true);
- SetReachable(NET_IPV6, true);
- SetReachable(NET_ONION, true);
- SetReachable(NET_I2P, true);
- SetReachable(NET_CJDNS, true);
-
- BOOST_CHECK(IsReachable(NET_IPV4));
- BOOST_CHECK(IsReachable(NET_IPV6));
- BOOST_CHECK(IsReachable(NET_ONION));
- BOOST_CHECK(IsReachable(NET_I2P));
- BOOST_CHECK(IsReachable(NET_CJDNS));
+ BOOST_CHECK(g_reachable_nets.Contains(NET_IPV4));
+ BOOST_CHECK(g_reachable_nets.Contains(NET_IPV6));
+ BOOST_CHECK(g_reachable_nets.Contains(NET_ONION));
+ BOOST_CHECK(g_reachable_nets.Contains(NET_I2P));
+ BOOST_CHECK(g_reachable_nets.Contains(NET_CJDNS));
+
+ g_reachable_nets.Remove(NET_IPV4);
+ g_reachable_nets.Remove(NET_IPV6);
+ g_reachable_nets.Remove(NET_ONION);
+ g_reachable_nets.Remove(NET_I2P);
+ g_reachable_nets.Remove(NET_CJDNS);
+
+ BOOST_CHECK(!g_reachable_nets.Contains(NET_IPV4));
+ BOOST_CHECK(!g_reachable_nets.Contains(NET_IPV6));
+ BOOST_CHECK(!g_reachable_nets.Contains(NET_ONION));
+ BOOST_CHECK(!g_reachable_nets.Contains(NET_I2P));
+ BOOST_CHECK(!g_reachable_nets.Contains(NET_CJDNS));
+
+ g_reachable_nets.Add(NET_IPV4);
+ g_reachable_nets.Add(NET_IPV6);
+ g_reachable_nets.Add(NET_ONION);
+ g_reachable_nets.Add(NET_I2P);
+ g_reachable_nets.Add(NET_CJDNS);
+
+ BOOST_CHECK(g_reachable_nets.Contains(NET_IPV4));
+ BOOST_CHECK(g_reachable_nets.Contains(NET_IPV6));
+ BOOST_CHECK(g_reachable_nets.Contains(NET_ONION));
+ BOOST_CHECK(g_reachable_nets.Contains(NET_I2P));
+ BOOST_CHECK(g_reachable_nets.Contains(NET_CJDNS));
}
BOOST_AUTO_TEST_CASE(LimitedAndReachable_NetworkCaseUnroutableAndInternal)
{
- BOOST_CHECK(IsReachable(NET_UNROUTABLE));
- BOOST_CHECK(IsReachable(NET_INTERNAL));
-
- SetReachable(NET_UNROUTABLE, false);
- SetReachable(NET_INTERNAL, false);
-
- BOOST_CHECK(IsReachable(NET_UNROUTABLE)); // Ignored for both networks
- BOOST_CHECK(IsReachable(NET_INTERNAL));
+ // Should be reachable by default.
+ BOOST_CHECK(g_reachable_nets.Contains(NET_UNROUTABLE));
+ BOOST_CHECK(g_reachable_nets.Contains(NET_INTERNAL));
+
+ g_reachable_nets.RemoveAll();
+
+ BOOST_CHECK(!g_reachable_nets.Contains(NET_UNROUTABLE));
+ BOOST_CHECK(!g_reachable_nets.Contains(NET_INTERNAL));
+
+ g_reachable_nets.Add(NET_IPV4);
+ g_reachable_nets.Add(NET_IPV6);
+ g_reachable_nets.Add(NET_ONION);
+ g_reachable_nets.Add(NET_I2P);
+ g_reachable_nets.Add(NET_CJDNS);
+ g_reachable_nets.Add(NET_UNROUTABLE);
+ g_reachable_nets.Add(NET_INTERNAL);
}
CNetAddr UtilBuildAddress(unsigned char p1, unsigned char p2, unsigned char p3, unsigned char p4)
@@ -776,13 +784,13 @@ BOOST_AUTO_TEST_CASE(LimitedAndReachable_CNetAddr)
{
CNetAddr addr = UtilBuildAddress(0x001, 0x001, 0x001, 0x001); // 1.1.1.1
- SetReachable(NET_IPV4, true);
- BOOST_CHECK(IsReachable(addr));
+ g_reachable_nets.Add(NET_IPV4);
+ BOOST_CHECK(g_reachable_nets.Contains(addr));
- SetReachable(NET_IPV4, false);
- BOOST_CHECK(!IsReachable(addr));
+ g_reachable_nets.Remove(NET_IPV4);
+ BOOST_CHECK(!g_reachable_nets.Contains(addr));
- SetReachable(NET_IPV4, true); // have to reset this, because this is stateful.
+ g_reachable_nets.Add(NET_IPV4); // have to reset this, because this is stateful.
}
@@ -790,7 +798,7 @@ BOOST_AUTO_TEST_CASE(LocalAddress_BasicLifecycle)
{
CService addr = CService(UtilBuildAddress(0x002, 0x001, 0x001, 0x001), 1000); // 2.1.1.1:1000
- SetReachable(NET_IPV4, true);
+ g_reachable_nets.Add(NET_IPV4);
BOOST_CHECK(!IsLocal(addr));
BOOST_CHECK(AddLocal(addr, 1000));
@@ -915,7 +923,7 @@ BOOST_AUTO_TEST_CASE(advertise_local_address)
ConnectionType::OUTBOUND_FULL_RELAY,
/*inbound_onion=*/false);
};
- SetReachable(NET_CJDNS, true);
+ g_reachable_nets.Add(NET_CJDNS);
CAddress addr_ipv4{Lookup("1.2.3.4", 8333, false).value(), NODE_NONE};
BOOST_REQUIRE(addr_ipv4.IsValid());
@@ -1080,9 +1088,9 @@ class V2TransportTester
bool reject{false};
auto msg = m_transport.GetReceivedMessage({}, reject);
if (reject) {
- ret.push_back(std::nullopt);
+ ret.emplace_back(std::nullopt);
} else {
- ret.push_back(std::move(msg));
+ ret.emplace_back(std::move(msg));
}
progress = true;
}
diff --git a/src/test/rbf_tests.cpp b/src/test/rbf_tests.cpp
index 10205cd641..fb6a3614c0 100644
--- a/src/test/rbf_tests.cpp
+++ b/src/test/rbf_tests.cpp
@@ -27,7 +27,7 @@ static inline CTransactionRef make_tx(const std::vector& inputs
tx.vin[i].prevout.n = 0;
// Add a witness so wtxid != txid
CScriptWitness witness;
- witness.stack.push_back(std::vector(i + 10));
+ witness.stack.emplace_back(i + 10);
tx.vin[i].scriptWitness = witness;
}
for (size_t i = 0; i < output_values.size(); ++i) {
diff --git a/src/test/rpc_tests.cpp b/src/test/rpc_tests.cpp
index 97a3408382..f9f24c19d9 100644
--- a/src/test/rpc_tests.cpp
+++ b/src/test/rpc_tests.cpp
@@ -428,11 +428,11 @@ BOOST_AUTO_TEST_CASE(rpc_getblockstats_calculate_percentiles_by_weight)
CAmount result[NUM_GETBLOCKSTATS_PERCENTILES] = { 0 };
for (int64_t i = 0; i < 100; i++) {
- feerates.emplace_back(std::make_pair(1 ,1));
+ feerates.emplace_back(1 ,1);
}
for (int64_t i = 0; i < 100; i++) {
- feerates.emplace_back(std::make_pair(2 ,1));
+ feerates.emplace_back(2 ,1);
}
CalculatePercentilesByWeight(result, feerates, total_weight);
@@ -447,11 +447,11 @@ BOOST_AUTO_TEST_CASE(rpc_getblockstats_calculate_percentiles_by_weight)
CAmount result2[NUM_GETBLOCKSTATS_PERCENTILES] = { 0 };
feerates.clear();
- feerates.emplace_back(std::make_pair(1, 9));
- feerates.emplace_back(std::make_pair(2 , 16)); //10th + 25th percentile
- feerates.emplace_back(std::make_pair(4 ,50)); //50th + 75th percentile
- feerates.emplace_back(std::make_pair(5 ,10));
- feerates.emplace_back(std::make_pair(9 ,15)); // 90th percentile
+ feerates.emplace_back(1, 9);
+ feerates.emplace_back(2 , 16); //10th + 25th percentile
+ feerates.emplace_back(4 ,50); //50th + 75th percentile
+ feerates.emplace_back(5 ,10);
+ feerates.emplace_back(9 ,15); // 90th percentile
CalculatePercentilesByWeight(result2, feerates, total_weight);
@@ -466,12 +466,12 @@ BOOST_AUTO_TEST_CASE(rpc_getblockstats_calculate_percentiles_by_weight)
CAmount result3[NUM_GETBLOCKSTATS_PERCENTILES] = { 0 };
feerates.clear();
- feerates.emplace_back(std::make_pair(1, 9));
- feerates.emplace_back(std::make_pair(2 , 11)); // 10th percentile
- feerates.emplace_back(std::make_pair(2 , 5)); // 25th percentile
- feerates.emplace_back(std::make_pair(4 ,50)); //50th + 75th percentile
- feerates.emplace_back(std::make_pair(5 ,10));
- feerates.emplace_back(std::make_pair(9 ,15)); // 90th percentile
+ feerates.emplace_back(1, 9);
+ feerates.emplace_back(2 , 11); // 10th percentile
+ feerates.emplace_back(2 , 5); // 25th percentile
+ feerates.emplace_back(4 ,50); //50th + 75th percentile
+ feerates.emplace_back(5 ,10);
+ feerates.emplace_back(9 ,15); // 90th percentile
CalculatePercentilesByWeight(result3, feerates, total_weight);
@@ -486,11 +486,11 @@ BOOST_AUTO_TEST_CASE(rpc_getblockstats_calculate_percentiles_by_weight)
CAmount result4[NUM_GETBLOCKSTATS_PERCENTILES] = { 0 };
feerates.clear();
- feerates.emplace_back(std::make_pair(1, 100));
- feerates.emplace_back(std::make_pair(2, 1));
- feerates.emplace_back(std::make_pair(3, 1));
- feerates.emplace_back(std::make_pair(3, 1));
- feerates.emplace_back(std::make_pair(999999, 1));
+ feerates.emplace_back(1, 100);
+ feerates.emplace_back(2, 1);
+ feerates.emplace_back(3, 1);
+ feerates.emplace_back(3, 1);
+ feerates.emplace_back(999999, 1);
CalculatePercentilesByWeight(result4, feerates, total_weight);
@@ -506,7 +506,7 @@ BOOST_AUTO_TEST_CASE(check_dup_param_names)
auto make_rpc = [](std::vector> param_names) {
std::vector params;
std::vector options;
- auto push_options = [&] { if (!options.empty()) params.emplace_back(RPCArg{strprintf("options%i", params.size()), RPCArg::Type::OBJ_NAMED_PARAMS, RPCArg::Optional::OMITTED, "", std::move(options)}); };
+ auto push_options = [&] { if (!options.empty()) params.emplace_back(strprintf("options%i", params.size()), RPCArg::Type::OBJ_NAMED_PARAMS, RPCArg::Optional::OMITTED, "", std::move(options)); };
for (auto& [param_name, param_type] : param_names) {
if (param_type == POSITIONAL) {
push_options();
diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp
index eec8bb7261..9ab03014bd 100644
--- a/src/test/script_tests.cpp
+++ b/src/test/script_tests.cpp
@@ -1499,8 +1499,8 @@ static CScriptWitness ScriptWitnessFromJSON(const UniValue& univalue)
#if defined(HAVE_CONSENSUS_LIB)
-/* Test simple (successful) usage of bitcoinconsensus_verify_script */
-BOOST_AUTO_TEST_CASE(bitcoinconsensus_verify_script_returns_true)
+/* Test simple (successful) usage of namecoinconsensus_verify_script */
+BOOST_AUTO_TEST_CASE(namecoinconsensus_verify_script_returns_true)
{
unsigned int libconsensus_flags = 0;
int nIn = 0;
@@ -1522,8 +1522,8 @@ BOOST_AUTO_TEST_CASE(bitcoinconsensus_verify_script_returns_true)
BOOST_CHECK_EQUAL(err, namecoinconsensus_ERR_OK);
}
-/* Test bitcoinconsensus_verify_script returns invalid tx index err*/
-BOOST_AUTO_TEST_CASE(bitcoinconsensus_verify_script_tx_index_err)
+/* Test namecoinconsensus_verify_script returns invalid tx index err*/
+BOOST_AUTO_TEST_CASE(namecoinconsensus_verify_script_tx_index_err)
{
unsigned int libconsensus_flags = 0;
int nIn = 3;
@@ -1545,8 +1545,8 @@ BOOST_AUTO_TEST_CASE(bitcoinconsensus_verify_script_tx_index_err)
BOOST_CHECK_EQUAL(err, namecoinconsensus_ERR_TX_INDEX);
}
-/* Test bitcoinconsensus_verify_script returns tx size mismatch err*/
-BOOST_AUTO_TEST_CASE(bitcoinconsensus_verify_script_tx_size)
+/* Test namecoinconsensus_verify_script returns tx size mismatch err*/
+BOOST_AUTO_TEST_CASE(namecoinconsensus_verify_script_tx_size)
{
unsigned int libconsensus_flags = 0;
int nIn = 0;
@@ -1568,8 +1568,8 @@ BOOST_AUTO_TEST_CASE(bitcoinconsensus_verify_script_tx_size)
BOOST_CHECK_EQUAL(err, namecoinconsensus_ERR_TX_SIZE_MISMATCH);
}
-/* Test bitcoinconsensus_verify_script returns invalid tx serialization error */
-BOOST_AUTO_TEST_CASE(bitcoinconsensus_verify_script_tx_serialization)
+/* Test namecoinconsensus_verify_script returns invalid tx serialization error */
+BOOST_AUTO_TEST_CASE(namecoinconsensus_verify_script_tx_serialization)
{
unsigned int libconsensus_flags = 0;
int nIn = 0;
@@ -1591,8 +1591,8 @@ BOOST_AUTO_TEST_CASE(bitcoinconsensus_verify_script_tx_serialization)
BOOST_CHECK_EQUAL(err, namecoinconsensus_ERR_TX_DESERIALIZE);
}
-/* Test bitcoinconsensus_verify_script returns amount required error */
-BOOST_AUTO_TEST_CASE(bitcoinconsensus_verify_script_amount_required_err)
+/* Test namecoinconsensus_verify_script returns amount required error */
+BOOST_AUTO_TEST_CASE(namecoinconsensus_verify_script_amount_required_err)
{
unsigned int libconsensus_flags = namecoinconsensus_SCRIPT_FLAGS_VERIFY_WITNESS;
int nIn = 0;
@@ -1614,8 +1614,8 @@ BOOST_AUTO_TEST_CASE(bitcoinconsensus_verify_script_amount_required_err)
BOOST_CHECK_EQUAL(err, namecoinconsensus_ERR_AMOUNT_REQUIRED);
}
-/* Test bitcoinconsensus_verify_script returns invalid flags err */
-BOOST_AUTO_TEST_CASE(bitcoinconsensus_verify_script_invalid_flags)
+/* Test namecoinconsensus_verify_script returns invalid flags err */
+BOOST_AUTO_TEST_CASE(namecoinconsensus_verify_script_invalid_flags)
{
unsigned int libconsensus_flags = 1 << 3;
int nIn = 0;
@@ -1637,6 +1637,37 @@ BOOST_AUTO_TEST_CASE(bitcoinconsensus_verify_script_invalid_flags)
BOOST_CHECK_EQUAL(err, namecoinconsensus_ERR_INVALID_FLAGS);
}
+/* Test namecoinconsensus_verify_script returns spent outputs required err */
+BOOST_AUTO_TEST_CASE(namecoinconsensus_verify_script_spent_outputs_required_err)
+{
+ unsigned int libconsensus_flags{namecoinconsensus_SCRIPT_FLAGS_VERIFY_TAPROOT};
+ const int nIn{0};
+
+ CScript scriptPubKey;
+ CScript scriptSig;
+ CScriptWitness wit;
+
+ scriptPubKey << OP_EQUAL;
+ CTransaction creditTx{BuildCreditingTransaction(scriptPubKey, 1)};
+ CTransaction spendTx{BuildSpendingTransaction(scriptSig, wit, creditTx)};
+
+ CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
+ stream << spendTx;
+
+ namecoinconsensus_error err;
+ int result{namecoinconsensus_verify_script_with_spent_outputs(scriptPubKey.data(), scriptPubKey.size(), creditTx.vout[0].nValue, UCharCast(stream.data()), stream.size(), nullptr, 0, nIn, libconsensus_flags, &err)};
+ BOOST_CHECK_EQUAL(result, 0);
+ BOOST_CHECK_EQUAL(err, namecoinconsensus_ERR_SPENT_OUTPUTS_REQUIRED);
+
+ result = namecoinconsensus_verify_script_with_amount(scriptPubKey.data(), scriptPubKey.size(), creditTx.vout[0].nValue, UCharCast(stream.data()), stream.size(), nIn, libconsensus_flags, &err);
+ BOOST_CHECK_EQUAL(result, 0);
+ BOOST_CHECK_EQUAL(err, namecoinconsensus_ERR_SPENT_OUTPUTS_REQUIRED);
+
+ result = namecoinconsensus_verify_script(scriptPubKey.data(), scriptPubKey.size(), UCharCast(stream.data()), stream.size(), nIn, libconsensus_flags, &err);
+ BOOST_CHECK_EQUAL(result, 0);
+ BOOST_CHECK_EQUAL(err, namecoinconsensus_ERR_SPENT_OUTPUTS_REQUIRED);
+}
+
#endif // defined(HAVE_CONSENSUS_LIB)
static std::vector AllConsensusFlags()
@@ -1685,12 +1716,29 @@ static void AssetTest(const UniValue& test)
PrecomputedTransactionData txdata;
txdata.Init(tx, std::vector(prevouts));
CachingTransactionSignatureChecker txcheck(&tx, idx, prevouts[idx].nValue, true, txdata);
+
+#if defined(HAVE_CONSENSUS_LIB)
+ CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
+ stream << tx;
+ std::vector utxos;
+ utxos.resize(prevouts.size());
+ for (size_t i = 0; i < prevouts.size(); i++) {
+ utxos[i].scriptPubKey = prevouts[i].scriptPubKey.data();
+ utxos[i].scriptPubKeySize = prevouts[i].scriptPubKey.size();
+ utxos[i].value = prevouts[i].nValue;
+ }
+#endif
+
for (const auto flags : ALL_CONSENSUS_FLAGS) {
// "final": true tests are valid for all flags. Others are only valid with flags that are
// a subset of test_flags.
if (fin || ((flags & test_flags) == flags)) {
bool ret = VerifyScript(tx.vin[idx].scriptSig, prevouts[idx].scriptPubKey, &tx.vin[idx].scriptWitness, flags, txcheck, nullptr);
BOOST_CHECK(ret);
+#if defined(HAVE_CONSENSUS_LIB)
+ int lib_ret = namecoinconsensus_verify_script_with_spent_outputs(prevouts[idx].scriptPubKey.data(), prevouts[idx].scriptPubKey.size(), prevouts[idx].nValue, UCharCast(stream.data()), stream.size(), utxos.data(), utxos.size(), idx, flags, nullptr);
+ BOOST_CHECK(lib_ret == 1);
+#endif
}
}
}
@@ -1702,11 +1750,28 @@ static void AssetTest(const UniValue& test)
PrecomputedTransactionData txdata;
txdata.Init(tx, std::vector(prevouts));
CachingTransactionSignatureChecker txcheck(&tx, idx, prevouts[idx].nValue, true, txdata);
+
+#if defined(HAVE_CONSENSUS_LIB)
+ CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
+ stream << tx;
+ std::vector utxos;
+ utxos.resize(prevouts.size());
+ for (size_t i = 0; i < prevouts.size(); i++) {
+ utxos[i].scriptPubKey = prevouts[i].scriptPubKey.data();
+ utxos[i].scriptPubKeySize = prevouts[i].scriptPubKey.size();
+ utxos[i].value = prevouts[i].nValue;
+ }
+#endif
+
for (const auto flags : ALL_CONSENSUS_FLAGS) {
// If a test is supposed to fail with test_flags, it should also fail with any superset thereof.
if ((flags & test_flags) == test_flags) {
bool ret = VerifyScript(tx.vin[idx].scriptSig, prevouts[idx].scriptPubKey, &tx.vin[idx].scriptWitness, flags, txcheck, nullptr);
BOOST_CHECK(!ret);
+#if defined(HAVE_CONSENSUS_LIB)
+ int lib_ret = namecoinconsensus_verify_script_with_spent_outputs(prevouts[idx].scriptPubKey.data(), prevouts[idx].scriptPubKey.size(), prevouts[idx].nValue, UCharCast(stream.data()), stream.size(), utxos.data(), utxos.size(), idx, flags, nullptr);
+ BOOST_CHECK(lib_ret == 0);
+#endif
}
}
}
diff --git a/src/test/settings_tests.cpp b/src/test/settings_tests.cpp
index eb11df0497..fa8ceb8dd6 100644
--- a/src/test/settings_tests.cpp
+++ b/src/test/settings_tests.cpp
@@ -119,16 +119,16 @@ static void CheckValues(const common::Settings& settings, const std::string& sin
BOOST_AUTO_TEST_CASE(Simple)
{
common::Settings settings;
- settings.command_line_options["name"].push_back("val1");
- settings.command_line_options["name"].push_back("val2");
- settings.ro_config["section"]["name"].push_back(2);
+ settings.command_line_options["name"].emplace_back("val1");
+ settings.command_line_options["name"].emplace_back("val2");
+ settings.ro_config["section"]["name"].emplace_back(2);
// The last given arg takes precedence when specified via commandline.
CheckValues(settings, R"("val2")", R"(["val1","val2",2])");
common::Settings settings2;
- settings2.ro_config["section"]["name"].push_back("val2");
- settings2.ro_config["section"]["name"].push_back("val3");
+ settings2.ro_config["section"]["name"].emplace_back("val2");
+ settings2.ro_config["section"]["name"].emplace_back("val3");
// The first given arg takes precedence when specified via config file.
CheckValues(settings2, R"("val2")", R"(["val2","val3"])");
@@ -141,7 +141,7 @@ BOOST_AUTO_TEST_CASE(Simple)
BOOST_AUTO_TEST_CASE(NullOverride)
{
common::Settings settings;
- settings.command_line_options["name"].push_back("value");
+ settings.command_line_options["name"].emplace_back("value");
BOOST_CHECK_EQUAL(R"("value")", GetSetting(settings, "section", "name", false, false, false).write().c_str());
settings.forced_settings["name"] = {};
BOOST_CHECK_EQUAL(R"(null)", GetSetting(settings, "section", "name", false, false, false).write().c_str());
@@ -202,11 +202,11 @@ BOOST_FIXTURE_TEST_CASE(Merge, MergeTestingSetup)
std::vector& dest) {
if (action == SET || action == SECTION_SET) {
for (int i = 0; i < 2; ++i) {
- dest.push_back(value_prefix + ToString(++value_suffix));
+ dest.emplace_back(value_prefix + ToString(++value_suffix));
desc += " " + name_prefix + name + "=" + dest.back().get_str();
}
} else if (action == NEGATE || action == SECTION_NEGATE) {
- dest.push_back(false);
+ dest.emplace_back(false);
desc += " " + name_prefix + "no" + name;
}
};
diff --git a/src/test/sighash_tests.cpp b/src/test/sighash_tests.cpp
index 178b16772b..9653edd84b 100644
--- a/src/test/sighash_tests.cpp
+++ b/src/test/sighash_tests.cpp
@@ -100,7 +100,7 @@ void static RandomTransaction(CMutableTransaction& tx, bool fSingle)
int ins = (InsecureRandBits(2)) + 1;
int outs = fSingle ? ins : (InsecureRandBits(2)) + 1;
for (int in = 0; in < ins; in++) {
- tx.vin.push_back(CTxIn());
+ tx.vin.emplace_back();
CTxIn &txin = tx.vin.back();
txin.prevout.hash = InsecureRand256();
txin.prevout.n = InsecureRandBits(2);
@@ -108,7 +108,7 @@ void static RandomTransaction(CMutableTransaction& tx, bool fSingle)
txin.nSequence = (InsecureRandBool()) ? InsecureRand32() : std::numeric_limits::max();
}
for (int out = 0; out < outs; out++) {
- tx.vout.push_back(CTxOut());
+ tx.vout.emplace_back();
CTxOut &txout = tx.vout.back();
txout.nValue = InsecureRandMoneyAmount();
RandomScript(txout.scriptPubKey);
diff --git a/src/test/sigopcount_tests.cpp b/src/test/sigopcount_tests.cpp
index ec9490d745..c0bed50e1d 100644
--- a/src/test/sigopcount_tests.cpp
+++ b/src/test/sigopcount_tests.cpp
@@ -160,8 +160,8 @@ BOOST_AUTO_TEST_CASE(GetTxSigOpCost)
CScript scriptPubKey = GetScriptForDestination(WitnessV0KeyHash(pubkey));
CScript scriptSig = CScript();
CScriptWitness scriptWitness;
- scriptWitness.stack.push_back(std::vector(0));
- scriptWitness.stack.push_back(std::vector(0));
+ scriptWitness.stack.emplace_back(0);
+ scriptWitness.stack.emplace_back(0);
BuildTxs(spendingTx, coins, creationTx, scriptPubKey, scriptSig, scriptWitness);
@@ -189,8 +189,8 @@ BOOST_AUTO_TEST_CASE(GetTxSigOpCost)
CScript scriptPubKey = GetScriptForDestination(ScriptHash(scriptSig));
scriptSig = CScript() << ToByteVector(scriptSig);
CScriptWitness scriptWitness;
- scriptWitness.stack.push_back(std::vector(0));
- scriptWitness.stack.push_back(std::vector(0));
+ scriptWitness.stack.emplace_back(0);
+ scriptWitness.stack.emplace_back(0);
BuildTxs(spendingTx, coins, creationTx, scriptPubKey, scriptSig, scriptWitness);
assert(GetTransactionSigOpCost(CTransaction(spendingTx), coins, flags) == 1);
@@ -203,9 +203,9 @@ BOOST_AUTO_TEST_CASE(GetTxSigOpCost)
CScript scriptPubKey = GetScriptForDestination(WitnessV0ScriptHash(witnessScript));
CScript scriptSig = CScript();
CScriptWitness scriptWitness;
- scriptWitness.stack.push_back(std::vector(0));
- scriptWitness.stack.push_back(std::vector(0));
- scriptWitness.stack.push_back(std::vector(witnessScript.begin(), witnessScript.end()));
+ scriptWitness.stack.emplace_back(0);
+ scriptWitness.stack.emplace_back(0);
+ scriptWitness.stack.emplace_back(witnessScript.begin(), witnessScript.end());
BuildTxs(spendingTx, coins, creationTx, scriptPubKey, scriptSig, scriptWitness);
assert(GetTransactionSigOpCost(CTransaction(spendingTx), coins, flags) == 2);
@@ -220,9 +220,9 @@ BOOST_AUTO_TEST_CASE(GetTxSigOpCost)
CScript scriptPubKey = GetScriptForDestination(ScriptHash(redeemScript));
CScript scriptSig = CScript() << ToByteVector(redeemScript);
CScriptWitness scriptWitness;
- scriptWitness.stack.push_back(std::vector(0));
- scriptWitness.stack.push_back(std::vector(0));
- scriptWitness.stack.push_back(std::vector(witnessScript.begin(), witnessScript.end()));
+ scriptWitness.stack.emplace_back(0);
+ scriptWitness.stack.emplace_back(0);
+ scriptWitness.stack.emplace_back(witnessScript.begin(), witnessScript.end());
BuildTxs(spendingTx, coins, creationTx, scriptPubKey, scriptSig, scriptWitness);
assert(GetTransactionSigOpCost(CTransaction(spendingTx), coins, flags) == 2);
diff --git a/src/test/txpackage_tests.cpp b/src/test/txpackage_tests.cpp
index 6a7594dc2f..7a8dd96a40 100644
--- a/src/test/txpackage_tests.cpp
+++ b/src/test/txpackage_tests.cpp
@@ -173,9 +173,9 @@ BOOST_FIXTURE_TEST_CASE(noncontextual_package_tests, TestChain100Setup)
auto parent = MakeTransactionRef(CreateValidMempoolTransaction(m_coinbase_txns[i + 1],
0, 0, coinbaseKey, spk, CAmount(48 * COIN), false));
package.emplace_back(parent);
- child.vin.push_back(CTxIn(COutPoint(parent->GetHash(), 0)));
+ child.vin.emplace_back(COutPoint(parent->GetHash(), 0));
}
- child.vout.push_back(CTxOut(47 * COIN, spk2));
+ child.vout.emplace_back(47 * COIN, spk2);
// The child must be in the package.
BOOST_CHECK(!IsChildWithParents(package));
@@ -201,20 +201,20 @@ BOOST_FIXTURE_TEST_CASE(noncontextual_package_tests, TestChain100Setup)
// 2 Parents and 1 Child where one parent depends on the other.
{
CMutableTransaction mtx_parent;
- mtx_parent.vin.push_back(CTxIn(COutPoint(m_coinbase_txns[0]->GetHash(), 0)));
- mtx_parent.vout.push_back(CTxOut(20 * COIN, spk));
- mtx_parent.vout.push_back(CTxOut(20 * COIN, spk2));
+ mtx_parent.vin.emplace_back(COutPoint(m_coinbase_txns[0]->GetHash(), 0));
+ mtx_parent.vout.emplace_back(20 * COIN, spk);
+ mtx_parent.vout.emplace_back(20 * COIN, spk2);
CTransactionRef tx_parent = MakeTransactionRef(mtx_parent);
CMutableTransaction mtx_parent_also_child;
- mtx_parent_also_child.vin.push_back(CTxIn(COutPoint(tx_parent->GetHash(), 0)));
- mtx_parent_also_child.vout.push_back(CTxOut(20 * COIN, spk));
+ mtx_parent_also_child.vin.emplace_back(COutPoint(tx_parent->GetHash(), 0));
+ mtx_parent_also_child.vout.emplace_back(20 * COIN, spk);
CTransactionRef tx_parent_also_child = MakeTransactionRef(mtx_parent_also_child);
CMutableTransaction mtx_child;
- mtx_child.vin.push_back(CTxIn(COutPoint(tx_parent->GetHash(), 1)));
- mtx_child.vin.push_back(CTxIn(COutPoint(tx_parent_also_child->GetHash(), 0)));
- mtx_child.vout.push_back(CTxOut(39 * COIN, spk));
+ mtx_child.vin.emplace_back(COutPoint(tx_parent->GetHash(), 1));
+ mtx_child.vin.emplace_back(COutPoint(tx_parent_also_child->GetHash(), 0));
+ mtx_child.vout.emplace_back(39 * COIN, spk);
CTransactionRef tx_child = MakeTransactionRef(mtx_child);
PackageValidationState state;
@@ -301,7 +301,7 @@ BOOST_FIXTURE_TEST_CASE(package_submission_tests, TestChain100Setup)
// missing inputs, so the package validation isn't expected to happen.
{
CScriptWitness bad_witness;
- bad_witness.stack.push_back(std::vector(1));
+ bad_witness.stack.emplace_back(1);
CMutableTransaction mtx_parent_invalid{mtx_parent};
mtx_parent_invalid.vin[0].scriptWitness = bad_witness;
CTransactionRef tx_parent_invalid = MakeTransactionRef(mtx_parent_invalid);
@@ -322,7 +322,7 @@ BOOST_FIXTURE_TEST_CASE(package_submission_tests, TestChain100Setup)
}
// Child with missing parent.
- mtx_child.vin.push_back(CTxIn(COutPoint(package_unrelated[0]->GetHash(), 0)));
+ mtx_child.vin.emplace_back(COutPoint(package_unrelated[0]->GetHash(), 0));
Package package_missing_parent;
package_missing_parent.push_back(tx_parent);
package_missing_parent.push_back(MakeTransactionRef(mtx_child));
@@ -404,12 +404,12 @@ BOOST_FIXTURE_TEST_CASE(package_witness_swap_tests, TestChain100Setup)
// Make two children with the same txid but different witnesses.
CScriptWitness witness1;
- witness1.stack.push_back(std::vector(1));
- witness1.stack.push_back(std::vector(witnessScript.begin(), witnessScript.end()));
+ witness1.stack.emplace_back(1);
+ witness1.stack.emplace_back(witnessScript.begin(), witnessScript.end());
CScriptWitness witness2(witness1);
- witness2.stack.push_back(std::vector(2));
- witness2.stack.push_back(std::vector(witnessScript.begin(), witnessScript.end()));
+ witness2.stack.emplace_back(2);
+ witness2.stack.emplace_back(witnessScript.begin(), witnessScript.end());
CKey child_key;
child_key.MakeNewKey(true);
@@ -529,7 +529,7 @@ BOOST_FIXTURE_TEST_CASE(package_witness_swap_tests, TestChain100Setup)
CScript acs_script = CScript() << OP_TRUE;
CScript acs_spk = GetScriptForDestination(WitnessV0ScriptHash(acs_script));
CScriptWitness acs_witness;
- acs_witness.stack.push_back(std::vector(acs_script.begin(), acs_script.end()));
+ acs_witness.stack.emplace_back(acs_script.begin(), acs_script.end());
// parent1 will already be in the mempool
auto mtx_parent1 = CreateValidMempoolTransaction(/*input_transaction=*/m_coinbase_txns[1], /*input_vout=*/0,
@@ -543,11 +543,11 @@ BOOST_FIXTURE_TEST_CASE(package_witness_swap_tests, TestChain100Setup)
CScript grandparent2_script = CScript() << OP_DROP << OP_TRUE;
CScript grandparent2_spk = GetScriptForDestination(WitnessV0ScriptHash(grandparent2_script));
CScriptWitness parent2_witness1;
- parent2_witness1.stack.push_back(std::vector(1));
- parent2_witness1.stack.push_back(std::vector(grandparent2_script.begin(), grandparent2_script.end()));
+ parent2_witness1.stack.emplace_back(1);
+ parent2_witness1.stack.emplace_back(grandparent2_script.begin(), grandparent2_script.end());
CScriptWitness parent2_witness2;
- parent2_witness2.stack.push_back(std::vector(2));
- parent2_witness2.stack.push_back(std::vector(grandparent2_script.begin(), grandparent2_script.end()));
+ parent2_witness2.stack.emplace_back(2);
+ parent2_witness2.stack.emplace_back(grandparent2_script.begin(), grandparent2_script.end());
// Create grandparent2 creating an output with multiple spending paths. Submit to mempool.
auto mtx_grandparent2 = CreateValidMempoolTransaction(/*input_transaction=*/m_coinbase_txns[2], /*input_vout=*/0,
@@ -593,13 +593,13 @@ BOOST_FIXTURE_TEST_CASE(package_witness_swap_tests, TestChain100Setup)
CScript mixed_child_spk = GetScriptForDestination(WitnessV0KeyHash(mixed_grandchild_key.GetPubKey()));
CMutableTransaction mtx_mixed_child;
- mtx_mixed_child.vin.push_back(CTxIn(COutPoint(ptx_parent1->GetHash(), 0)));
- mtx_mixed_child.vin.push_back(CTxIn(COutPoint(ptx_parent2_v1->GetHash(), 0)));
- mtx_mixed_child.vin.push_back(CTxIn(COutPoint(ptx_parent3->GetHash(), 0)));
+ mtx_mixed_child.vin.emplace_back(COutPoint(ptx_parent1->GetHash(), 0));
+ mtx_mixed_child.vin.emplace_back(COutPoint(ptx_parent2_v1->GetHash(), 0));
+ mtx_mixed_child.vin.emplace_back(COutPoint(ptx_parent3->GetHash(), 0));
mtx_mixed_child.vin[0].scriptWitness = acs_witness;
mtx_mixed_child.vin[1].scriptWitness = acs_witness;
mtx_mixed_child.vin[2].scriptWitness = acs_witness;
- mtx_mixed_child.vout.push_back(CTxOut((48 + 49 + 50 - 1) * COIN, mixed_child_spk));
+ mtx_mixed_child.vout.emplace_back((48 + 49 + 50 - 1) * COIN, mixed_child_spk);
CTransactionRef ptx_mixed_child = MakeTransactionRef(mtx_mixed_child);
package_mixed.push_back(ptx_mixed_child);
diff --git a/src/test/util/setup_common.cpp b/src/test/util/setup_common.cpp
index 57e189cdad..38ed9383b5 100644
--- a/src/test/util/setup_common.cpp
+++ b/src/test/util/setup_common.cpp
@@ -408,7 +408,7 @@ std::vector TestChain100Setup::PopulateMempool(FastRandomContex
for (size_t n{0}; n < num_inputs; ++n) {
if (unspent_prevouts.empty()) break;
const auto& [prevout, amount] = unspent_prevouts.front();
- mtx.vin.push_back(CTxIn(prevout, CScript()));
+ mtx.vin.emplace_back(prevout, CScript());
total_in += amount;
unspent_prevouts.pop_front();
}
@@ -417,7 +417,7 @@ std::vector TestChain100Setup::PopulateMempool(FastRandomContex
const CAmount amount_per_output = (total_in - fee) / num_outputs;
for (size_t n{0}; n < num_outputs; ++n) {
CScript spk = CScript() << CScriptNum(num_transactions + n);
- mtx.vout.push_back(CTxOut(amount_per_output, spk));
+ mtx.vout.emplace_back(amount_per_output, spk);
}
CTransactionRef ptx = MakeTransactionRef(mtx);
mempool_transactions.push_back(ptx);
@@ -426,7 +426,7 @@ std::vector TestChain100Setup::PopulateMempool(FastRandomContex
// it can be used to build a more complex transaction graph. Insert randomly into
// unspent_prevouts for extra randomness in the resulting structures.
for (size_t n{0}; n < num_outputs; ++n) {
- unspent_prevouts.push_back(std::make_pair(COutPoint(ptx->GetHash(), n), amount_per_output));
+ unspent_prevouts.emplace_back(COutPoint(ptx->GetHash(), n), amount_per_output);
std::swap(unspent_prevouts.back(), unspent_prevouts[det_rand.randrange(unspent_prevouts.size())]);
}
}
@@ -456,8 +456,8 @@ void TestChain100Setup::MockMempoolMinFee(const CFeeRate& target_feerate)
// Manually create an invalid transaction. Manually set the fee in the CTxMemPoolEntry to
// achieve the exact target feerate.
CMutableTransaction mtx = CMutableTransaction();
- mtx.vin.push_back(CTxIn{COutPoint{g_insecure_rand_ctx.rand256(), 0}});
- mtx.vout.push_back(CTxOut(1 * COIN, GetScriptForDestination(WitnessV0ScriptHash(CScript() << OP_TRUE))));
+ mtx.vin.emplace_back(COutPoint{g_insecure_rand_ctx.rand256(), 0});
+ mtx.vout.emplace_back(1 * COIN, GetScriptForDestination(WitnessV0ScriptHash(CScript() << OP_TRUE)));
const auto tx{MakeTransactionRef(mtx)};
LockPoints lp;
// The new mempool min feerate is equal to the removed package's feerate + incremental feerate.
diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp
index 95bdd7e16d..af2b6df673 100644
--- a/src/test/util_tests.cpp
+++ b/src/test/util_tests.cpp
@@ -1023,9 +1023,9 @@ BOOST_AUTO_TEST_CASE(test_FormatParagraph)
BOOST_AUTO_TEST_CASE(test_FormatSubVersion)
{
std::vector comments;
- comments.push_back(std::string("comment1"));
+ comments.emplace_back("comment1");
std::vector comments2;
- comments2.push_back(std::string("comment1"));
+ comments2.emplace_back("comment1");
comments2.push_back(SanitizeString(std::string("Comment2; .,_?@-; !\"#$%&'()*+/<=>[]\\^`{|}~"), SAFE_CHARS_UA_COMMENT)); // Semicolon is discouraged but not forbidden by BIP-0014
BOOST_CHECK_EQUAL(FormatSubVersion("Test", 99900, std::vector()),std::string("/Test:9.99.0/"));
BOOST_CHECK_EQUAL(FormatSubVersion("Test", 99900, comments),std::string("/Test:9.99.0(comment1)/"));
diff --git a/src/test/util_threadnames_tests.cpp b/src/test/util_threadnames_tests.cpp
index ae913939e8..45d3a58fd3 100644
--- a/src/test/util_threadnames_tests.cpp
+++ b/src/test/util_threadnames_tests.cpp
@@ -40,7 +40,7 @@ std::set RenameEnMasse(int num_threads)
threads.reserve(num_threads);
for (int i = 0; i < num_threads; ++i) {
- threads.push_back(std::thread(RenameThisThread, i));
+ threads.emplace_back(RenameThisThread, i);
}
for (std::thread& thread : threads) thread.join();
diff --git a/src/test/validation_block_tests.cpp b/src/test/validation_block_tests.cpp
index 20662f8ff6..16f8d15318 100644
--- a/src/test/validation_block_tests.cpp
+++ b/src/test/validation_block_tests.cpp
@@ -119,7 +119,7 @@ std::shared_ptr MinerTestingSetup::BadBlock(const uint256& prev_ha
auto pblock = Block(prev_hash);
CMutableTransaction coinbase_spend;
- coinbase_spend.vin.push_back(CTxIn(COutPoint(pblock->vtx[0]->GetHash(), 0), CScript(), 0));
+ coinbase_spend.vin.emplace_back(COutPoint(pblock->vtx[0]->GetHash(), 0), CScript(), 0);
coinbase_spend.vout.push_back(pblock->vtx[0]->vout[0]);
CTransactionRef tx = MakeTransactionRef(coinbase_spend);
@@ -247,7 +247,7 @@ BOOST_AUTO_TEST_CASE(mempool_locks_reorg)
std::vector txs;
for (int num_txs = 22; num_txs > 0; --num_txs) {
CMutableTransaction mtx;
- mtx.vin.push_back(CTxIn{COutPoint{last_mined->vtx[0]->GetHash(), 1}, CScript{}});
+ mtx.vin.emplace_back(COutPoint{last_mined->vtx[0]->GetHash(), 1}, CScript{});
mtx.vin[0].scriptWitness.stack.push_back(WITNESS_STACK_ELEM_OP_TRUE);
mtx.vout.push_back(last_mined->vtx[0]->vout[1]);
mtx.vout[0].nValue -= 10000;
diff --git a/src/torcontrol.cpp b/src/torcontrol.cpp
index 4c99aa5746..60cf31a964 100644
--- a/src/torcontrol.cpp
+++ b/src/torcontrol.cpp
@@ -409,7 +409,7 @@ void TorController::get_socks_cb(TorControlConnection& _conn, const TorControlRe
//
// If NET_ONION is not reachable, then none of -proxy or -onion was given.
// Since we are here, then -torcontrol and -torpassword were given.
- SetReachable(NET_ONION, true);
+ g_reachable_nets.Add(NET_ONION);
}
}
diff --git a/src/txmempool.cpp b/src/txmempool.cpp
index fdb092a6e0..c98e7d8c90 100644
--- a/src/txmempool.cpp
+++ b/src/txmempool.cpp
@@ -1036,7 +1036,7 @@ void CCoinsViewMemPool::PackageAddTransaction(const CTransactionRef& tx)
{
for (unsigned int n = 0; n < tx->vout.size(); ++n) {
m_temp_added.emplace(COutPoint(tx->GetHash(), n), Coin(tx->vout[n], MEMPOOL_HEIGHT, false));
- m_non_base_coins.emplace(COutPoint(tx->GetHash(), n));
+ m_non_base_coins.emplace(tx->GetHash(), n);
}
}
void CCoinsViewMemPool::Reset()
diff --git a/src/validation.cpp b/src/validation.cpp
index ca1a9cb594..bc7dec6d6c 100644
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -2456,7 +2456,7 @@ bool Chainstate::ConnectBlock(const CBlock& block, BlockValidationState& state,
CTxUndo undoDummy;
if (i > 0) {
- blockundo.vtxundo.push_back(CTxUndo());
+ blockundo.vtxundo.emplace_back();
}
UpdateCoins(tx, view, i == 0 ? undoDummy : blockundo.vtxundo.back(), pindex->nHeight);
ApplyNameTransaction(tx, pindex->nHeight, view, blockundo);
@@ -5821,8 +5821,8 @@ void ChainstateManager::MaybeRebalanceCaches()
assert(ibd_usable || snapshot_usable);
if (ibd_usable && !snapshot_usable) {
- LogPrintf("[snapshot] allocating all cache to the IBD chainstate\n");
- // Allocate everything to the IBD chainstate.
+ // Allocate everything to the IBD chainstate. This will always happen
+ // when we are not using a snapshot.
m_ibd_chainstate->ResizeCoinsCaches(m_total_coinstip_cache, m_total_coinsdb_cache);
}
else if (snapshot_usable && !ibd_usable) {
diff --git a/src/wallet/rpc/backup.cpp b/src/wallet/rpc/backup.cpp
index 1d80678d9f..e55ffc814e 100644
--- a/src/wallet/rpc/backup.cpp
+++ b/src/wallet/rpc/backup.cpp
@@ -573,13 +573,13 @@ RPCHelpMan importwallet()
}
}
nTimeBegin = std::min(nTimeBegin, nTime);
- keys.push_back(std::make_tuple(key, nTime, fLabel, strLabel));
+ keys.emplace_back(key, nTime, fLabel, strLabel);
} else if(IsHex(vstr[0])) {
std::vector vData(ParseHex(vstr[0]));
CScript script = CScript(vData.begin(), vData.end());
int64_t birth_time = ParseISO8601DateTime(vstr[1]);
if (birth_time > 0) nTimeBegin = std::min(nTimeBegin, birth_time);
- scripts.push_back(std::pair(script, birth_time));
+ scripts.emplace_back(script, birth_time);
}
}
file.close();
@@ -759,7 +759,7 @@ RPCHelpMan dumpwallet()
std::vector > vKeyBirth;
vKeyBirth.reserve(mapKeyBirth.size());
for (const auto& entry : mapKeyBirth) {
- vKeyBirth.push_back(std::make_pair(entry.second, entry.first));
+ vKeyBirth.emplace_back(entry.second, entry.first);
}
mapKeyBirth.clear();
std::sort(vKeyBirth.begin(), vKeyBirth.end());
diff --git a/src/wallet/salvage.cpp b/src/wallet/salvage.cpp
index 0a0745b1c5..04c02b0dcc 100644
--- a/src/wallet/salvage.cpp
+++ b/src/wallet/salvage.cpp
@@ -146,7 +146,7 @@ bool RecoverDatabaseFile(const ArgsManager& args, const fs::path& file_path, bil
warnings.push_back(Untranslated("Salvage: WARNING: Number of keys in data does not match number of values."));
break;
}
- salvagedData.push_back(make_pair(ParseHex(keyHex), ParseHex(valueHex)));
+ salvagedData.emplace_back(ParseHex(keyHex), ParseHex(valueHex));
}
}
diff --git a/src/wallet/scriptpubkeyman.cpp b/src/wallet/scriptpubkeyman.cpp
index 8309eabbf8..ae6d255a14 100644
--- a/src/wallet/scriptpubkeyman.cpp
+++ b/src/wallet/scriptpubkeyman.cpp
@@ -1908,7 +1908,7 @@ std::optional LegacyScriptPubKeyMan::MigrateToDescriptor()
std::string desc_str;
bool watchonly = !desc->ToPrivateString(*this, desc_str);
if (watchonly && !m_storage.IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
- out.watch_descs.push_back({desc->ToString(), creation_time});
+ out.watch_descs.emplace_back(desc->ToString(), creation_time);
// Get the scriptPubKeys without writing this to the wallet
FlatSigningProvider provider;
@@ -1977,14 +1977,14 @@ std::optional LegacyScriptPubKeyMan::MigrateToDescriptor()
assert(IsMine(sh_spk) == ISMINE_NO && IsMine(witprog) == ISMINE_NO && IsMine(sh_wsh_spk) == ISMINE_NO);
std::unique_ptr sh_desc = InferDescriptor(sh_spk, *GetSolvingProvider(sh_spk));
- out.solvable_descs.push_back({sh_desc->ToString(), creation_time});
+ out.solvable_descs.emplace_back(sh_desc->ToString(), creation_time);
const auto desc = InferDescriptor(witprog, *this);
if (desc->IsSolvable()) {
std::unique_ptr wsh_desc = InferDescriptor(witprog, *GetSolvingProvider(witprog));
- out.solvable_descs.push_back({wsh_desc->ToString(), creation_time});
+ out.solvable_descs.emplace_back(wsh_desc->ToString(), creation_time);
std::unique_ptr sh_wsh_desc = InferDescriptor(sh_wsh_spk, *GetSolvingProvider(sh_wsh_spk));
- out.solvable_descs.push_back({sh_wsh_desc->ToString(), creation_time});
+ out.solvable_descs.emplace_back(sh_wsh_desc->ToString(), creation_time);
}
}
}
diff --git a/src/wallet/spend.cpp b/src/wallet/spend.cpp
index 30a7ac44ff..718487ad22 100644
--- a/src/wallet/spend.cpp
+++ b/src/wallet/spend.cpp
@@ -1177,7 +1177,7 @@ static util::Result CreateTransactionInternal(
// behavior."
const uint32_t nSequence{coin_control.m_signal_bip125_rbf.value_or(wallet.m_signal_rbf) ? MAX_BIP125_RBF_SEQUENCE : CTxIn::MAX_SEQUENCE_NONFINAL};
for (const auto& coin : selected_coins) {
- txNew.vin.push_back(CTxIn(coin->outpoint, CScript(), nSequence));
+ txNew.vin.emplace_back(coin->outpoint, CScript(), nSequence);
}
DiscourageFeeSniping(txNew, rng_fast, wallet.chain(), wallet.GetLastBlockHash(), wallet.GetLastBlockHeight());
diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp
index 78202d6ff9..7774b66c15 100644
--- a/src/wallet/test/wallet_tests.cpp
+++ b/src/wallet/test/wallet_tests.cpp
@@ -49,7 +49,7 @@ BOOST_FIXTURE_TEST_SUITE(wallet_tests, WalletTestingSetup)
static CMutableTransaction TestSimpleSpend(const CTransaction& from, uint32_t index, const CKey& key, const CScript& pubkey)
{
CMutableTransaction mtx;
- mtx.vout.push_back({from.vout[index].nValue - DEFAULT_TRANSACTION_MAXFEE, pubkey});
+ mtx.vout.emplace_back(from.vout[index].nValue - DEFAULT_TRANSACTION_MAXFEE, pubkey);
mtx.vin.push_back({CTxIn{from.GetHash(), index}});
FillableSigningProvider keystore;
keystore.AddKey(key);
@@ -950,8 +950,8 @@ BOOST_FIXTURE_TEST_CASE(wallet_sync_tx_invalid_state_test, TestingSetup)
const auto op_dest{*Assert(wallet.GetNewDestination(OutputType::BECH32M, ""))};
CMutableTransaction mtx;
- mtx.vout.push_back({COIN, GetScriptForDestination(op_dest)});
- mtx.vin.push_back(CTxIn(g_insecure_rand_ctx.rand256(), 0));
+ mtx.vout.emplace_back(COIN, GetScriptForDestination(op_dest));
+ mtx.vin.emplace_back(g_insecure_rand_ctx.rand256(), 0);
const auto& tx_id_to_spend = wallet.AddToWallet(MakeTransactionRef(mtx), TxStateInMempool{})->GetHash();
{
@@ -966,7 +966,7 @@ BOOST_FIXTURE_TEST_CASE(wallet_sync_tx_invalid_state_test, TestingSetup)
// 2) Verify that the available balance of this new tx and the old one is updated (prev tx is marked dirty)
mtx.vin.clear();
- mtx.vin.push_back(CTxIn(tx_id_to_spend, 0));
+ mtx.vin.emplace_back(tx_id_to_spend, 0);
wallet.transactionAddedToMempool(MakeTransactionRef(mtx));
const uint256& good_tx_id = mtx.GetHash();
@@ -987,7 +987,7 @@ BOOST_FIXTURE_TEST_CASE(wallet_sync_tx_invalid_state_test, TestingSetup)
// verify that we are not moving forward if the wallet cannot store it
GetMockableDatabase(wallet).m_pass = false;
mtx.vin.clear();
- mtx.vin.push_back(CTxIn(good_tx_id, 0));
+ mtx.vin.emplace_back(good_tx_id, 0);
BOOST_CHECK_EXCEPTION(wallet.transactionAddedToMempool(MakeTransactionRef(mtx)),
std::runtime_error,
HasReason("DB error adding transaction to wallet, write failed"));
diff --git a/src/wallet/transaction.h b/src/wallet/transaction.h
index 51ae4119ab..9d456d118e 100644
--- a/src/wallet/transaction.h
+++ b/src/wallet/transaction.h
@@ -30,10 +30,12 @@ struct TxStateConfirmed {
int position_in_block;
explicit TxStateConfirmed(const uint256& block_hash, int height, int index) : confirmed_block_hash(block_hash), confirmed_block_height(height), position_in_block(index) {}
+ std::string toString() const { return strprintf("Confirmed (block=%s, height=%i, index=%i)", confirmed_block_hash.ToString(), confirmed_block_height, position_in_block); }
};
//! State of transaction added to mempool.
struct TxStateInMempool {
+ std::string toString() const { return strprintf("InMempool"); }
};
//! State of rejected transaction that conflicts with a confirmed block.
@@ -42,6 +44,7 @@ struct TxStateConflicted {
int conflicting_block_height;
explicit TxStateConflicted(const uint256& block_hash, int height) : conflicting_block_hash(block_hash), conflicting_block_height(height) {}
+ std::string toString() const { return strprintf("Conflicted (block=%s, height=%i)", conflicting_block_hash.ToString(), conflicting_block_height); }
};
//! State of transaction not confirmed or conflicting with a known block and
@@ -52,6 +55,7 @@ struct TxStateInactive {
bool abandoned;
explicit TxStateInactive(bool abandoned = false) : abandoned(abandoned) {}
+ std::string toString() const { return strprintf("Inactive (abandoned=%i)", abandoned); }
};
//! State of transaction loaded in an unrecognized state with unexpected hash or
@@ -63,6 +67,7 @@ struct TxStateUnrecognized {
int index;
TxStateUnrecognized(const uint256& block_hash, int index) : block_hash(block_hash), index(index) {}
+ std::string toString() const { return strprintf("Unrecognized (block=%s, index=%i)", block_hash.ToString(), index); }
};
//! All possible CWalletTx states
@@ -110,6 +115,12 @@ static inline int TxStateSerializedIndex(const TxState& state)
}, state);
}
+//! Return TxState or SyncTxState as a string for logging or debugging.
+template
+std::string TxStateString(const T& state)
+{
+ return std::visit([](const auto& s) { return s.toString(); }, state);
+}
/**
* Cachable amount subdivided into watchonly and spendable parts.
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index c572aa4697..4079251b73 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -1132,7 +1132,7 @@ CWalletTx* CWallet::AddToWallet(CTransactionRef tx, const TxState& state, const
}
//// debug print
- WalletLogPrintf("AddToWallet %s %s%s\n", hash.ToString(), (fInsertedNew ? "new" : ""), (fUpdated ? "update" : ""));
+ WalletLogPrintf("AddToWallet %s %s%s %s\n", hash.ToString(), (fInsertedNew ? "new" : ""), (fUpdated ? "update" : ""), TxStateString(state));
// Write to disk
if (fInsertedNew || fUpdated)
@@ -4343,7 +4343,7 @@ util::Result MigrateLegacyToDescriptor(const std::string& walle
// Remember this wallet's walletdir to remove after unloading
std::vector wallet_dirs;
- wallet_dirs.push_back(fs::PathFromString(local_wallet->GetDatabase().Filename()).parent_path());
+ wallet_dirs.emplace_back(fs::PathFromString(local_wallet->GetDatabase().Filename()).parent_path());
// Unload the wallet locally
assert(local_wallet.use_count() == 1);
@@ -4356,7 +4356,7 @@ util::Result MigrateLegacyToDescriptor(const std::string& walle
// Get the directories to remove after unloading
for (std::shared_ptr& w : created_wallets) {
- wallet_dirs.push_back(fs::PathFromString(w->GetDatabase().Filename()).parent_path());
+ wallet_dirs.emplace_back(fs::PathFromString(w->GetDatabase().Filename()).parent_path());
}
// Unload the wallets
diff --git a/test/functional/feature_assumeutxo.py b/test/functional/feature_assumeutxo.py
index a5c756582c..999e9d8efa 100755
--- a/test/functional/feature_assumeutxo.py
+++ b/test/functional/feature_assumeutxo.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2021 The Bitcoin Core developers
+# Copyright (c) 2021-present The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Test for assumeutxo, a means of quickly bootstrapping a node using
@@ -17,10 +17,8 @@
Interesting test cases could be loading an assumeutxo snapshot file with:
-- TODO: An invalid hash
-- TODO: Valid hash but invalid snapshot file (bad coin height or truncated file or
+- TODO: Valid hash but invalid snapshot file (bad coin height or
bad other serialization)
-- TODO: Valid snapshot file, but referencing an unknown block
- TODO: Valid snapshot file, but referencing a snapshot block that turns out to be
invalid, or has an invalid parent
- TODO: Valid snapshot file and snapshot block, but the block is not on the
@@ -40,7 +38,6 @@
assert_equal,
assert_raises_rpc_error,
)
-import struct
START_HEIGHT = 199
SNAPSHOT_BASE_HEIGHT = 299
@@ -72,30 +69,41 @@ def test_invalid_snapshot_scenarios(self, valid_snapshot_path):
valid_snapshot_contents = f.read()
bad_snapshot_path = valid_snapshot_path + '.mod'
+ def expected_error(log_msg="", rpc_details=""):
+ with self.nodes[1].assert_debug_log([log_msg]):
+ assert_raises_rpc_error(-32603, f"Unable to load UTXO snapshot{rpc_details}", self.nodes[1].loadtxoutset, bad_snapshot_path)
+
self.log.info(" - snapshot file refering to a block that is not in the assumeutxo parameters")
- # we can only test this with a block that is already known, as otherwise the `loadtxoutset` RPC
- # would time out (waiting to see the hash in the headers chain), rather than error immediately
- bad_snapshot_height = SNAPSHOT_BASE_HEIGHT - 1
- with open(bad_snapshot_path, 'wb') as f:
- bad_snapshot_block_hash = self.nodes[0].getblockhash(bad_snapshot_height)
- # block hash of the snapshot base is stored right at the start (first 32 bytes)
- f.write(bytes.fromhex(bad_snapshot_block_hash)[::-1] + valid_snapshot_contents[32:])
-
- expected_log = f"assumeutxo height in snapshot metadata not recognized ({bad_snapshot_height}) - refusing to load snapshot"
- with self.nodes[1].assert_debug_log([expected_log]):
- assert_raises_rpc_error(-32603, "Unable to load UTXO snapshot", self.nodes[1].loadtxoutset, bad_snapshot_path)
+ prev_block_hash = self.nodes[0].getblockhash(SNAPSHOT_BASE_HEIGHT - 1)
+ bogus_block_hash = "0" * 64 # Represents any unknown block hash
+ for bad_block_hash in [bogus_block_hash, prev_block_hash]:
+ with open(bad_snapshot_path, 'wb') as f:
+ # block hash of the snapshot base is stored right at the start (first 32 bytes)
+ f.write(bytes.fromhex(bad_block_hash)[::-1] + valid_snapshot_contents[32:])
+ error_details = f", assumeutxo block hash in snapshot metadata not recognized ({bad_block_hash})"
+ expected_error(rpc_details=error_details)
self.log.info(" - snapshot file with wrong number of coins")
- valid_num_coins = struct.unpack(" bool:
- return bool(reg.match(fname)) or 'test_utxo_snapshots.sh' in fname
+ return bool(reg.match(fname))
# remove everything that doesn't match this regex
files[:] = [file for file in files if not should_exclude(file)]