Merge bitcoin/bitcoin#33609: [30.x] Backports

b2cb203af05743ea5c130913afa7549c02d1bae5 doc: update release notes for 30.x (fanquake)
39d53dd8bf2a19dfdc6976e9d8e9c562065adc1d interfaces: add interruptWait method (ismaelsadeeq)
577ddf6f5d1e7b01c496350206ac8fc33178e416 depends: Add patch for Windows11Style plugin (Hennadii Stepanov)
a0a2b0770164b606780c707d6d0a82a02ff9039f scripted-diff: Remove obsolete comment (Hennadii Stepanov)
e2c71c4fca44e14366653eedb8a15183d6a0444b doc: Correct `pkgin` command usage on NetBSD (Hennadii Stepanov)
c0d851e6c69ba8fc1d70b89e0660831c8fb9e633 qt: Modernize custom filtering (Hennadii Stepanov)
34576c45747214e02b34cac5de71f5139888661f ci: fix configure docker action inputs (will)
8f8c7cf7fa957337d9f5715ae28835dbba12698d ci: fix lint docker caching (will)
049bf100f114db3ec95eebbc56621ab5bce2cabd qt: add createwallet, createwalletdescriptor, and migratewallet to history filter (WakeTrainDev)
3afd5a9729d78f38d2cac7b34f3ef44c79b4bf9a miner: fix empty mempool case for waitNext() (Sjors Provoost)
23ac752d0966317894ae5279a59a12dd6f9f616a bitcoin: Make wrapper not require -m (Ryan Ofsky)
cd7937ce2d313715f380eafd15b20d429b65c83c test: add tool_bitcoin to test bitcoin wrapper behavior (Ryan Ofsky)
42d4847fdff3e1c3b0644de5f503db80ef3ff2a1 init: add exe name to bitcoind, bitcoin-node -version output to be able to distinguish these in tests (Ryan Ofsky)
96110f884604ab85db04170f22e9a4bd936c59d7 [doc] correct topology requirements in submitpackage helptext (glozow)
729e4c2abd4ab4eda4051579c57410dd64d4e7a9 multiprocess: align our logging with libmultiprocess's (Cory Fields)
f8db6f6ce7d30c1b6db8646eedc9160ded556823 multiprocess: update multiprocess EventLoop construction to use options (Cory Fields)
5e389959b9bacae60da64d6e0213ae12242b4c2e test: change log rate limit version gate from 299900 to 290100 (Eugene Siegel)
c48d3a6ad8e884bdb595d5608d914f7de688b7af ci: expose all ACTIONS_* vars (willcl-ark)
73ed57a35e624c6eb4c5dca2687303920fa792bc depends: Use $(package)_file_name when downloading from the fallback (Ava Chow)
72d1141bd8ded704cc6b881a7d26d9103ec813df ci: Use native platform for win-cross task (MarcoFalke)
c9fa661131c336a844109a5d8627b7419280bf52 ci: Properly include $FILE_ENV in DEPENDS_HASH (Ava Chow)

Pull request description:

  Backports:
  * #33229
  * #33508
  * #33517
  * #33558
  * #33566
  * #33580
  * #33581
  * #33612
  * #33630
  * #33676
  * #33744
  * #33826
  * #33827
  * #33906
  * https://github.com/bitcoin-core/gui/pull/899
  * https://github.com/bitcoin-core/gui/pull/901

ACKs for top commit:
  willcl-ark:
    ACK b2cb203af05743ea5c130913afa7549c02d1bae5
  marcofleon:
    Lgtm, ACK b2cb203af05743ea5c130913afa7549c02d1bae5

Tree-SHA512: cde3584c7ad9bc6034a54527c1f5e84f0c5e314520109342a5cbb3c6c703286e2bed26f2b24fbf0ba7bcc9cbc140d79921e9d63def6b5c4782fd2e208f51948a
This commit is contained in:
merge-script 2025-12-02 10:15:15 +00:00
commit 72675b8f55
No known key found for this signature in database
GPG Key ID: 2EEB9F5CC09526C1
38 changed files with 519 additions and 422 deletions

View File

@ -4,12 +4,21 @@ inputs:
cache-provider:
description: 'gha or cirrus cache provider'
required: true
options:
- gh
- cirrus
runs:
using: 'composite'
steps:
- name: Check inputs
shell: bash
run: |
# We expect only gha or cirrus as inputs to cache-provider
case "${{ inputs.cache-provider }}" in
gha|cirrus)
;;
*)
echo "::warning title=Unknown input to configure docker action::Provided value was ${{ inputs.cache-provider }}"
;;
esac
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
with:
@ -22,8 +31,12 @@ runs:
uses: actions/github-script@v6
with:
script: |
core.exportVariable('ACTIONS_CACHE_URL', process.env['ACTIONS_CACHE_URL'])
core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env['ACTIONS_RUNTIME_TOKEN'])
Object.keys(process.env).forEach(function (key) {
if (key.startsWith('ACTIONS_')) {
core.info(`Exporting ${key}`);
core.exportVariable(key, process.env[key]);
}
});
- name: Construct docker build cache args
shell: bash

View File

@ -17,7 +17,7 @@ runs:
- name: Set cache hashes
shell: bash
run: |
echo "DEPENDS_HASH=$(git ls-tree HEAD depends "ci/test/$FILE_ENV" | sha256sum | cut -d' ' -f1)" >> $GITHUB_ENV
echo "DEPENDS_HASH=$(git ls-tree HEAD depends "$FILE_ENV" | sha256sum | cut -d' ' -f1)" >> $GITHUB_ENV
echo "PREVIOUS_RELEASES_HASH=$(git ls-tree HEAD test/get_previous_releases.py | sha256sum | cut -d' ' -f1)" >> $GITHUB_ENV
- name: Get container name

View File

@ -536,7 +536,7 @@ jobs:
lint:
name: 'lint'
needs: runners
runs-on: ${{ needs.runners.outputs.use-cirrus-runners == 'true' && 'ghcr.io/cirruslabs/ubuntu-runner-amd64:24.04-xs' || 'ubuntu-24.04' }}
runs-on: ${{ needs.runners.outputs.provider == 'cirrus' && 'ghcr.io/cirruslabs/ubuntu-runner-amd64:24.04-xs' || 'ubuntu-24.04' }}
if: ${{ vars.SKIP_BRANCH_PUSH != 'true' || github.event_name == 'pull_request' }}
timeout-minutes: 20
env:

View File

@ -8,7 +8,6 @@ export LC_ALL=C.UTF-8
export CONTAINER_NAME=ci_win64
export CI_IMAGE_NAME_TAG="mirror.gcr.io/ubuntu:24.04" # Check that https://packages.ubuntu.com/noble/g++-mingw-w64-x86-64-posix (version 13.x, similar to guix) can cross-compile
export CI_IMAGE_PLATFORM="linux/amd64"
export HOST=x86_64-w64-mingw32
export PACKAGES="g++-mingw-w64-x86-64-posix nsis"
export RUN_UNIT_TESTS=false

View File

@ -38,7 +38,7 @@ endef
define fetch_file
( test -f $$($(1)_source_dir)/$(4) || \
( $(call fetch_file_inner,$(1),$(2),$(3),$(4),$(5)) || \
$(call fetch_file_inner,$(1),$(FALLBACK_DOWNLOAD_PATH),$(3),$(4),$(5))))
$(call fetch_file_inner,$(1),$(FALLBACK_DOWNLOAD_PATH),$(4),$(4),$(5))))
endef
# Shell script to create a source tarball in $(1)_source from local directory

View File

@ -16,6 +16,7 @@ $(package)_patches += qtbase_avoid_native_float16.patch
$(package)_patches += qtbase_avoid_qmain.patch
$(package)_patches += qtbase_platformsupport.patch
$(package)_patches += qtbase_plugins_cocoa.patch
$(package)_patches += qtbase_plugins_windows11style.patch
$(package)_patches += qtbase_skip_tools.patch
$(package)_patches += rcc_hardcode_timestamp.patch
$(package)_patches += qttools_skip_dependencies.patch
@ -261,6 +262,7 @@ define $(package)_preprocess_cmds
patch -p1 -i $($(package)_patch_dir)/qtbase_avoid_qmain.patch && \
patch -p1 -i $($(package)_patch_dir)/qtbase_platformsupport.patch && \
patch -p1 -i $($(package)_patch_dir)/qtbase_plugins_cocoa.patch && \
patch -p1 -i $($(package)_patch_dir)/qtbase_plugins_windows11style.patch && \
patch -p1 -i $($(package)_patch_dir)/qtbase_skip_tools.patch && \
patch -p1 -i $($(package)_patch_dir)/rcc_hardcode_timestamp.patch
endef

View File

@ -0,0 +1,113 @@
QWindows11Style: Calculate Spinbox size based on CommonStyle size
Use the calculation from Commonstyle and add the increased padding and
horizontally layouted buttons to the horizontal size hint.
Fixes: QTBUG-130288
Change-Id: I7932b782e7873a0178091a51379f17453eb585fd
Upstream commits:
- Qt 6.8.1: 9107817eaceaacc968dbc767c24594566d637b8c
- Qt 6.9.0: 96d46cad43517adefa2eb7cb8819a0b2cc9241e6
--- a/qtbase/src/plugins/styles/modernwindows/qwindows11style.cpp
+++ b/qtbase/src/plugins/styles/modernwindows/qwindows11style.cpp
@@ -2048,39 +2048,22 @@ QSize QWindows11Style::sizeFromContents(ContentsType type, const QStyleOption *o
}
break;
#endif
+#if QT_CONFIG(spinbox)
case QStyle::CT_SpinBox: {
if (const auto *spinBoxOpt = qstyleoption_cast<const QStyleOptionSpinBox *>(option)) {
// Add button + frame widths
- int width = 0;
-
- if (const QDateTimeEdit *spinBox = qobject_cast<const QDateTimeEdit *>(widget)) {
- const QSize textSizeMin = spinBoxOpt->fontMetrics.size(Qt::TextSingleLine, spinBox->minimumDateTime().toString(spinBox->displayFormat()));
- const QSize textSizeMax = spinBoxOpt->fontMetrics.size(Qt::TextSingleLine, spinBox->maximumDateTime().toString(spinBox->displayFormat()));
- width = qMax(textSizeMin.width(),textSizeMax.width());
- } else if (const QSpinBox *spinBox = qobject_cast<const QSpinBox *>(widget)) {
- const QSize textSizeMin = spinBoxOpt->fontMetrics.size(Qt::TextSingleLine, QString::number(spinBox->minimum()));
- const QSize textSizeMax = spinBoxOpt->fontMetrics.size(Qt::TextSingleLine, QString::number(spinBox->maximum()));
- width = qMax(textSizeMin.width(),textSizeMax.width());
- width += spinBoxOpt->fontMetrics.size(Qt::TextSingleLine, spinBox->prefix()).width();
- width += spinBoxOpt->fontMetrics.size(Qt::TextSingleLine, spinBox->suffix()).width();
-
- } else if (const QDoubleSpinBox *spinBox = qobject_cast<const QDoubleSpinBox *>(widget)) {
- const QSize textSizeMin = spinBoxOpt->fontMetrics.size(Qt::TextSingleLine, QString::number(spinBox->minimum()));
- const QSize textSizeMax = spinBoxOpt->fontMetrics.size(Qt::TextSingleLine, QString::number(spinBox->maximum()));
- width = qMax(textSizeMin.width(),textSizeMax.width());
- width += spinBoxOpt->fontMetrics.size(Qt::TextSingleLine, spinBox->prefix()).width();
- width += spinBoxOpt->fontMetrics.size(Qt::TextSingleLine, spinBox->suffix()).width();
- }
const qreal dpi = QStyleHelper::dpi(option);
const bool hasButtons = (spinBoxOpt->buttonSymbols != QAbstractSpinBox::NoButtons);
- const int buttonWidth = hasButtons ? 2 * qRound(QStyleHelper::dpiScaled(16, dpi)) : 0;
+ const int margins = 8;
+ const int buttonWidth = hasButtons ? qRound(QStyleHelper::dpiScaled(16, dpi)) : 0;
const int frameWidth = spinBoxOpt->frame ? proxy()->pixelMetric(PM_SpinBoxFrameWidth,
spinBoxOpt, widget) : 0;
- contentSize.setWidth(2 * 12 + width);
- contentSize += QSize(buttonWidth + 2 * frameWidth, 2 * frameWidth);
+
+ contentSize += QSize(2 * buttonWidth + 2 * frameWidth + 2 * margins, 2 * frameWidth);
}
break;
}
+#endif
default:
contentSize = QWindowsVistaStyle::sizeFromContents(type, option, size, widget);
break;
Windows11Style: don't set minimum width for QAbstractSpinBox
There is no need to set a minimum width for QAbstractSpinBox in
QWindows11Style::polish() as this might override the user preferences.
Also the minimum size handling is now properly done within
sizeFromContents().
Change-Id: Ibc1fd7a6f862fc85e3739025b9de581aa235d74c
Upstream commits:
- Qt 6.8.3: f86da3d3f853adb1a5b823c1cc7be6db4a0265f3
- Qt 6.9.0: b93a8dfdfe6900cb542fdc587dd2682007a6ac53
- Qt 6.10.0: 2ec4c28470de115c16944653a5d4f6209452d56c
--- a/qtbase/src/plugins/styles/modernwindows/qwindows11style.cpp
+++ b/qtbase/src/plugins/styles/modernwindows/qwindows11style.cpp
@@ -29,7 +29,6 @@ QT_BEGIN_NAMESPACE
const static int topLevelRoundingRadius = 8; //Radius for toplevel items like popups for round corners
const static int secondLevelRoundingRadius = 4; //Radius for second level items like hovered menu item round corners
-constexpr QLatin1StringView originalWidthProperty("_q_windows11_style_original_width");
enum WINUI3Color {
subtleHighlightColor, //Subtle highlight based on alpha used for hovered elements
@@ -2140,13 +2139,6 @@ void QWindows11Style::polish(QWidget* widget)
pal.setColor(QPalette::ButtonText, pal.text().color());
pal.setColor(QPalette::BrightText, pal.text().color());
widget->setPalette(pal);
- } else if (widget->inherits("QAbstractSpinBox")) {
- const int minWidth = 2 * 24 + 40;
- const int originalWidth = widget->size().width();
- if (originalWidth < minWidth) {
- widget->resize(minWidth, widget->size().height());
- widget->setProperty(originalWidthProperty.constData(), originalWidth);
- }
} else if (widget->inherits("QAbstractButton") || widget->inherits("QToolButton")) {
widget->setAutoFillBackground(false);
auto pal = widget->palette();
@@ -2191,13 +2183,6 @@ void QWindows11Style::unpolish(QWidget *widget)
scrollarea->viewport()->setPalette(pal);
scrollarea->viewport()->setProperty("_q_original_background_palette", QVariant());
}
- if (widget->inherits("QAbstractSpinBox")) {
- const QVariant originalWidth = widget->property(originalWidthProperty.constData());
- if (originalWidth.isValid()) {
- widget->resize(originalWidth.toInt(), widget->size().height());
- widget->setProperty(originalWidthProperty.constData(), QVariant());
- }
- }
}
/*

View File

@ -101,5 +101,5 @@ cmake -B build -DENABLE_WALLET=OFF
```bash
cmake --build build # Append "-j N" for N parallel jobs.
ctest --test-dir build # Append "-j N" for N parallel tests. Some tests are disabled if Python 3 is not available.
ctest --test-dir build # Append "-j N" for N parallel tests.
```

View File

@ -34,7 +34,7 @@ cmake -B build
SQLite is required for the wallet:
```bash
pkgin sqlite3
pkgin install sqlite3
```
To build Bitcoin Core without the wallet, use `-DENABLE_WALLET=OFF`.
@ -42,7 +42,7 @@ To build Bitcoin Core without the wallet, use `-DENABLE_WALLET=OFF`.
Cap'n Proto is needed for IPC functionality (see [multiprocess.md](multiprocess.md)):
```bash
pkgin capnproto
pkgin install capnproto
```
Compile with `-DENABLE_IPC=OFF` if you do not need IPC functionality.
@ -84,7 +84,7 @@ Otherwise, if you don't need QR encoding support, use the `-DWITH_QRENCODE=OFF`
Bitcoin Core can provide notifications via ZeroMQ. If the package is installed, support will be compiled in.
```bash
pkgin zeromq
pkgin install zeromq
```
#### Test Suite Dependencies
@ -115,5 +115,5 @@ Build and run the tests:
```bash
cmake --build build # Append "-j N" for N parallel jobs.
ctest --test-dir build # Append "-j N" for N parallel tests. Some tests are disabled if Python 3 is not available.
ctest --test-dir build # Append "-j N" for N parallel tests.
```

View File

@ -93,7 +93,7 @@ Run `cmake -B build -LH` to see the full list of available options.
```bash
cmake --build build # Append "-j N" for N parallel jobs.
ctest --test-dir build # Append "-j N" for N parallel tests. Some tests are disabled if Python 3 is not available.
ctest --test-dir build # Append "-j N" for N parallel tests.
```
## Resource limits

View File

@ -170,7 +170,7 @@ Run the following in your terminal to compile Bitcoin Core:
``` bash
cmake --build build # Append "-j N" here for N parallel jobs.
ctest --test-dir build # Append "-j N" for N parallel tests. Some tests are disabled if Python 3 is not available.
ctest --test-dir build # Append "-j N" for N parallel tests.
```
### 3. Deploy (optional)

View File

@ -55,7 +55,7 @@ In the following instructions, the "Debug" configuration can be specified instea
```
cmake -B build --preset vs2022-static # It might take a while if the vcpkg binary cache is unpopulated or invalidated.
cmake --build build --config Release # Append "-j N" for N parallel jobs.
ctest --test-dir build --build-config Release # Append "-j N" for N parallel tests. Some tests are disabled if Python 3 is not available.
ctest --test-dir build --build-config Release # Append "-j N" for N parallel tests.
cmake --install build --config Release # Optional.
```
@ -64,7 +64,7 @@ cmake --install build --config Release # Optional.
```
cmake -B build --preset vs2022 -DBUILD_GUI=OFF # It might take a while if the vcpkg binary cache is unpopulated or invalidated.
cmake --build build --config Release # Append "-j N" for N parallel jobs.
ctest --test-dir build --build-config Release # Append "-j N" for N parallel tests. Some tests are disabled if Python 3 is not available.
ctest --test-dir build --build-config Release # Append "-j N" for N parallel tests.
```
### 6. vcpkg-specific Issues and Workarounds

View File

@ -1,9 +1,9 @@
v30.0 Release Notes
v30.x Release Notes
===================
Bitcoin Core version v30.0 is now available from:
Bitcoin Core version v30.x is now available from:
<https://bitcoincore.org/bin/bitcoin-core-30.0/>
<https://bitcoincore.org/bin/bitcoin-core-30.x/>
This release includes new features, various bug fixes and performance
improvements, as well as updated translations.
@ -40,399 +40,57 @@ unsupported systems.
Notable changes
===============
Policy
------
### Build
- The maximum number of potentially executed legacy signature operations in a
single standard transaction is now limited to 2500. Signature operations in all
previous output scripts, in all input scripts, as well as all P2SH redeem
scripts (if there are any) are counted toward the limit. The new limit is
assumed to not affect any known typically formed standard transactions. The
change was done to prepare for a possible BIP54 deployment in the future. (#32521)
- #33580 depends: Use `$(package)_file_name` when downloading from the fallback
- #33906 depends: Add patch for Windows11Style plugin
- `-datacarriersize` is increased to 100,000 by default, which effectively uncaps
the limit (as the maximum transaction size limit will be hit first). It can be
overridden with `-datacarriersize=83` to revert to the limit enforced in previous
versions. (#32406)
### IPC
- Multiple data carrier (OP_RETURN) outputs in a transaction are now permitted for
relay and mining. The `-datacarriersize` limit applies to the aggregate size of
the scriptPubKeys across all such outputs in a transaction, not including the
scriptPubKey size itself. (#32406)
- #33229 multiprocess: Don't require bitcoin -m argument when IPC options are used
- #33517 multiprocess: Fix high overhead from message logging
- #33519 Update libmultiprocess subtree in 30.x branch
- #33566 miner: fix empty mempool case for waitNext()
- #33676 interfaces: enable cancelling running waitNext calls
- The minimum block feerate (`-blockmintxfee`) has been changed to 0.001 satoshi per
vB. It can still be changed using the configuration option. This option can be used
by miners to set a minimum feerate on packages added to block templates. (#33106)
### GUI
- The default minimum relay feerate (`-minrelaytxfee`) and incremental relay feerate
(`-incrementalrelayfee`) have been changed to 0.1 satoshis per vB. They can still
be changed using their respective configuration options, but it is recommended to
change both together if you decide to do so. (#33106)
- gui#899 qt: Modernize custom filtering
- gui#901 Add createwallet, createwalletdescriptor, and migratewallet to history filter
Other minimum feerates (e.g. the dust feerate, the minimum returned by the fee
estimator, and all feerates used by the wallet) remain unchanged. The mempool minimum
feerate still changes in response to high volume.
### Test
Note that unless these lower defaults are widely adopted across the network, transactions
created with lower fee rates are not guaranteed to propagate or confirm. The wallet
feerates remain unchanged; `-mintxfee` must be changed before attempting to create
transactions with lower feerates using the wallet. (#33106)
- #33612 test: change log rate limit version gate
P2P and network changes
-----------------------
### Doc
- Opportunistic 1-parent-1-child package relay has been improved to handle
situations when the child already has unconfirmed parent(s) in the mempool.
This means that 1p1c packages can be accepted and propagate, even if they are
connected to broader topologies: multi-parent-1-child (where only 1 parent
requires fee-bumping), grandparent-parent-child (where only parent requires
fee-bumping) etc. (#31385)
- #33630 doc: correct topology requirements in submitpackage helptext
- #33826 scripted-diff: Remove obsolete comment
- #33827 doc: Correct pkgin command usage on NetBSD
- The transaction orphanage, which holds transactions with missing inputs temporarily
while the node attempts to fetch its parents, now has improved Denial of Service protections.
Previously, it enforced a maximum number of unique transactions (default 100,
configurable using `-maxorphantx`). Now, its limits are as follows: the number of
entries (unique by wtxid and peer), plus each unique transaction's input count divided
by 10, must not exceed 3,000. The total weight of unique transactions must not exceed
`404,000` Wu multiplied by the number of peers. (#31829)
### Misc
- The `-maxorphantx` option no longer has any effect, since the orphanage no longer
limits the number of unique transactions. Users should remove this configuration
option if they were using it, as the setting will cause an error in future versions
when it is no longer recognized. (#31829)
New `bitcoin` command
---------------------
- A new `bitcoin` command line tool has been added to make features more discoverable
and convenient to use. The `bitcoin` tool just calls other executables and does not
implement any functionality on its own. Specifically `bitcoin node` is a synonym for
`bitcoind`, `bitcoin gui` is a synonym for `bitcoin-qt`, and `bitcoin rpc` is a synonym
for `bitcoin-cli -named`. Other commands and options can be listed with `bitcoin help`.
The new `bitcoin` command is an alternative to calling other commands directly, but it
doesn't replace them, and there are no plans to deprecate existing commands. (#31375)
External Signing
----------------
- Support for external signing on Windows has been re-enabled. (#29868)
IPC Mining Interface
--------------------
- The new `bitcoin` command does support one new feature: an (experimental) IPC Mining
Interface that allows the node to work with Stratum v2 or other mining client software,
see (#31098). When the node is started with `bitcoin -m node -ipcbind=unix` it will
listen on a unix socket for IPC client connections, allowing clients to request block
templates and submit mined blocks. The `-m` option launches a new internal binary
(`bitcoin-node` instead of `bitcoind`) and is currently required but will become optional
in the future (with [#33229](https://github.com/bitcoin/bitcoin/pull/33229)).
- IPC connectivity introduces new dependencies (see [multiprocess.md](https://github.com/bitcoin/bitcoin/blob/master/doc/multiprocess.md)),
which can be turned off with the `-DENABLE_IPC=OFF` build option if you do not intend
to use IPC. (#31802)
Install changes
---------------
- The `test_bitcoin` executable is now installed in `libexec/` instead of `bin/`.
It can still be executed directly, or accessed through the new `bitcoin` command
as `bitcoin test`. The `libexec/` directory also contains new `bitcoin-node` and
`bitcoin-gui` binaries which support IPC features and are called through the
`bitcoin` tool. In source builds only, `test_bitcoin-qt`, `bench_bitcoin`, and
`bitcoin-chainstate` are also now installed to `libexec/` instead of `bin/` and
can be accessed through the new `bitcoin` command. See `bitcoin help` output for
details. (#31679)
- On Windows, the installer no longer adds a “(64-bit)” suffix to entries in the
Start Menu (#32132), and it now automatically removes obsolete artifacts during
upgrades (#33422).
Indexes
-------
- The implementation of coinstatsindex was changed to prevent an overflow bug that
could already be observed on the default Signet. The new version of the index will
need to be synced from scratch when starting the upgraded node for the first time.
The new version is stored in `/indexes/coinstatsindex/` in contrast to the old version
which was stored at `/indexes/coinstats/`. The old version of the index is not deleted
by the upgraded node in case the user chooses to downgrade their node in the future.
If the user does not plan to downgrade it is safe for them to remove `/indexes/coinstats/`
from their datadir. A future release of Bitcoin Core may remove the old version of the
index automatically. (#30469)
Logging
-------
- Unconditional logging to disk is now rate limited by giving each source location
a quota of 1MiB per hour. Unconditional logging is any logging with a log level
higher than debug, that is `info`, `warning`, and `error`. All logs will be
prefixed with `[*]` if there is at least one source location that is currently
being suppressed. (#32604)
- When `-logsourcelocations` is enabled, the log output now contains the entire
function signature instead of just the function name. (#32604)
Updated RPCs
------------
- The `-paytxfee` startup option and the `settxfee` RPC are now deprecated and
will be removed in Bitcoin Core 31.0. They allowed the user to set a static fee
rate for wallet transactions, which could potentially lead to overpaying or underpaying.
Users should instead rely on fee estimation or specify a fee rate per transaction
using the `fee_rate` argument in RPCs such as `fundrawtransaction`, `sendtoaddress`,
`send`, `sendall`, and `sendmany`. (#31278)
- Any RPC in which one of the parameters is a descriptor will throw an error
if the provided descriptor contains a whitespace at the beginning or the end
of the public key within a fragment - e.g. `pk( KEY)` or `pk(KEY )`. (#31603)
- The `submitpackage` RPC, which allows submissions of child-with-parents
packages, no longer requires that all unconfirmed parents be present. The
package may contain other in-mempool ancestors as well. (#31385)
- The `waitfornewblock` RPC now takes an optional `current_tip` argument. It
is also no longer hidden. (#30635)
- The `waitforblock` and `waitforblockheight` RPCs are no longer hidden. (#30635)
- The `psbtbumpfee` and `bumpfee` RPCs allow a replacement under fullrbf and no
longer require BIP-125 signalling. (#31953)
- Transaction Script validation errors used to return the reason for the error
prefixed by either `mandatory-script-verify-flag-failed` if it was a consensus
error, or `non-mandatory-script-verify-flag` (without "-failed") if it was a
standardness error. This has been changed to `block-script-verify-flag-failed`
and `mempool-script-verify-flag-failed` for all block and mempool errors
respectively. (#33183)
- The `getmininginfo` RPC now returns "blockmintxfee" result specifying the value of
`-blockmintxfee` configuration. (#33189)
- The `getmempoolinfo` RPC now returns an additional "permitbaremultisig" and
"maxdatacarriersize" field, reflecting the `-permitbaremultisig` and `-datacarriersize`
config values. (#29954)
Changes to wallet-related RPCs can be found in the Wallet section below.
New RPCs
--------
- A new REST API endpoint (`/rest/spenttxouts/BLOCKHASH`) has been introduced for
efficiently fetching spent transaction outputs using the block's undo data (#32540).
Build System
------------
Updated settings
----------------
- The `-maxmempool` and `-dbcache` startup parameters are now capped on 32-bit systems
to 500MB and 1GiB respectively. (#32530)
- The `-natpmp` option is now set to `1` by default. This means nodes with `-listen`
enabled (the default) but running behind a firewall, such as a local network router,
will be reachable if the firewall/router supports any of the `PCP` or `NAT-PMP`
protocols. (#33004)
- The `-upnp` setting has now been fully removed. Use `-natpmp` instead. (#32500)
- Previously, `-proxy` specified the proxy for all networks (except I2P which
uses `-i2psam`) and only the Tor proxy could have been specified separately
via `-onion`. Now, the syntax of `-proxy` has been extended and it is possible
to specify separately the proxy for IPv4, IPv6, Tor and CJDNS by appending `=`
followed by the network name, for example `-proxy=127.0.0.1:5555=ipv6`
configures a proxy only for IPv6. The `-proxy` option can be used multiple
times to define different proxies for different networks, such as
`-proxy=127.0.0.1:4444=ipv4 -proxy=10.0.0.1:6666=ipv6`. Later settings
override earlier ones for the same network; this can be used to remove an
earlier all-networks proxy and use direct connections only for a given
network, for example `-proxy=127.0.0.1:5555 -proxy=0=cjdns`. (#32425)
- The `-blockmaxweight` startup option has been updated to be debug-only.
It is still available to users, but now hidden from the default `-help` text
and shown only in `-help-debug` (#32654).
Changes to GUI or wallet related settings can be found in the GUI or Wallet section below.
Wallet
------
- BDB legacy wallets can no longer be created or loaded. They can be migrated
to the new descriptor wallet format. Refer to the `migratewallet` RPC for more
details.
- The legacy wallet removal drops redundant options in the bitcoin-wallet tool,
such as `-withinternalbdb`, `-legacy`, and `-descriptors`. Moreover, the
legacy-only RPCs `addmultisigaddress`, `dumpprivkey`, `dumpwallet`,
`importaddress`, `importmulti`, `importprivkey`, `importpubkey`,
`importwallet`, `newkeypool`, `sethdseed`, and `upgradewallet`, are removed.
(#32944, #28710, #32438, #31250)
- Support has been added for spending TRUC transactions received by the
wallet, as well as creating TRUC transactions. The wallet ensures that
TRUC policy rules are being met. The wallet will throw an error if the
user is trying to spend TRUC utxos with utxos of other versions.
Additionally, the wallet will treat unconfirmed TRUC sibling
transactions as mempool conflicts. The wallet will also ensure that
transactions spending TRUC utxos meet the required size restrictions. (#32896)
- Since descriptor wallets do not allow mixing watchonly and non-watchonly descriptors,
the `include_watchonly` option (and its variants in naming) are removed from all RPCs
that had it. (#32618)
- The `iswatchonly` field is removed from any RPCs that returned it. (#32618)
- `unloadwallet` - Return RPC_INVALID_PARAMETER when both the RPC wallet endpoint
and wallet_name parameters are unspecified. Previously the RPC failed with a JSON
parsing error. (#32845)
- `getdescriptoractivity` - Mark blockhashes and scanobjects arguments as required,
so the user receives a clear help message when either is missing. As in `unloadwallet`,
previously the RPC failed with a JSON parsing error. (#32845)
- `getwalletinfo` - Removes the fields `balance`, `immature_balance` and
`unconfirmed_balance`. (#32721)
- `getunconfirmedbalance` - Removes this RPC command. You can query the `getbalances`
RPC and inspect the `["mine"]["untrusted_pending"]` entry within the JSON
response. (#32721)
- The following RPCs now contain a `version` parameter that allows
the user to create transactions of any standard version number (1-3):
- `createrawtransaction`
- `createpsbt`
- `send`
- `sendall`
- `walletcreatefundedpsbt`
(#32896)
GUI changes
-----------
- The GUI has been migrated from Qt 5 to Qt 6. On Windows, dark mode is now supported.
On macOS, the Metal backend is now used. (#30997)
- A transaction's fee bump is allowed under fullrbf and no longer requires
BIP-125 signalling. (#31953)
- Custom column widths in the Transactions tab are reset as a side-effect of legacy
wallet removal. (#32459)
Low-level changes
=================
- Logs now include which peer sent us a header. Additionally there are fewer
redundant header log messages. A side-effect of this change is that for
some untypical cases new headers aren't logged anymore, e.g. a direct
`BLOCK` message with a previously unknown header and `submitheader` RPC. (#27826)
- #33508 ci: fix buildx gha cache authentication on forks
- #33558 ci: Use native platform for win-cross task
- #33581 ci: Properly include $FILE_ENV in DEPENDS_HASH
- #33744 ci: Fix lint runner selection (and docker cache)
Credits
=======
Thanks to everyone who directly contributed to this release:
- 0xb10c
- amisha
- Andrew Toth
- Anthony Towns
- Antoine Poinsot
- Ava Chow
- benthecarman
- Brandon Odiwuor
- brunoerg
- Bue-von-hon
- Bufo
- Chandra Pratap
- Chris Stewart
- Cory Fields
- Daniel Pfeifer
- Daniela Brozzoni
- David Gumberg
- deadmanoz
- dennsikl
- dergoegge
- enoch
- Ethan Heilman
- Eugene Siegel
- Eunovo
- Eval EXEC
- Fabian Jahr
- fanquake
- Florian Schmaus
- fuder.eth
- furszy
- glozow
- Greg Sanders
- Hao Xu
- Haoran Peng
- Haowen Liu
- Hennadii Stepanov
- Hodlinator
- hoffman
- ishaanam
- ismaelsadeeq
- Jameson Lopp
- janb84
- Jiri Jakes
- John Bampton
- Jon Atack
- josibake
- jurraca
- kevkevin
- kevkevinpal
- kilavvy
- Kristaps Kaupe
- l0rinc
- laanwj
- leopardracer
- Lőrinc
- Luis Schwab
- Luke Dashjr
- MarcoFalke
- marcofleon
- Martin Zumsande
- Matt Corallo
- Matthew Zipkin
- Max Edwards
- monlovesmango
- Murch
- naiyoma
- nervana21
- Nicola Leonardo Susca
- Novo
- pablomartin4btc
- Peter Todd
- Pieter Wuille
- Pol Espinasa
- Prabhat Verma
- rkrux
- Roman Zeyde
- Ryan Ofsky
- Saikiran
- Salvatore Ingala
- Sebastian Falbesoner
- Sergi Delgado Segura
- Shunsuke Shimizu
- Sjors Provoost
- stickies-v
- stratospher
- stringintech
- strmfos
- stutxo
- tdb3
- TheCharlatan
- Tomás Andróil
- UdjinM6
- Vasil Dimov
- VolodymyrBg
- w0xlt
- will
- WakeTrainDev
- willcl-ark
- William Casarin
- woltx
- yancy
- zaidmstrr
As well as to everyone that helped with translations on
[Transifex](https://explore.transifex.com/bitcoin/bitcoin/).

View File

@ -292,7 +292,7 @@ if(BUILD_BITCOIN_BIN)
add_executable(bitcoin bitcoin.cpp)
add_windows_resources(bitcoin bitcoin-res.rc)
add_windows_application_manifest(bitcoin)
target_link_libraries(bitcoin core_interface bitcoin_util)
target_link_libraries(bitcoin core_interface bitcoin_common bitcoin_util)
install_binary_component(bitcoin HAS_MANPAGE)
endif()

View File

@ -5,6 +5,7 @@
#include <bitcoin-build-config.h> // IWYU pragma: keep
#include <clientversion.h>
#include <common/args.h>
#include <util/fs.h>
#include <util/exec.h>
#include <util/strencodings.h>
@ -47,7 +48,7 @@ Run '%s help' to see additional commands (e.g. for testing and debugging).
)";
struct CommandLine {
bool use_multiprocess{false};
std::optional<bool> use_multiprocess;
bool show_version{false};
bool show_help{false};
std::string_view command;
@ -55,6 +56,7 @@ struct CommandLine {
};
CommandLine ParseCommandLine(int argc, char* argv[]);
bool UseMultiprocess(const CommandLine& cmd);
static void ExecCommand(const std::vector<const char*>& args, std::string_view argv0);
int main(int argc, char* argv[])
@ -78,9 +80,9 @@ int main(int argc, char* argv[])
return EXIT_FAILURE;
}
} else if (cmd.command == "gui") {
args.emplace_back(cmd.use_multiprocess ? "bitcoin-gui" : "bitcoin-qt");
args.emplace_back(UseMultiprocess(cmd) ? "bitcoin-gui" : "bitcoin-qt");
} else if (cmd.command == "node") {
args.emplace_back(cmd.use_multiprocess ? "bitcoin-node" : "bitcoind");
args.emplace_back(UseMultiprocess(cmd) ? "bitcoin-node" : "bitcoind");
} else if (cmd.command == "rpc") {
args.emplace_back("bitcoin-cli");
// Since "bitcoin rpc" is a new interface that doesn't need to be
@ -143,6 +145,30 @@ CommandLine ParseCommandLine(int argc, char* argv[])
return cmd;
}
bool UseMultiprocess(const CommandLine& cmd)
{
// If -m or -M options were explicitly specified, there is no need to
// further parse arguments to determine which to use.
if (cmd.use_multiprocess) return *cmd.use_multiprocess;
ArgsManager args;
args.SetDefaultFlags(ArgsManager::ALLOW_ANY);
std::string error_message;
auto argv{cmd.args};
argv.insert(argv.begin(), nullptr);
if (!args.ParseParameters(argv.size(), argv.data(), error_message)) {
tfm::format(std::cerr, "Warning: failed to parse subcommand command line options: %s\n", error_message);
}
if (!args.ReadConfigFiles(error_message, true)) {
tfm::format(std::cerr, "Warning: failed to parse subcommand config: %s\n", error_message);
}
args.SelectConfigNetwork(args.GetChainTypeString());
// If any -ipc* options are set these need to be processed by a
// multiprocess-capable binary.
return args.IsArgSet("-ipcbind") || args.IsArgSet("-ipcconnect") || args.IsArgSet("-ipcfd");
}
//! Execute the specified bitcoind, bitcoin-qt or other command line in `args`
//! using src, bin and libexec directory paths relative to this executable, where
//! the path to this executable is specified in `wrapper_argv0`.

View File

@ -132,11 +132,16 @@ static bool ParseArgs(NodeContext& node, int argc, char* argv[])
return true;
}
static bool ProcessInitCommands(ArgsManager& args)
static bool ProcessInitCommands(interfaces::Init& init, ArgsManager& args)
{
// Process help and version before taking care about datadir
if (HelpRequested(args) || args.GetBoolArg("-version", false)) {
std::string strUsage = CLIENT_NAME " daemon version " + FormatFullVersion() + "\n";
std::string strUsage = CLIENT_NAME " daemon version " + FormatFullVersion();
if (const char* exe_name{init.exeName()}) {
strUsage += " ";
strUsage += exe_name;
}
strUsage += "\n";
if (args.GetBoolArg("-version", false)) {
strUsage += FormatParagraph(LicenseInfo());
@ -277,7 +282,7 @@ MAIN_FUNCTION
ArgsManager& args = *Assert(node.args);
if (!ParseArgs(node, argc, argv)) return EXIT_FAILURE;
// Process early info return commands such as -help or -version
if (ProcessInitCommands(args)) return EXIT_SUCCESS;
if (ProcessInitCommands(*init, args)) return EXIT_SUCCESS;
// Start application
if (!AppInit(node) || !Assert(node.shutdown_signal)->wait()) {

View File

@ -266,7 +266,13 @@ std::optional<unsigned int> ArgsManager::GetArgFlags(const std::string& name) co
return search->second.m_flags;
}
}
return std::nullopt;
return m_default_flags;
}
void ArgsManager::SetDefaultFlags(std::optional<unsigned int> flags)
{
LOCK(cs_args);
m_default_flags = flags;
}
fs::path ArgsManager::GetPathArg(std::string arg, const fs::path& default_value) const

View File

@ -137,6 +137,7 @@ protected:
std::string m_network GUARDED_BY(cs_args);
std::set<std::string> m_network_only_args GUARDED_BY(cs_args);
std::map<OptionsCategory, std::map<std::string, Arg>> m_available_args GUARDED_BY(cs_args);
std::optional<unsigned int> m_default_flags GUARDED_BY(cs_args){};
bool m_accept_any_command GUARDED_BY(cs_args){true};
std::list<SectionInfo> m_config_sections GUARDED_BY(cs_args);
std::optional<fs::path> m_config_path GUARDED_BY(cs_args);
@ -375,10 +376,15 @@ protected:
/**
* Return Flags for known arg.
* Return nullopt for unknown arg.
* Return default flags for unknown arg.
*/
std::optional<unsigned int> GetArgFlags(const std::string& name) const;
/**
* Set default flags to return for an unknown arg.
*/
void SetDefaultFlags(std::optional<unsigned int>);
/**
* Get settings file path, or return false if read-write settings were
* disabled with -nosettings.

View File

@ -39,6 +39,7 @@ public:
// bitcoin-node accepts the option, and bitcoin-gui accepts all bitcoin-node
// options and will start the node with those options.
bool canListenIpc() override { return true; }
const char* exeName() override { return EXE_NAME; }
node::NodeContext m_node;
std::unique_ptr<interfaces::Ipc> m_ipc;
};

View File

@ -38,6 +38,7 @@ public:
std::unique_ptr<interfaces::Echo> makeEcho() override { return interfaces::MakeEcho(); }
interfaces::Ipc* ipc() override { return m_ipc.get(); }
bool canListenIpc() override { return true; }
const char* exeName() override { return EXE_NAME; }
node::NodeContext& m_node;
std::unique_ptr<interfaces::Ipc> m_ipc;
};

View File

@ -16,6 +16,8 @@
namespace init {
namespace {
const char* EXE_NAME = "bitcoin-qt";
class BitcoinQtInit : public interfaces::Init
{
public:
@ -32,6 +34,7 @@ public:
return MakeWalletLoader(chain, *Assert(m_node.args));
}
std::unique_ptr<interfaces::Echo> makeEcho() override { return interfaces::MakeEcho(); }
const char* exeName() override { return EXE_NAME; }
node::NodeContext m_node;
};
} // namespace

View File

@ -18,6 +18,8 @@ using node::NodeContext;
namespace init {
namespace {
const char* EXE_NAME = "bitcoind";
class BitcoindInit : public interfaces::Init
{
public:
@ -34,6 +36,7 @@ public:
return MakeWalletLoader(chain, *Assert(m_node.args));
}
std::unique_ptr<interfaces::Echo> makeEcho() override { return interfaces::MakeEcho(); }
const char* exeName() override { return EXE_NAME; }
NodeContext& m_node;
};
} // namespace

View File

@ -38,6 +38,7 @@ public:
virtual std::unique_ptr<Echo> makeEcho() { return nullptr; }
virtual Ipc* ipc() { return nullptr; }
virtual bool canListenIpc() { return false; }
virtual const char* exeName() { return nullptr; }
};
//! Return implementation of Init interface for the node process. If the argv

View File

@ -72,6 +72,11 @@ public:
* the tip is more than 20 minutes old.
*/
virtual std::unique_ptr<BlockTemplate> waitNext(const node::BlockWaitOptions options = {}) = 0;
/**
* Interrupts the current wait for the next block template.
*/
virtual void interruptWait() = 0;
};
//! Interface giving clients (RPC, Stratum v2 Template Provider in the future)

View File

@ -33,6 +33,7 @@ interface BlockTemplate $Proxy.wrap("interfaces::BlockTemplate") {
getCoinbaseMerklePath @8 (context: Proxy.Context) -> (result: List(Data));
submitSolution @9 (context: Proxy.Context, version: UInt32, timestamp: UInt32, nonce: UInt32, coinbase :Data) -> (result: Bool);
waitNext @10 (context: Proxy.Context, options: BlockWaitOptions) -> (result: BlockTemplate);
interruptWait @11() -> ();
}
struct BlockCreateOptions $Proxy.wrap("node::BlockCreateOptions") {

View File

@ -30,10 +30,36 @@
namespace ipc {
namespace capnp {
namespace {
void IpcLogFn(bool raise, std::string message)
BCLog::Level ConvertIPCLogLevel(mp::Log level)
{
LogDebug(BCLog::IPC, "%s\n", message);
if (raise) throw Exception(message);
switch (level) {
case mp::Log::Trace: return BCLog::Level::Trace;
case mp::Log::Debug: return BCLog::Level::Debug;
case mp::Log::Info: return BCLog::Level::Info;
case mp::Log::Warning: return BCLog::Level::Warning;
case mp::Log::Error: return BCLog::Level::Error;
case mp::Log::Raise: return BCLog::Level::Error;
} // no default case, so the compiler can warn about missing cases
// Be conservative and assume that if MP ever adds a new log level, it
// should only be shown at our most verbose level.
return BCLog::Level::Trace;
}
mp::Log GetRequestedIPCLogLevel()
{
if (LogAcceptCategory(BCLog::IPC, BCLog::Level::Trace)) return mp::Log::Trace;
if (LogAcceptCategory(BCLog::IPC, BCLog::Level::Debug)) return mp::Log::Debug;
// Info, Warning, and Error are logged unconditionally
return mp::Log::Info;
}
void IpcLogFn(mp::LogMessage message)
{
LogPrintLevel(BCLog::IPC, ConvertIPCLogLevel(message.level), "%s\n", message.message);
if (message.level == mp::Log::Raise) throw Exception(message.message);
}
class CapnpProtocol : public Protocol
@ -62,7 +88,11 @@ public:
{
assert(!m_loop);
mp::g_thread_context.thread_name = mp::ThreadName(exe_name);
m_loop.emplace(exe_name, &IpcLogFn, &m_context);
mp::LogOptions opts = {
.log_fn = IpcLogFn,
.log_level = GetRequestedIPCLogLevel()
};
m_loop.emplace(exe_name, std::move(opts), &m_context);
if (ready_fn) ready_fn();
mp::ServeStream<messages::Init>(*m_loop, fd, init);
m_parent_connection = &m_loop->m_incoming_connections.back();
@ -90,7 +120,11 @@ public:
std::promise<void> promise;
m_loop_thread = std::thread([&] {
util::ThreadRename("capnp-loop");
m_loop.emplace(exe_name, &IpcLogFn, &m_context);
mp::LogOptions opts = {
.log_fn = IpcLogFn,
.log_level = GetRequestedIPCLogLevel()
};
m_loop.emplace(exe_name, std::move(opts), &m_context);
m_loop_ref.emplace(*m_loop);
promise.set_value();
m_loop->loop();

View File

@ -918,15 +918,21 @@ public:
std::unique_ptr<BlockTemplate> waitNext(BlockWaitOptions options) override
{
auto new_template = WaitAndCreateNewBlock(chainman(), notifications(), m_node.mempool.get(), m_block_template, options, m_assemble_options);
auto new_template = WaitAndCreateNewBlock(chainman(), notifications(), m_node.mempool.get(), m_block_template, options, m_assemble_options, m_interrupt_wait);
if (new_template) return std::make_unique<BlockTemplateImpl>(m_assemble_options, std::move(new_template), m_node);
return nullptr;
}
void interruptWait() override
{
InterruptWait(notifications(), m_interrupt_wait);
}
const BlockAssembler::Options m_assemble_options;
const std::unique_ptr<CBlockTemplate> m_block_template;
bool m_interrupt_wait{false};
ChainstateManager& chainman() { return *Assert(m_node.chainman); }
KernelNotifications& notifications() { return *Assert(m_node.notifications); }
NodeContext& m_node;

View File

@ -29,6 +29,7 @@
#include <algorithm>
#include <utility>
#include <numeric>
namespace node {
@ -453,12 +454,20 @@ void AddMerkleRootAndCoinbase(CBlock& block, CTransactionRef coinbase, uint32_t
block.hashMerkleRoot = BlockMerkleRoot(block);
}
void InterruptWait(KernelNotifications& kernel_notifications, bool& interrupt_wait)
{
LOCK(kernel_notifications.m_tip_block_mutex);
interrupt_wait = true;
kernel_notifications.m_tip_block_cv.notify_all();
}
std::unique_ptr<CBlockTemplate> WaitAndCreateNewBlock(ChainstateManager& chainman,
KernelNotifications& kernel_notifications,
CTxMemPool* mempool,
const std::unique_ptr<CBlockTemplate>& block_template,
const BlockWaitOptions& options,
const BlockAssembler::Options& assemble_options)
const BlockAssembler::Options& assemble_options,
bool& interrupt_wait)
{
// Delay calculating the current template fees, just in case a new block
// comes in before the next tick.
@ -483,8 +492,12 @@ std::unique_ptr<CBlockTemplate> WaitAndCreateNewBlock(ChainstateManager& chainma
// method on BlockTemplate and no template could have been
// generated before a tip exists.
tip_changed = Assume(tip_block) && tip_block != block_template->block.hashPrevBlock;
return tip_changed || chainman.m_interrupt;
return tip_changed || chainman.m_interrupt || interrupt_wait;
});
if (interrupt_wait) {
interrupt_wait = false;
return nullptr;
}
}
if (chainman.m_interrupt) return nullptr;
@ -522,18 +535,13 @@ std::unique_ptr<CBlockTemplate> WaitAndCreateNewBlock(ChainstateManager& chainma
// Calculate the original template total fees if we haven't already
if (current_fees == -1) {
current_fees = 0;
for (CAmount fee : block_template->vTxFees) {
current_fees += fee;
}
current_fees = std::accumulate(block_template->vTxFees.begin(), block_template->vTxFees.end(), CAmount{0});
}
CAmount new_fees = 0;
for (CAmount fee : new_tmpl->vTxFees) {
new_fees += fee;
Assume(options.fee_threshold != MAX_MONEY);
if (new_fees >= current_fees + options.fee_threshold) return new_tmpl;
}
// Check if fees increased enough to return the new template
const CAmount new_fees = std::accumulate(new_tmpl->vTxFees.begin(), new_tmpl->vTxFees.end(), CAmount{0});
Assume(options.fee_threshold != MAX_MONEY);
if (new_fees >= current_fees + options.fee_threshold) return new_tmpl;
}
now = NodeClock::now();

View File

@ -238,6 +238,9 @@ void ApplyArgsManOptions(const ArgsManager& gArgs, BlockAssembler::Options& opti
/* Compute the block's merkle root, insert or replace the coinbase transaction and the merkle root into the block */
void AddMerkleRootAndCoinbase(CBlock& block, CTransactionRef coinbase, uint32_t version, uint32_t timestamp, uint32_t nonce);
/* Interrupt the current wait for the next block template. */
void InterruptWait(KernelNotifications& kernel_notifications, bool& interrupt_wait);
/**
* Return a new block template when fees rise to a certain threshold or after a
* new tip; return nullopt if timeout is reached.
@ -247,7 +250,8 @@ std::unique_ptr<CBlockTemplate> WaitAndCreateNewBlock(ChainstateManager& chainma
CTxMemPool* mempool,
const std::unique_ptr<CBlockTemplate>& block_template,
const BlockWaitOptions& options,
const BlockAssembler::Options& assemble_options);
const BlockAssembler::Options& assemble_options,
bool& interrupt_wait);
/* Locks cs_main and returns the block hash and block height of the active chain if it exists; otherwise, returns nullopt.*/
std::optional<BlockRef> GetTip(ChainstateManager& chainman);

View File

@ -72,6 +72,9 @@ namespace {
// don't add private key handling cmd's to the history
const QStringList historyFilter = QStringList()
<< "createwallet"
<< "createwalletdescriptor"
<< "migratewallet"
<< "signmessagewithprivkey"
<< "signrawtransactionwithkey"
<< "walletpassphrase"

View File

@ -52,32 +52,78 @@ bool TransactionFilterProxy::filterAcceptsRow(int sourceRow, const QModelIndex &
void TransactionFilterProxy::setDateRange(const std::optional<QDateTime>& from, const std::optional<QDateTime>& to)
{
#if QT_VERSION >= QT_VERSION_CHECK(6, 10, 0)
beginFilterChange();
#endif
dateFrom = from;
dateTo = to;
#if QT_VERSION >= QT_VERSION_CHECK(6, 10, 0)
endFilterChange(QSortFilterProxyModel::Direction::Rows);
#else
invalidateFilter();
#endif
}
void TransactionFilterProxy::setSearchString(const QString &search_string)
{
if (m_search_string == search_string) return;
#if QT_VERSION >= QT_VERSION_CHECK(6, 10, 0)
beginFilterChange();
#endif
m_search_string = search_string;
#if QT_VERSION >= QT_VERSION_CHECK(6, 10, 0)
endFilterChange(QSortFilterProxyModel::Direction::Rows);
#else
invalidateFilter();
#endif
}
void TransactionFilterProxy::setTypeFilter(quint32 modes)
{
#if QT_VERSION >= QT_VERSION_CHECK(6, 10, 0)
beginFilterChange();
#endif
this->typeFilter = modes;
#if QT_VERSION >= QT_VERSION_CHECK(6, 10, 0)
endFilterChange(QSortFilterProxyModel::Direction::Rows);
#else
invalidateFilter();
#endif
}
void TransactionFilterProxy::setMinAmount(const CAmount& minimum)
{
#if QT_VERSION >= QT_VERSION_CHECK(6, 10, 0)
beginFilterChange();
#endif
this->minAmount = minimum;
#if QT_VERSION >= QT_VERSION_CHECK(6, 10, 0)
endFilterChange(QSortFilterProxyModel::Direction::Rows);
#else
invalidateFilter();
#endif
}
void TransactionFilterProxy::setShowInactive(bool _showInactive)
{
#if QT_VERSION >= QT_VERSION_CHECK(6, 10, 0)
beginFilterChange();
#endif
this->showInactive = _showInactive;
#if QT_VERSION >= QT_VERSION_CHECK(6, 10, 0)
endFilterChange(QSortFilterProxyModel::Direction::Rows);
#else
invalidateFilter();
#endif
}

View File

@ -936,8 +936,9 @@ static RPCHelpMan submitpackage()
,
{
{"package", RPCArg::Type::ARR, RPCArg::Optional::NO, "An array of raw transactions.\n"
"The package must solely consist of a child transaction and all of its unconfirmed parents, if any. None of the parents may depend on each other.\n"
"The package must be topologically sorted, with the child being the last element in the array.",
"The package must consist of a transaction with (some, all, or none of) its unconfirmed parents. A single transaction is permitted.\n"
"None of the parents may depend on each other. Parents that are already in mempool do not need to be present in the package.\n"
"The package must be topologically sorted, with the child being the last element in the array if there are multiple elements.",
{
{"rawtx", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, ""},
},

View File

@ -113,6 +113,22 @@ void MinerTestingSetup::TestPackageSelection(const CScript& scriptPubKey, const
options.coinbase_output_script = scriptPubKey;
LOCK(tx_mempool.cs);
BOOST_CHECK(tx_mempool.size() == 0);
// Block template should only have a coinbase when there's nothing in the mempool
std::unique_ptr<BlockTemplate> block_template = mining->createNewBlock(options);
BOOST_REQUIRE(block_template);
CBlock block{block_template->getBlock()};
BOOST_REQUIRE_EQUAL(block.vtx.size(), 1U);
// waitNext() on an empty mempool should return nullptr because there is no better template
auto should_be_nullptr = block_template->waitNext({.timeout = MillisecondsDouble{0}, .fee_threshold = 1});
BOOST_REQUIRE(should_be_nullptr == nullptr);
// Unless fee_threshold is 0
block_template = block_template->waitNext({.timeout = MillisecondsDouble{0}, .fee_threshold = 0});
BOOST_REQUIRE(block_template);
// Test the ancestor feerate transaction selection.
TestMemPoolEntryHelper entry;
@ -144,9 +160,9 @@ void MinerTestingSetup::TestPackageSelection(const CScript& scriptPubKey, const
const auto high_fee_tx{entry.Fee(50000).Time(Now<NodeSeconds>()).SpendsCoinbase(false).FromTx(tx)};
AddToMempool(tx_mempool, high_fee_tx);
std::unique_ptr<BlockTemplate> block_template = mining->createNewBlock(options);
block_template = mining->createNewBlock(options);
BOOST_REQUIRE(block_template);
CBlock block{block_template->getBlock()};
block = block_template->getBlock();
BOOST_REQUIRE_EQUAL(block.vtx.size(), 4U);
BOOST_CHECK(block.vtx[1]->GetHash() == hashParentTx);
BOOST_CHECK(block.vtx[2]->GetHash() == hashHighFeeTx);
@ -184,7 +200,7 @@ void MinerTestingSetup::TestPackageSelection(const CScript& scriptPubKey, const
AddToMempool(tx_mempool, entry.Fee(feeToUse).FromTx(tx));
// waitNext() should return nullptr because there is no better template
auto should_be_nullptr = block_template->waitNext({.timeout = MillisecondsDouble{0}, .fee_threshold = 1});
should_be_nullptr = block_template->waitNext({.timeout = MillisecondsDouble{0}, .fee_threshold = 1});
BOOST_REQUIRE(should_be_nullptr == nullptr);
block = block_template->getBlock();

View File

@ -153,6 +153,7 @@ class IPCInterfaceTest(BitcoinTestFramework):
self.log.debug("Wait for a new template")
waitoptions = self.capnp_modules['mining'].BlockWaitOptions()
waitoptions.timeout = timeout
waitoptions.feeThreshold = 1
waitnext = template.result.waitNext(ctx, waitoptions)
self.generate(self.nodes[0], 1)
template2 = await waitnext
@ -168,6 +169,7 @@ class IPCInterfaceTest(BitcoinTestFramework):
block3 = await self.parse_and_deserialize_block(template4, ctx)
assert_equal(len(block3.vtx), 2)
self.log.debug("Wait again, this should return the same template, since the fee threshold is zero")
waitoptions.feeThreshold = 0
template5 = await template4.result.waitNext(ctx, waitoptions)
block4 = await self.parse_and_deserialize_block(template5, ctx)
assert_equal(len(block4.vtx), 2)
@ -182,6 +184,28 @@ class IPCInterfaceTest(BitcoinTestFramework):
template7 = await template6.result.waitNext(ctx, waitoptions)
assert_equal(template7.to_dict(), {})
self.log.debug("interruptWait should abort the current wait")
wait_started = asyncio.Event()
async def wait_for_block():
new_waitoptions = self.capnp_modules['mining'].BlockWaitOptions()
new_waitoptions.timeout = waitoptions.timeout * 60 # 1 minute wait
new_waitoptions.feeThreshold = 1
wait_started.set()
return await template6.result.waitNext(ctx, new_waitoptions)
async def interrupt_wait():
await wait_started.wait() # Wait for confirmation wait started
await asyncio.sleep(0.1) # Minimal buffer
template6.result.interruptWait()
miniwallet.send_self_transfer(fee_rate=10, from_node=self.nodes[0])
wait_task = asyncio.create_task(wait_for_block())
interrupt_task = asyncio.create_task(interrupt_wait())
result = await wait_task
await interrupt_task
assert_equal(result.to_dict(), {})
current_block_height = self.nodes[0].getchaintips()[0]["height"]
check_opts = self.capnp_modules['mining'].BlockCheckOptions()
template = await mining.result.createNewBlock(opts)

View File

@ -161,7 +161,7 @@ class TestNode():
self.args.append("-logsourcelocations")
if self.version_is_at_least(239000):
self.args.append("-loglevel=trace")
if self.version_is_at_least(299900):
if self.version_is_at_least(290100):
self.args.append("-nologratelimit")
# Default behavior from global -v2transport flag is added to args to persist it over restarts.

View File

@ -336,6 +336,7 @@ BASE_SCRIPTS = [
'p2p_tx_privacy.py',
'rpc_getdescriptoractivity.py',
'rpc_scanblocks.py',
'tool_bitcoin.py',
'p2p_sendtxrcncl.py',
'rpc_scantxoutset.py',
'feature_unsupported_utxo_db.py',

111
test/functional/tool_bitcoin.py Executable file
View File

@ -0,0 +1,111 @@
#!/usr/bin/env python3
# Copyright (c) The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Test the bitcoin wrapper tool."""
from test_framework.test_framework import (
BitcoinTestFramework,
SkipTest,
)
from test_framework.util import (
append_config,
assert_equal,
)
import platform
import re
class ToolBitcoinTest(BitcoinTestFramework):
def set_test_params(self):
self.setup_clean_chain = True
self.num_nodes = 1
def skip_test_if_missing_module(self):
# Skip test on windows because currently when `bitcoin node -version` is
# run on windows, python doesn't capture output from the child
# `bitcoind` and `bitcoin-node` process started with _wexecvp, and
# stdout/stderr are always empty. See
# https://github.com/bitcoin/bitcoin/pull/33229#issuecomment-3265524908
if platform.system() == "Windows":
raise SkipTest("Test does not currently work on windows")
def setup_network(self):
"""Set up nodes normally, but save a copy of their arguments before starting them."""
self.add_nodes(self.num_nodes, self.extra_args)
node_argv = self.get_binaries().node_argv()
self.node_options = [node.args[len(node_argv):] for node in self.nodes]
assert all(node.args[:len(node_argv)] == node_argv for node in self.nodes)
def set_cmd_args(self, node, args):
"""Set up node so it will be started through bitcoin wrapper command with specified arguments."""
node.args = [self.binary_paths.bitcoin_bin] + args + ["node"] + self.node_options[node.index]
def test_args(self, cmd_args, node_args, expect_exe=None, expect_error=None):
node = self.nodes[0]
self.set_cmd_args(node, cmd_args)
extra_args = node_args + ["-version"]
if expect_error is not None:
node.assert_start_raises_init_error(expected_msg=expect_error, extra_args=extra_args)
else:
assert expect_exe
node.start(extra_args=extra_args)
ret, out, err = get_node_output(node)
try:
assert_equal(get_exe_name(out), expect_exe.encode())
assert_equal(err, b"")
except Exception as e:
raise RuntimeError(f"Unexpected output from {node.args + extra_args}: {out=!r} {err=!r} {ret=!r}") from e
def run_test(self):
node = self.nodes[0]
self.log.info("Ensure bitcoin node command invokes bitcoind by default")
self.test_args([], [], expect_exe="bitcoind")
self.log.info("Ensure bitcoin -M invokes bitcoind")
self.test_args(["-M"], [], expect_exe="bitcoind")
self.log.info("Ensure bitcoin -M does not accept -ipcbind")
self.test_args(["-M"], ["-ipcbind=unix"], expect_error='Error: Error parsing command line arguments: Invalid parameter -ipcbind=unix')
if self.is_ipc_compiled():
self.log.info("Ensure bitcoin -m invokes bitcoin-node")
self.test_args(["-m"], [], expect_exe="bitcoin-node")
self.log.info("Ensure bitcoin -m does accept -ipcbind")
self.test_args(["-m"], ["-ipcbind=unix"], expect_exe="bitcoin-node")
self.log.info("Ensure bitcoin accepts -ipcbind by default")
self.test_args([], ["-ipcbind=unix"], expect_exe="bitcoin-node")
self.log.info("Ensure bitcoin recognizes -ipcbind in config file")
append_config(node.datadir_path, ["ipcbind=unix"])
self.test_args([], [], expect_exe="bitcoin-node")
def get_node_output(node):
ret = node.process.wait(timeout=60)
node.stdout.seek(0)
node.stderr.seek(0)
out = node.stdout.read()
err = node.stderr.read()
node.stdout.close()
node.stderr.close()
# Clean up TestNode state
node.running = False
node.process = None
node.rpc_connected = False
node.rpc = None
return ret, out, err
def get_exe_name(version_str):
"""Get exe name from last word of first line of version string."""
return re.match(rb".*?(\S+)\s*?(?:\n|$)", version_str.strip()).group(1)
if __name__ == '__main__':
ToolBitcoinTest(__file__).main()

View File

@ -23,7 +23,7 @@ CMD_GREP_WALLET_ARGS = r"git grep --function-context 'void WalletInit::AddWallet
CMD_GREP_WALLET_HIDDEN_ARGS = r"git grep --function-context 'void DummyWalletInit::AddWalletOptions' -- {}".format(CMD_ROOT_DIR)
CMD_GREP_DOCS = r"git grep --perl-regexp '{}' {}".format(REGEX_DOC, CMD_ROOT_DIR)
# list unsupported, deprecated and duplicate args as they need no documentation
SET_DOC_OPTIONAL = set(['-h', '-?', '-dbcrashratio', '-forcecompactdb'])
SET_DOC_OPTIONAL = set(['-h', '-?', '-dbcrashratio', '-forcecompactdb', '-ipcconnect', '-ipcfd'])
def lint_missing_argument_documentation():