From 7ea855fd551738cabb215e1172097c319574cf8b Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Thu, 18 Dec 2025 20:43:27 +0000 Subject: [PATCH 1/9] build: Update minimum required Boost version Building with Boost 1.73.0 is broken. Github-Pull: #34107 Rebased-From: f480c1e7177744d11b058c3a9422975d7ec1af46 --- cmake/module/AddBoostIfNeeded.cmake | 2 +- doc/dependencies.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/module/AddBoostIfNeeded.cmake b/cmake/module/AddBoostIfNeeded.cmake index e2eaf5565ac..b3f248009d8 100644 --- a/cmake/module/AddBoostIfNeeded.cmake +++ b/cmake/module/AddBoostIfNeeded.cmake @@ -29,7 +29,7 @@ function(add_boost_if_needed) endif() endif() - find_package(Boost 1.73.0 REQUIRED CONFIG) + find_package(Boost 1.74.0 REQUIRED CONFIG) mark_as_advanced(Boost_INCLUDE_DIR boost_headers_DIR) # Workaround for a bug in NetBSD pkgsrc. # See: https://github.com/NetBSD/pkgsrc/issues/167. diff --git a/doc/dependencies.md b/doc/dependencies.md index 93916aaf5dc..79f7f05e8af 100644 --- a/doc/dependencies.md +++ b/doc/dependencies.md @@ -19,7 +19,7 @@ Bitcoin Core requires one of the following compilers. | Dependency | Releases | Minimum required | | --- | --- | --- | -| [Boost](../depends/packages/boost.mk) | [link](https://www.boost.org/users/download/) | [1.73.0](https://github.com/bitcoin/bitcoin/pull/29066) | +| [Boost](../depends/packages/boost.mk) | [link](https://www.boost.org/users/download/) | [1.74.0](https://github.com/bitcoin/bitcoin/pull/34107) | | CMake | [link](https://cmake.org/) | [3.22](https://github.com/bitcoin/bitcoin/pull/30454) | | [libevent](../depends/packages/libevent.mk) | [link](https://github.com/libevent/libevent/releases) | [2.1.8](https://github.com/bitcoin/bitcoin/pull/24681) | From b734c4026b008f16e318fab7471984c0c1a87e88 Mon Sep 17 00:00:00 2001 From: fanquake Date: Wed, 26 Nov 2025 13:21:04 +0000 Subject: [PATCH 2/9] guix: reduce allowed exported symbols Github-Pull: #33950 Rebased-From: 7b90b4f5bb10e2156709b07e3996f867e2421232 --- contrib/guix/symbol-check.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/contrib/guix/symbol-check.py b/contrib/guix/symbol-check.py index 79ab6b0fe54..df3d5461afb 100755 --- a/contrib/guix/symbol-check.py +++ b/contrib/guix/symbol-check.py @@ -46,8 +46,7 @@ MAX_VERSIONS = { # Ignore symbols that are exported as part of every executable IGNORE_EXPORTS = { -'environ', '_environ', '__environ', '_fini', '_init', 'stdin', -'stdout', 'stderr', +'stdin', 'stdout', 'stderr', } # Expected linker-loader names can be found here: From f620dde4113924c6153c3d8b6c4210c128761325 Mon Sep 17 00:00:00 2001 From: brunoerg Date: Wed, 17 Dec 2025 11:57:11 -0300 Subject: [PATCH 3/9] fuzz: doc: remove any mention to address_deserialize_v2 Github-Pull: #34091 Rebased-From: caf4843a59a9d2512d69f8fd88a9672112bd80ac --- doc/fuzzing.md | 2 +- src/test/fuzz/fuzz.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/fuzzing.md b/doc/fuzzing.md index 8a024e591c5..905e50fb524 100644 --- a/doc/fuzzing.md +++ b/doc/fuzzing.md @@ -79,7 +79,7 @@ of the test. Just make sure to use double-dash to distinguish them from the fuzzer's own arguments: ```sh -$ FUZZ=address_deserialize_v2 build_fuzz/bin/fuzz -runs=1 fuzz_corpora/address_deserialize_v2 --checkaddrman=5 --printtoconsole=1 +$ FUZZ=address_deserialize build_fuzz/bin/fuzz -runs=1 fuzz_corpora/address_deserialize --checkaddrman=5 --printtoconsole=1 ``` ## Fuzzing corpora diff --git a/src/test/fuzz/fuzz.cpp b/src/test/fuzz/fuzz.cpp index d4d82a623b4..26121968062 100644 --- a/src/test/fuzz/fuzz.cpp +++ b/src/test/fuzz/fuzz.cpp @@ -51,7 +51,7 @@ static std::vector g_args; static void SetArgs(int argc, char** argv) { for (int i = 1; i < argc; ++i) { // Only take into account arguments that start with `--`. The others are for the fuzz engine: - // `fuzz -runs=1 fuzz_corpora/address_deserialize_v2 --checkaddrman=5` + // `fuzz -runs=1 fuzz_corpora/address_deserialize --checkaddrman=5` if (strlen(argv[i]) > 2 && argv[i][0] == '-' && argv[i][1] == '-') { g_args.push_back(argv[i]); } From ed0774bd08b83813f162be33672b7d6c7fff9933 Mon Sep 17 00:00:00 2001 From: fanquake Date: Mon, 29 Dec 2025 12:15:34 +0000 Subject: [PATCH 4/9] doc: update copyright year Github-Pull: #34174 Rebased-From: b23b901363c56043c536f32261ac8cb540624a84 --- CMakeLists.txt | 2 +- COPYING | 4 ++-- contrib/debian/copyright | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 781771eea1c..2a7983c0c33 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,7 +32,7 @@ set(CLIENT_VERSION_MINOR 1) set(CLIENT_VERSION_BUILD 0) set(CLIENT_VERSION_RC 0) set(CLIENT_VERSION_IS_RELEASE "true") -set(COPYRIGHT_YEAR "2025") +set(COPYRIGHT_YEAR "2026") # During the enabling of the CXX and CXXOBJ languages, we modify # CMake's compiler/linker invocation strings by appending the content diff --git a/COPYING b/COPYING index 23dc5e905b6..89960cbf2f2 100644 --- a/COPYING +++ b/COPYING @@ -1,7 +1,7 @@ The MIT License (MIT) -Copyright (c) 2009-2025 The Bitcoin Core developers -Copyright (c) 2009-2025 Bitcoin Developers +Copyright (c) 2009-2026 The Bitcoin Core developers +Copyright (c) 2009-2026 Bitcoin Developers Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/contrib/debian/copyright b/contrib/debian/copyright index 4e4deef9a1f..4f703770361 100644 --- a/contrib/debian/copyright +++ b/contrib/debian/copyright @@ -5,7 +5,7 @@ Upstream-Contact: Satoshi Nakamoto Source: https://github.com/bitcoin/bitcoin Files: * -Copyright: 2009-2025, Bitcoin Core Developers +Copyright: 2009-2026, Bitcoin Core Developers License: Expat Comment: The Bitcoin Core Developers encompasses all contributors to the project, listed in the release notes or the git log. From 8769c718f419519e9267b282475c342bf4688cb9 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Tue, 30 Dec 2025 19:45:14 +0000 Subject: [PATCH 5/9] doc: Update OpenBSD Build Guide Github-Pull: #34182 Rebased-From: 84d8c52662545b33c0d02c8ac02ae694950ad9d4 --- doc/build-openbsd.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/doc/build-openbsd.md b/doc/build-openbsd.md index fdeafe88d76..4ea58795a05 100644 --- a/doc/build-openbsd.md +++ b/doc/build-openbsd.md @@ -1,6 +1,6 @@ # OpenBSD Build Guide -**Updated for OpenBSD [7.6](https://www.openbsd.org/76.html)** +**Updated for OpenBSD [7.8](https://www.openbsd.org/78.html)** This guide describes how to build bitcoind, command-line utilities, and GUI on OpenBSD. @@ -21,8 +21,11 @@ pkg_add sqlite3 To build Bitcoin Core without the wallet, use `-DENABLE_WALLET=OFF`. -Cap'n Proto is needed for IPC functionality (see [multiprocess.md](multiprocess.md)) -and can be built from source: https://capnproto.org/install.html +Cap'n Proto is needed for IPC functionality (see [multiprocess.md](multiprocess.md)): + +```bash +pkg_add capnproto +``` Compile with `-DENABLE_IPC=OFF` if you do not need IPC functionality. From 6983c7d7695198b8cefe67b43b7061de93320aa1 Mon Sep 17 00:00:00 2001 From: Ryan Ofsky Date: Tue, 30 Sep 2025 14:47:17 -0400 Subject: [PATCH 6/9] test: Test SIGTERM handling during waitforblockheight call Currently when CTRL-C is pressed and there is an active `waitforblockheight`, or `waitforblock`, or `waitfornewblock` RPC call, or a mining interface `waitTipChanged` IPC call with a long timeout, the node will not shut down right away, and will wait for the timeout to be reached before exiting. This behavior is not ideal and only happens when the node is stopped with CTRL-C or SIGTERM. When the node is stopped with `bitcoin-cli stop`, the wait calls are interrupted and the node does shut down right away. The next commit improves node behavior. This commit just adds test coverage to simplify the next commit and clarify the change in behavior there. Github-Pull: #33511 Rebased-From: 6a29f79006a9d60b476893dface5eea8f9bf271c --- test/functional/feature_init.py | 56 +++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/test/functional/feature_init.py b/test/functional/feature_init.py index b9d41a9713c..d8a773bbe88 100755 --- a/test/functional/feature_init.py +++ b/test/functional/feature_init.py @@ -3,13 +3,16 @@ # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Tests related to node initialization.""" +from concurrent.futures import ThreadPoolExecutor from pathlib import Path import os import platform import shutil import signal import subprocess +import time +from test_framework.authproxy import JSONRPCException from test_framework.test_framework import BitcoinTestFramework from test_framework.test_node import ( BITCOIN_PID_FILENAME_DEFAULT, @@ -240,9 +243,62 @@ class InitTest(BitcoinTestFramework): self.stop_node(0) assert not custom_pidfile_absolute.exists() + def break_wait_test(self): + """Test what happens when a break signal is sent during a + waitforblockheight RPC call with a long timeout. Ctrl-Break is sent on + Windows and SIGTERM is sent on other platforms, to trigger the same node + shutdown sequence that would happen if Ctrl-C were pressed in a + terminal. (This can be different than the node shutdown sequence that + happens when the stop RPC is sent.) + + Currently when the break signal is sent, it does not interrupt the + waitforblockheight RPC call, and the node does not exit until it times + out.""" + + self.log.info("Testing waitforblockheight RPC call followed by break signal") + node = self.nodes[0] + + if platform.system() == 'Windows': + # CREATE_NEW_PROCESS_GROUP prevents python test from exiting + # with STATUS_CONTROL_C_EXIT (-1073741510) when break is sent. + self.start_node(node.index, creationflags=subprocess.CREATE_NEW_PROCESS_GROUP) + else: + self.start_node(node.index) + + current_height = node.getblock(node.getbestblockhash())['height'] + + with ThreadPoolExecutor(max_workers=1) as ex: + # Call waitforblockheight with wait timeout longer than RPC timeout, + # so it is possible to distinguish whether it times out or returns + # early. If it times out it will throw an exception, and if it + # returns early it will return the current block height. + self.log.debug(f"Calling waitforblockheight with {self.rpc_timeout} sec RPC timeout") + fut = ex.submit(node.waitforblockheight, height=current_height+1, timeout=self.rpc_timeout*1000*2) + time.sleep(1) + + self.log.debug(f"Sending break signal to pid {node.process.pid}") + if platform.system() == 'Windows': + # Note: CTRL_C_EVENT should not be sent here because unlike + # CTRL_BREAK_EVENT it can not be targeted at a specific process + # group and may behave unpredictably. + node.process.send_signal(signal.CTRL_BREAK_EVENT) + else: + # Note: signal.SIGINT would work here as well + node.process.send_signal(signal.SIGTERM) + node.process.wait() + + try: + result = fut.result() + raise Exception(f"waitforblockheight returned {result!r}") + except JSONRPCException as e: + self.log.debug(f"waitforblockheight raised {e!r}") + assert_equal(e.error['code'], -344) # -344 is RPC timeout + node.wait_until_stopped() + def run_test(self): self.init_pid_test() self.init_stress_test() + self.break_wait_test() if __name__ == '__main__': From c065bcd2d7edd79b60c3224911640817b3cb837a Mon Sep 17 00:00:00 2001 From: Ryan Ofsky Date: Wed, 1 Oct 2025 13:00:33 -0400 Subject: [PATCH 7/9] init: Signal m_tip_block_cv on Ctrl-C Signal m_tip_block_cv when Ctrl-C is pressed or SIGTERM is received, the same way it is currently signalled when the `stop` RPC is called. This lets RPC calls like `waitforblockheight` and IPC calls like `waitTipChanged` be interrupted, instead of waiting for their original timeouts and delaying shutdown. Historical notes: - The behavior where `stop` RPC signals `m_tip_block_cv`, but CTRL-C does not, has been around since the condition variable was introduced in #30409 (7eccdaf16081d6f624c4dc21df75b0474e049d2b). - The signaling was later moved without changing behavior in #30967 (5ca28ef28bcca1775ff49921fc2528d9439b71ab). This commit moves it again to the Interrupt() function, which is probably the place it should have been added initially, so it works for Ctrl-C shutdowns as well as `stop` shutdowns. - A Qt shutdown bug calling wait methods was fixed previously in #18452 (da73f1513a637a9f347b64de66564d6cdb2541f8), and this change updates that fix to avoid the hang happening again in Qt. Github-Pull: #33511 Rebased-From: c25a5e670b27d3b6eb958ce437dbe89678bd1511 --- src/init.cpp | 4 ++-- src/node/interfaces.cpp | 8 +------- test/functional/feature_init.py | 15 +++++---------- 3 files changed, 8 insertions(+), 19 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 02e5f2a2488..def3211ef41 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -215,8 +215,6 @@ void InitContext(NodeContext& node) node.shutdown_request = [&node] { assert(node.shutdown_signal); if (!(*node.shutdown_signal)()) return false; - // Wake any threads that may be waiting for the tip to change. - if (node.notifications) WITH_LOCK(node.notifications->m_tip_block_mutex, node.notifications->m_tip_block_cv.notify_all()); return true; }; } @@ -267,6 +265,8 @@ void Interrupt(NodeContext& node) #if HAVE_SYSTEM ShutdownNotify(*node.args); #endif + // Wake any threads that may be waiting for the tip to change. + if (node.notifications) WITH_LOCK(node.notifications->m_tip_block_mutex, node.notifications->m_tip_block_cv.notify_all()); InterruptHTTPServer(); InterruptHTTPRPC(); InterruptRPC(); diff --git a/src/node/interfaces.cpp b/src/node/interfaces.cpp index 509528d9c06..442aed1e5d5 100644 --- a/src/node/interfaces.cpp +++ b/src/node/interfaces.cpp @@ -132,7 +132,6 @@ public: } void appShutdown() override { - Interrupt(*m_context); Shutdown(*m_context); } void startShutdown() override @@ -141,12 +140,7 @@ public: if (!(Assert(ctx.shutdown_request))()) { LogError("Failed to send shutdown signal\n"); } - - // Stop RPC for clean shutdown if any of waitfor* commands is executed. - if (args().GetBoolArg("-server", false)) { - InterruptRPC(); - StopRPC(); - } + Interrupt(*m_context); } bool shutdownRequested() override { return ShutdownRequested(*Assert(m_context)); }; bool isSettingIgnored(const std::string& name) override diff --git a/test/functional/feature_init.py b/test/functional/feature_init.py index d8a773bbe88..0fa99470ddd 100755 --- a/test/functional/feature_init.py +++ b/test/functional/feature_init.py @@ -12,7 +12,6 @@ import signal import subprocess import time -from test_framework.authproxy import JSONRPCException from test_framework.test_framework import BitcoinTestFramework from test_framework.test_node import ( BITCOIN_PID_FILENAME_DEFAULT, @@ -251,9 +250,8 @@ class InitTest(BitcoinTestFramework): terminal. (This can be different than the node shutdown sequence that happens when the stop RPC is sent.) - Currently when the break signal is sent, it does not interrupt the - waitforblockheight RPC call, and the node does not exit until it times - out.""" + The waitforblockheight call should be interrupted and return right away, + and not time out.""" self.log.info("Testing waitforblockheight RPC call followed by break signal") node = self.nodes[0] @@ -287,12 +285,9 @@ class InitTest(BitcoinTestFramework): node.process.send_signal(signal.SIGTERM) node.process.wait() - try: - result = fut.result() - raise Exception(f"waitforblockheight returned {result!r}") - except JSONRPCException as e: - self.log.debug(f"waitforblockheight raised {e!r}") - assert_equal(e.error['code'], -344) # -344 is RPC timeout + result = fut.result() + self.log.debug(f"waitforblockheight returned {result!r}") + assert_equal(result["height"], current_height) node.wait_until_stopped() def run_test(self): From 7568bc3ab08e7a4c9b7bdbf4e14e73f5c5fcbfe1 Mon Sep 17 00:00:00 2001 From: MarcoFalke <*~=`'#}+{/-|&$^_@721217.xyz> Date: Mon, 22 Dec 2025 14:55:47 +0100 Subject: [PATCH 8/9] test: Avoid hard time.sleep(1) in feature_init.py Github-Pull: #34137 Rebased-From: fa727e3ec984106371eeedb34d7bbbbc3dcce4ff --- test/functional/feature_init.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/functional/feature_init.py b/test/functional/feature_init.py index 0fa99470ddd..f3572013b37 100755 --- a/test/functional/feature_init.py +++ b/test/functional/feature_init.py @@ -10,7 +10,6 @@ import platform import shutil import signal import subprocess -import time from test_framework.test_framework import BitcoinTestFramework from test_framework.test_node import ( @@ -272,7 +271,8 @@ class InitTest(BitcoinTestFramework): # returns early it will return the current block height. self.log.debug(f"Calling waitforblockheight with {self.rpc_timeout} sec RPC timeout") fut = ex.submit(node.waitforblockheight, height=current_height+1, timeout=self.rpc_timeout*1000*2) - time.sleep(1) + + self.wait_until(lambda: any(c["method"] == "waitforblockheight" for c in node.cli.getrpcinfo()["active_commands"])) self.log.debug(f"Sending break signal to pid {node.process.pid}") if platform.system() == 'Windows': From f22122bc27b52f4d82fb0a79e5e145f1e4112732 Mon Sep 17 00:00:00 2001 From: fanquake Date: Wed, 31 Dec 2025 12:24:25 +0000 Subject: [PATCH 9/9] doc: update release notes for v30.x --- doc/release-notes.md | 56 +++++++++++--------------------------------- 1 file changed, 14 insertions(+), 42 deletions(-) diff --git a/doc/release-notes.md b/doc/release-notes.md index 16120afb71d..683ec38da5c 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -1,9 +1,9 @@ v30.x Release Notes =================== -Bitcoin Core version v30.1 is now available from: +Bitcoin Core version v30.x is now available from: - + This release includes new features, various bug fixes and performance improvements, as well as updated translations. @@ -40,69 +40,41 @@ unsupported systems. Notable changes =============== -### Wallet +### IPC -- #33528 wallet: don't consider unconfirmed TRUC coins with ancestors +- #33511 init: Fix Ctrl-C shutdown hangs during wait calls ### Build -- #33580 depends: Use `$(package)_file_name` when downloading from the fallback -- #33906 depends: Add patch for Windows11Style plugin -- #32009 contrib: turn off compression of macOS SDK to fix determinism - -### IPC - -- #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 - -### P2P - -- #33723 chainparams: remove dnsseed.bitcoin.dashjr-list-of-p2p-nodes.us - -### GUI - -- gui#899 qt: Modernize custom filtering -- gui#901 Add createwallet, createwalletdescriptor, and migratewallet to history filter +- #33950 guix: reduce allowed exported symbols +- #34107 build: Update minimum required Boost version ### Test -- #33612 test: change log rate limit version gate +- #34137 test: Avoid hard time.sleep(1) in feature_init.py + +### Fuzz + +- #34091 fuzz: doc: remove any mention to address_deserialize_v2 ### Doc -- #33630 doc: correct topology requirements in submitpackage helptext -- #33826 scripted-diff: Remove obsolete comment -- #33827 doc: Correct pkgin command usage on NetBSD +- #34182 doc: Update OpenBSD Build Guide ### Misc -- #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) -- #33996 contrib: fix manpage generation +- #34174 doc: update copyright year to 2026 Credits ======= Thanks to everyone who directly contributed to this release: -- Ava Chow -- Cory Fields -- Eugene Siegel +- brunoerg - fanquake -- glozow - Hennadii Stepanov -- ismaelsadeeq - MarcoFalke - Ryan Ofsky -- SatsAndSports -- Sjors Provoost -- WakeTrainDev -- willcl-ark As well as to everyone that helped with translations on [Transifex](https://explore.transifex.com/bitcoin/bitcoin/).