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/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/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. 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: 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. 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) | 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/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/). 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/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]); } diff --git a/test/functional/feature_init.py b/test/functional/feature_init.py index b9d41a9713c..f3572013b37 100755 --- a/test/functional/feature_init.py +++ b/test/functional/feature_init.py @@ -3,6 +3,7 @@ # 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 @@ -240,9 +241,59 @@ 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.) + + 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] + + 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) + + 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': + # 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() + + 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): self.init_pid_test() self.init_stress_test() + self.break_wait_test() if __name__ == '__main__':