Skip to content

http: replace WorkQueue and single threads handling for ThreadPool#33689

Merged
sedited merged 5 commits intobitcoin:masterfrom
furszy:2025_threadpool_http_server
Feb 11, 2026
Merged

http: replace WorkQueue and single threads handling for ThreadPool#33689
sedited merged 5 commits intobitcoin:masterfrom
furszy:2025_threadpool_http_server

Conversation

@furszy
Copy link
Member

@furszy furszy commented Oct 23, 2025

This has been a recent discovery; the general thread pool class created for #26966, cleanly
integrates into the HTTP server. It simplifies init, shutdown and requests execution logic.
Replacing code that was never unit tested for code that is properly unit and fuzz tested.
Although our functional test framework extensively uses this RPC interface (that’s how
we’ve been ensuring its correct behavior so far - which is not the best).

This clearly separates the responsibilities:
The HTTP server now focuses solely on receiving and dispatching requests, while ThreadPool handles
concurrency, queuing, and execution.

This will also allows us to experiment with further performance improvements at the task queuing and
execution level, such as a lock-free structure or task prioritization or any other implementation detail
like coroutines in the future, without having to deal with HTTP code that lives on a different layer.

Note:
The rationale behind introducing the ThreadPool first is to be able to easily cherry-pick it across different
working paths. Some of the ones that are benefited from it are #26966 for the parallelization of the indexes
initial sync, #31132 for the parallelization of the inputs fetching procedure, #32061 for the libevent replacement,
the kernel API #30595 (#30595 (comment)) to avoid blocking validation among others use cases not publicly available.

Note 2:
I could have created a wrapper around the existing code and replaced the WorkQueue in a subsequent
commit, but it didn’t seem worth the extra commits and review effort. The ThreadPool implements
essentially the same functionality in a more modern and cleaner way.

@DrahtBot
Copy link
Contributor

DrahtBot commented Oct 23, 2025

The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

Code Coverage & Benchmarks

For details see: https://corecheck.dev/bitcoin/bitcoin/pulls/33689.

Reviews

See the guideline for information on the review process.

Type Reviewers
ACK Eunovo, sedited, pinheadmz
Stale ACK ismaelsadeeq

If your review is incorrectly listed, please copy-paste <!--meta-tag:bot-skip--> into the comment that the bot should ignore.

Conflicts

Reviewers, this pull request conflicts with the following ones:

  • #34411 ([POC] Full Libevent removal by fanquake)
  • #34400 (wallet: parallel fast rescan (approx 5x speed up with 16 threads) by Eunovo)
  • #32061 (Replace libevent with our own HTTP and socket-handling implementation by pinheadmz)
  • #26966 (index: initial sync speedup, parallelize process by furszy)

If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

LLM Linter (✨ experimental)

Possible typos and grammar issues:

  • servers responses -> server responses or servers' responses [possessive is missing; "servers responses" is ungrammatical]

2026-01-30 21:18:09

@pinheadmz
Copy link
Member

concept ACK :-) will be reviewing this

@laanwj laanwj self-requested a review October 23, 2025 14:49
@laanwj
Copy link
Member

laanwj commented Oct 23, 2025

Adding myself as i wrote the original shitty code.

@Raimo33
Copy link
Contributor

Raimo33 commented Oct 24, 2025

Can't we use an already existing open source library instead of reinventing the wheel?

@furszy
Copy link
Member Author

furszy commented Oct 24, 2025

Can't we use an already existing open source library instead of reinventing the wheel?

That's a good question. It's usually where we all start.
Generally, the project consensus is to avoid introducing new external dependencies (unless they’re maintained by us) to minimize potential attack vectors. This doesn’t mean we should reinvent everything, just that we need to be very careful about what we decide to include.

That being said, for the changes introduced in this PR, can argue that we’re encapsulating, documenting, and unit + fuzz testing code that wasn’t covered before, while also improving separation of responsibilities. We’re not adding anything more complex or that behaves radically differently from what we currently have.
The nice property of this PR is that it will let us experiment with more complex approaches in the future without having to deal with application-specific code (like the HTTP server code). This also includes learning from other open source libraries for sure.

@sedited
Copy link
Contributor

sedited commented Oct 27, 2025

Approach ACK

@furszy furszy force-pushed the 2025_threadpool_http_server branch from bb71b0e to 195a962 Compare October 28, 2025 19:08
Copy link
Member

@ismaelsadeeq ismaelsadeeq left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Concept ACK, thanks for the seperation from the initial index PR.

Copy link
Member

@pinheadmz pinheadmz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK 195a96258f970c384ce180d57e73616904ef5fa1

Built and tested on macos/arm64 and debian/x86. Reviewed each commit and left a few comments.

I also tested the branch against other popular software that consumes the HTTP interface by running their CI:

The http worker threads are clearly labeled and visible in htop!

Image
Show Signature
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

ACK 195a96258f970c384ce180d57e73616904ef5fa1
-----BEGIN PGP SIGNATURE-----

iQIzBAEBCAAdFiEE5hdzzW4BBA4vG9eM5+KYS2KJyToFAmkCMdwACgkQ5+KYS2KJ
yTriXA//RRnzezUHdmzRlKmoSDA+ZBHz0RY3z2LGk63izb/YdYaJY9JBZL2Y9BA8
K2nyexdSDC/DFOm4H56ddEe6ChlB7w+uZc92SgFSLSvavInpZ80KEJRk07vgoIL7
hwuyyevWyOOU32iz1NE3q316TMaJmzVsPhRGwbdmTXNwJLtUX6g4czfh28ajW1DC
Y9ULKwT36rFHRcKwC1YZYuBJUNBZWQgVBcydcmS1UEykY4mBnCW9knrATwn/29b7
2AYPV+yuaiy9OpDEOJ8iKtZOPGR36NrIUleMUqruq4Sy2/TnJtm3AKNK0336/Fxu
MqVyPKSyusg7kBA6f2h/2+NHpbyLoboYhjZew+HvED/aFfi+Jla+nxybkUYXfciL
pzbND22TTuRGB1fKU7AwPD0TO9JwOTU385iEdpoGq8rbT3EpgPr31N4TeDQDJx5t
jPzzWZYj43JMuIc3bm/K5S2HYSdFZUEDQC81kbND+jOLF6YkJwS9794anLO38tvi
fip/eLK8Nw4pmWnW63/9lc+Y/1gLpgLDMxxhA1NKJyytk7z2IRo7vJKck6TqAjcZ
nU8Wv9/ful5ndDJfLIKuYT9jqRk9ORohVwv+P+ppuO8jhFjhuswxPlFJKkMXTeZn
hGi8QCrAUuibvVuLfLKVExJqSmmeUAkTVKp5ZTWLwNB7IkZrSoo=
=hZYm
-----END PGP SIGNATURE-----

pinheadmz's public key is on openpgp.org

@furszy furszy force-pushed the 2025_threadpool_http_server branch from 195a962 to f5eca8d Compare October 29, 2025 15:55
@furszy
Copy link
Member Author

furszy commented Oct 29, 2025

Oh, awesome extensive test and review @pinheadmz! you rock!

Copy link
Member

@pinheadmz pinheadmz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK f5eca8d

minor changes since last ack

Show Signature
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

ACK f5eca8d5252a68f0fbc8b5efec021c75744555b6
-----BEGIN PGP SIGNATURE-----

iQIzBAEBCAAdFiEE5hdzzW4BBA4vG9eM5+KYS2KJyToFAmkCWuYACgkQ5+KYS2KJ
yTpb9RAAgxNlDQlqkVfnIK2Xt8BQmRsiG+1KHQGJA2d3RHoxjFg2129fj47y5i+t
GlatlcsXEcibI2D0F22sKSzY1u0LWy4GYLI1d12JAIewA99n/lRr1ktDk3v64pp8
kldvYpd8UBs7DCHSJhPs4HbOPgwIILPASdSbQTb+6m48X5jg+cu+yMBuANVq3sbB
9I8rUlbUgRva5voy3EGRkXsGTuwcaCoLDNHnnjrqQkJMYTym47rMF/xTZJJ11isF
QrpzFu+P2tFy1oj0bGd4e5EhqNk++qfRCuw9sGLgLL6YEHzC/ihVH/L5NAxoeJX4
L0yX09BG5wDrbUQvZn4w1uaQz39Uor5mb8+tZyDUyRmO9MrG5AHomUtfdbiYLwSO
007bLD+WX4Hxode47xCdhUhqflXqbHD2mhkf5ESyUgGu3smSHSQQosuzIJiVmTn9
b2UJG6see/tckFvart6YLn1AIu9uCyUMmB+hZIcSasZv95oEHv1YB3E5dcKUmq0d
A1cUHIhNvU4i/hNy2xgijgSjDdpVQMFbLYUt9y4ZnzpJXFd7mnbpHVUVM1P+Onvp
ScAtgvosXfbd5PjnAQWsMWgSmVHUtSc4t9GPjGlRYaVpHFkEbqWpWeKrYqMkU3id
9YiFP9BueWNbNV7OBlB0LcfCpwO2WbvfJOW93/jxDovc0tgohbU=
=c8aD
-----END PGP SIGNATURE-----

pinheadmz's public key is on openpgp.org

Copy link
Contributor

@sedited sedited left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK f5eca8d

I have fuzzed the thread pool for some time again, and did not find any new issues. Also the previously observed memory leak during fuzzing was not observed anymore. The changes to the http workers look sane to me.

Can you run the commits through clang-format-diff.py? There are a bunch of formatting issues in the first two commits.

@furszy furszy force-pushed the 2025_threadpool_http_server branch from f5eca8d to 435e8b5 Compare October 30, 2025 01:21
@furszy
Copy link
Member Author

furszy commented Oct 30, 2025

Can you run the commits through clang-format-diff.py? There are a bunch of formatting issues in the first two commits.

Pushed.

Copy link
Contributor

@l0rinc l0rinc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have started reviewing this PR but have only finished the first commit (e1eb4cd).

The depth of tests gives me hope that this transition will be smooth, the tests cover most of the functionality, even a few corner cases I haven't thought of!

It seemed, however, that I had more to say about that than anticipated. I didn't even get to reviewing the threadpool properly, just most of the tests.

I know receiving this amount of feedback can be daunting, but we both want this to succeed. I have spent a lot of time meticulously going through the details. I hope you will take it as I meant it: to make absolutely sure this won't cause any problems and that our test suite is rock solid.
I will continue the review, but wanted to make sure you're aware of the progress and thought we can synchronize more often this way (pun intended).

In general I think adding a threadpool can untangle complicated code as such, but we have to find a balance between IO and CPU bound tasks. I found that oversubscription is usually a smaller problem, so we can likely solve the IO/CPU contention problem by creating dedicated ThreadPools for each major task (http, script verification, input fetcher, compaction, etc). This way it won't be a general resource guardian (which can be a ThreadPool's main purpose), just a tool to avoid the overhead of starting/stopping threads.

As hinted in the original thread, I find the current structure to be harder to follow, I would appreciate if you would consider doing the extraction in smaller steps:

  • first step would be to use the new ThreadPool's structure, but extract the old logic into it;
  • add the tests (unit and fuzz, no need to split it) against the old impl in a separate commit;
  • in a last step swap it out with the new logic, keeping the same structure and tests.

This way we could debug and understand the old code before we jump into the new one - and the tests would guide us in guaranteeing that the behavior stayed basically the same.
I understand that's extra work, but I'm of course willing to help in whatever you need to be able to do a less risky transition.

I glanced quickly to the actual ThreadPool implementation, looks okay, but I want to investigate as part of my next wave of reviews why we need so much locking here and why we're relying on old primitives here instead of the C++20 concurrency tools (such as latches and barriers) and whether we can create and destroy the pool via RAII instead of manual start/stops.

Note that I have done an IBD before and after this change to see if everything was still working and I didn't see any regression!

here are all the changes I did locally while reviewing the change
diff --git a/src/test/threadpool_tests.cpp b/src/test/threadpool_tests.cpp
index e8200533cd..052784db37 100644
--- a/src/test/threadpool_tests.cpp
+++ b/src/test/threadpool_tests.cpp
@@ -2,270 +2,208 @@
 // Distributed under the MIT software license, see the accompanying
 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 
+#include <common/system.h>
+#include <test/util/setup_common.h>
 #include <util/string.h>
 #include <util/threadpool.h>
+#include <util/time.h>
 
 #include <boost/test/unit_test.hpp>
 
-BOOST_AUTO_TEST_SUITE(threadpool_tests)
+#include <latch>
+#include <semaphore>
 
-constexpr auto TIMEOUT_SECS = std::chrono::seconds(120);
+using namespace std::chrono;
+constexpr auto TIMEOUT = seconds(120);
 
-template <typename T>
-void WaitFor(const std::vector<std::future<T>>& futures, const std::string& context)
+void WaitFor(std::span<const std::future<void>> futures)
 {
-    for (size_t i = 0; i < futures.size(); ++i) {
-        if (futures[i].wait_for(TIMEOUT_SECS) != std::future_status::ready) {
-            throw std::runtime_error("Timeout waiting for: " + context + ", task index " + util::ToString(i));
-        }
+    for (const auto& f : futures) {
+        BOOST_REQUIRE(f.wait_for(TIMEOUT) == std::future_status::ready);
     }
 }
 
 // Block a number of worker threads by submitting tasks that wait on `blocker_future`.
 // Returns the futures of the blocking tasks, ensuring all have started and are waiting.
-std::vector<std::future<void>> BlockWorkers(ThreadPool& threadPool, std::shared_future<void>& blocker_future, int num_of_threads_to_block, const std::string& context)
+std::vector<std::future<void>> BlockWorkers(ThreadPool& threadPool, std::counting_semaphore<>& release_sem, size_t num_of_threads_to_block)
 {
-    // Per-thread ready promises to ensure all workers are actually blocked
-    std::vector<std::promise<void>> ready_promises(num_of_threads_to_block);
-    std::vector<std::future<void>> ready_futures;
-    ready_futures.reserve(num_of_threads_to_block);
-    for (auto& p : ready_promises) ready_futures.emplace_back(p.get_future());
-
-    // Fill all workers with blocking tasks
-    std::vector<std::future<void>> blocking_tasks;
-    for (int i = 0; i < num_of_threads_to_block; i++) {
-        std::promise<void>& ready = ready_promises[i];
-        blocking_tasks.emplace_back(threadPool.Submit([blocker_future, &ready]() {
-            ready.set_value();
-            blocker_future.wait();
-        }));
-    }
+    assert(threadPool.WorkersCount() >= num_of_threads_to_block);
+    std::latch ready{std::ptrdiff_t(num_of_threads_to_block)};
 
-    // Wait until all threads are actually blocked
-    WaitFor(ready_futures, context);
+    std::vector<std::future<void>> blocking_tasks(num_of_threads_to_block);
+    for (auto& f : blocking_tasks) f = threadPool.Submit([&] {
+        ready.count_down();
+        release_sem.acquire();
+    });
+
+    ready.wait();
     return blocking_tasks;
 }
 
-BOOST_AUTO_TEST_CASE(threadpool_basic)
+BOOST_FIXTURE_TEST_SUITE(threadpool_tests, BasicTestingSetup)
+
+const size_t NUM_WORKERS_DEFAULT{size_t(GetNumCores()) + 1}; // we need to make sure there's *some* contention
+
+BOOST_AUTO_TEST_CASE(submit_to_non_started_pool_throws)
 {
-    // Test Cases
-    // 0) Submit task to a non-started pool.
-    // 1) Submit tasks and verify completion.
-    // 2) Maintain all threads busy except one.
-    // 3) Wait for work to finish.
-    // 4) Wait for result object.
-    // 5) The task throws an exception, catch must be done in the consumer side.
-    // 6) Busy workers, help them by processing tasks from outside.
-    // 7) Recursive submission of tasks.
-    // 8) Submit task when all threads are busy, stop pool and verify the task gets executed.
-
-    const int NUM_WORKERS_DEFAULT = 3;
-    const std::string POOL_NAME = "test";
-
-    // Test case 0, submit task to a non-started pool
-    {
-        ThreadPool threadPool(POOL_NAME);
-        bool err = false;
-        try {
-            threadPool.Submit([]() { return false; });
-        } catch (const std::runtime_error&) {
-            err = true;
-        }
-        BOOST_CHECK(err);
+    ThreadPool threadPool{"not_started"};
+    BOOST_CHECK_EXCEPTION(threadPool.Submit([] { return 0; }), std::runtime_error, HasReason{"No active workers"});
+}
+
+BOOST_AUTO_TEST_CASE(submit_and_verify_completion)
+{
+    ThreadPool threadPool{"completion"};
+    threadPool.Start(NUM_WORKERS_DEFAULT);
+
+    const auto num_tasks{1 + m_rng.randrange<size_t>(50)};
+    std::atomic_size_t counter{0};
+
+    std::vector<std::future<void>> futures(num_tasks);
+    for (size_t i{0}; i < num_tasks; ++i) {
+        futures[i] = threadPool.Submit([&counter, i] { counter.fetch_add(i, std::memory_order_relaxed); });
     }
 
-    // Test case 1, submit tasks and verify completion.
-    {
-        int num_tasks = 50;
+    WaitFor(futures);
+    BOOST_CHECK_EQUAL(counter.load(std::memory_order_relaxed), (num_tasks - 1) * num_tasks / 2);
+    BOOST_CHECK_EQUAL(threadPool.WorkQueueSize(), 0);
+}
 
-        ThreadPool threadPool(POOL_NAME);
-        threadPool.Start(NUM_WORKERS_DEFAULT);
-        std::atomic<int> counter = 0;
+BOOST_AUTO_TEST_CASE(limited_free_workers_processes_all_task)
+{
+    ThreadPool threadPool{"block_counts"};
+    threadPool.Start(NUM_WORKERS_DEFAULT);
+    const auto num_tasks{1 + m_rng.randrange<size_t>(20)};
 
-        // Store futures to ensure completion before checking counter.
-        std::vector<std::future<void>> futures;
-        futures.reserve(num_tasks);
+    for (size_t free{1}; free < NUM_WORKERS_DEFAULT; ++free) {
+        BOOST_TEST_MESSAGE("Testing with " << free << " available workers");
+        std::counting_semaphore sem{0};
+        const auto blocking_tasks{BlockWorkers(threadPool, sem, free)};
 
-        for (int i = 1; i <= num_tasks; i++) {
-            futures.emplace_back(threadPool.Submit([&counter, i]() {
-                counter.fetch_add(i);
-            }));
-        }
+        size_t counter{0};
+        std::vector<std::future<void>> futures(num_tasks);
+        for (auto& f : futures) f = threadPool.Submit([&counter] { ++counter; });
 
-        // Wait for all tasks to finish
-        WaitFor(futures, /*context=*/"test1 task");
-        int expected_value = (num_tasks * (num_tasks + 1)) / 2; // Gauss sum.
-        BOOST_CHECK_EQUAL(counter.load(), expected_value);
+        WaitFor(futures);
         BOOST_CHECK_EQUAL(threadPool.WorkQueueSize(), 0);
-    }
 
-    // Test case 2, maintain all threads busy except one.
-    {
-        ThreadPool threadPool(POOL_NAME);
-        threadPool.Start(NUM_WORKERS_DEFAULT);
-        // Single blocking future for all threads
-        std::promise<void> blocker;
-        std::shared_future<void> blocker_future(blocker.get_future());
-        const auto& blocking_tasks = BlockWorkers(threadPool, blocker_future, NUM_WORKERS_DEFAULT - 1, /*context=*/"test2 blocking tasks enabled");
-
-        // Now execute tasks on the single available worker
-        // and check that all the tasks are executed.
-        int num_tasks = 15;
-        int counter = 0;
-
-        // Store futures to wait on
-        std::vector<std::future<void>> futures;
-        futures.reserve(num_tasks);
-        for (int i = 0; i < num_tasks; i++) {
-            futures.emplace_back(threadPool.Submit([&counter]() {
-                counter += 1;
-            }));
+        if (free == 1) {
+            BOOST_CHECK_EQUAL(counter, num_tasks);
+        } else {
+            BOOST_CHECK_LE(counter, num_tasks); // unsynchronized update from multiple threads doesn't guarantee consistency
         }
 
-        WaitFor(futures, /*context=*/"test2 tasks");
-        BOOST_CHECK_EQUAL(counter, num_tasks);
-
-        blocker.set_value();
-        WaitFor(blocking_tasks, /*context=*/"test2 blocking tasks disabled");
-        threadPool.Stop();
-        BOOST_CHECK_EQUAL(threadPool.WorkersCount(), 0);
+        sem.release(free);
+        WaitFor(blocking_tasks);
     }
 
-    // Test case 3, wait for work to finish.
-    {
-        ThreadPool threadPool(POOL_NAME);
-        threadPool.Start(NUM_WORKERS_DEFAULT);
-        std::atomic<bool> flag = false;
-        std::future<void> future = threadPool.Submit([&flag]() {
-            std::this_thread::sleep_for(std::chrono::milliseconds{200});
-            flag.store(true);
-        });
-        future.wait();
-        BOOST_CHECK(flag.load());
-    }
+    threadPool.Stop();
+}
 
-    // Test case 4, obtain result object.
-    {
-        ThreadPool threadPool(POOL_NAME);
-        threadPool.Start(NUM_WORKERS_DEFAULT);
-        std::future<bool> future_bool = threadPool.Submit([]() {
-            return true;
-        });
-        BOOST_CHECK(future_bool.get());
+BOOST_AUTO_TEST_CASE(future_wait_blocks_until_task_completes)
+{
+    ThreadPool threadPool{"wait_test"};
+    threadPool.Start(NUM_WORKERS_DEFAULT);
+    const auto num_tasks{1 + m_rng.randrange<size_t>(20)};
 
-        std::future<std::string> future_str = threadPool.Submit([]() {
-            return std::string("true");
-        });
-        std::string result = future_str.get();
-        BOOST_CHECK_EQUAL(result, "true");
+    const auto start{steady_clock::now()};
+
+    std::vector<std::future<void>> futures(num_tasks + 1);
+    for (size_t i{0}; i <= num_tasks; ++i) {
+        futures[i] = threadPool.Submit([i] { UninterruptibleSleep(milliseconds{i}); });
     }
+    WaitFor(futures);
 
-    // Test case 5, throw exception and catch it on the consumer side.
-    {
-        ThreadPool threadPool(POOL_NAME);
-        threadPool.Start(NUM_WORKERS_DEFAULT);
-
-        int ROUNDS = 5;
-        std::string err_msg{"something wrong happened"};
-        std::vector<std::future<void>> futures;
-        futures.reserve(ROUNDS);
-        for (int i = 0; i < ROUNDS; i++) {
-            futures.emplace_back(threadPool.Submit([err_msg, i]() {
-                throw std::runtime_error(err_msg + util::ToString(i));
-            }));
-        }
+    const size_t elapsed_ms{size_t(duration_cast<milliseconds>(steady_clock::now() - start).count())};
+    BOOST_CHECK(elapsed_ms >= num_tasks);
+}
 
-        for (int i = 0; i < ROUNDS; i++) {
-            try {
-                futures.at(i).get();
-                BOOST_FAIL("Expected exception not thrown");
-            } catch (const std::runtime_error& e) {
-                BOOST_CHECK_EQUAL(e.what(), err_msg + util::ToString(i));
-            }
-        }
-    }
+BOOST_AUTO_TEST_CASE(future_get_returns_task_result)
+{
+    ThreadPool threadPool{"result_test"};
+    threadPool.Start(NUM_WORKERS_DEFAULT);
 
-    // Test case 6, all workers are busy, help them by processing tasks from outside.
-    {
-        ThreadPool threadPool(POOL_NAME);
-        threadPool.Start(NUM_WORKERS_DEFAULT);
-
-        std::promise<void> blocker;
-        std::shared_future<void> blocker_future(blocker.get_future());
-        const auto& blocking_tasks = BlockWorkers(threadPool, blocker_future, NUM_WORKERS_DEFAULT, /*context=*/"test6 blocking tasks enabled");
-
-        // Now submit tasks and check that none of them are executed.
-        int num_tasks = 20;
-        std::atomic<int> counter = 0;
-        for (int i = 0; i < num_tasks; i++) {
-            threadPool.Submit([&counter]() {
-                counter.fetch_add(1);
-            });
-        }
-        std::this_thread::sleep_for(std::chrono::milliseconds{100});
-        BOOST_CHECK_EQUAL(threadPool.WorkQueueSize(), 20);
+    BOOST_CHECK_EQUAL(threadPool.Submit([] { return true; }).get(), true);
+    BOOST_CHECK_EQUAL(threadPool.Submit([] { return 42; }).get(), 42);
+    BOOST_CHECK_EQUAL(threadPool.Submit([] { return std::string{"true"}; }).get(), "true");
+}
 
-        // Now process manually
-        for (int i = 0; i < num_tasks; i++) {
-            threadPool.ProcessTask();
-        }
-        BOOST_CHECK_EQUAL(counter.load(), num_tasks);
-        BOOST_CHECK_EQUAL(threadPool.WorkQueueSize(), 0);
-        blocker.set_value();
-        threadPool.Stop();
-        WaitFor(blocking_tasks, "Failure waiting for test6 blocking task futures");
+BOOST_AUTO_TEST_CASE(task_exception_propagated_to_future)
+{
+    ThreadPool threadPool{"exception_test"};
+    threadPool.Start(NUM_WORKERS_DEFAULT);
+
+    const auto err{[&](size_t n) { return strprintf("error on thread #%s", n); }};
+
+    const auto num_tasks{1 + m_rng.randrange<size_t>(20)};
+    for (size_t i{0}; i < num_tasks; ++i) {
+        BOOST_CHECK_EXCEPTION(threadPool.Submit([&] { throw std::runtime_error(err(i)); }).get(), std::runtime_error, HasReason{err(i)});
     }
+}
+
+BOOST_AUTO_TEST_CASE(process_task_manually_when_workers_busy)
+{
+    ThreadPool threadPool{"manual_process"};
+    threadPool.Start(NUM_WORKERS_DEFAULT);
+    const auto num_tasks{1 + m_rng.randrange<size_t>(20)};
 
-    // Test case 7, recursive submission of tasks.
-    {
-        ThreadPool threadPool(POOL_NAME);
-        threadPool.Start(NUM_WORKERS_DEFAULT);
+    std::counting_semaphore sem{0};
+    const auto blocking_tasks{BlockWorkers(threadPool, sem, NUM_WORKERS_DEFAULT)};
 
-        std::promise<void> signal;
-        threadPool.Submit([&]() {
-            threadPool.Submit([&]() {
-                signal.set_value();
-            });
-        });
+    std::atomic_size_t counter{0};
+    std::vector<std::future<void>> futures(num_tasks);
+    for (auto& f : futures) f = threadPool.Submit([&counter] { counter.fetch_add(1, std::memory_order_relaxed); });
 
-        signal.get_future().wait();
-        threadPool.Stop();
-    }
+    UninterruptibleSleep(milliseconds{100});
+    BOOST_CHECK_EQUAL(threadPool.WorkQueueSize(), num_tasks);
 
-    // Test case 8, submit a task when all threads are busy and then stop the pool.
-    {
-        ThreadPool threadPool(POOL_NAME);
-        threadPool.Start(NUM_WORKERS_DEFAULT);
+    for (size_t i{0}; i < num_tasks; ++i) {
+        threadPool.ProcessTask();
+    }
 
-        std::promise<void> blocker;
-        std::shared_future<void> blocker_future(blocker.get_future());
-        const auto& blocking_tasks = BlockWorkers(threadPool, blocker_future, NUM_WORKERS_DEFAULT, /*context=*/"test8 blocking tasks enabled");
+    BOOST_CHECK_EQUAL(counter.load(), num_tasks);
+    BOOST_CHECK_EQUAL(threadPool.WorkQueueSize(), 0);
 
-        // Submit an extra task that should execute once a worker is free
-        std::future<bool> future = threadPool.Submit([]() { return true; });
+    sem.release(NUM_WORKERS_DEFAULT);
+    WaitFor(blocking_tasks);
+}
 
-        // At this point, all workers are blocked, and the extra task is queued
-        BOOST_CHECK_EQUAL(threadPool.WorkQueueSize(), 1);
+BOOST_AUTO_TEST_CASE(recursive_task_submission)
+{
+    ThreadPool threadPool{"recursive"};
+    threadPool.Start(NUM_WORKERS_DEFAULT);
 
-        // Wait a short moment before unblocking the threads to mimic a concurrent shutdown
-        std::thread thread_unblocker([&blocker]() {
-            std::this_thread::sleep_for(std::chrono::milliseconds{300});
-            blocker.set_value();
+    std::promise<void> signal;
+    threadPool.Submit([&threadPool, &signal] {
+        threadPool.Submit([&signal] {
+            signal.set_value();
         });
+    });
 
-        // Stop the pool while the workers are still blocked
-        threadPool.Stop();
+    signal.get_future().wait();
+}
 
-        // Expect the submitted task to complete
-        BOOST_CHECK(future.get());
-        thread_unblocker.join();
+BOOST_AUTO_TEST_CASE(stop_completes_queued_tasks_gracefully)
+{
+    ThreadPool threadPool{"graceful_stop"};
+    threadPool.Start(NUM_WORKERS_DEFAULT);
 
-        // Obviously all the previously blocking tasks should be completed at this point too
-        WaitFor(blocking_tasks, "Failure waiting for test8 blocking task futures");
+    std::counting_semaphore sem{0};
+    const auto blocking_tasks{BlockWorkers(threadPool, sem, NUM_WORKERS_DEFAULT)};
 
-        // Pool should be stopped and no workers remaining
-        BOOST_CHECK_EQUAL(threadPool.WorkersCount(), 0);
-    }
+    auto future{threadPool.Submit([] { return true; })};
+    BOOST_CHECK_EQUAL(threadPool.WorkQueueSize(), 1);
+
+    std::thread thread_unblocker{[&sem] {
+        std::this_thread::sleep_for(milliseconds{300});
+        sem.release(NUM_WORKERS_DEFAULT);
+    }};
+
+    threadPool.Stop();
+
+    BOOST_CHECK(future.get());
+    thread_unblocker.join();
+    WaitFor(blocking_tasks);
+    BOOST_CHECK_EQUAL(threadPool.WorkersCount(), 0);
 }
 
 BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/util/threadpool.h b/src/util/threadpool.h
index 5d9884086e..c89fda37c2 100644
--- a/src/util/threadpool.h
+++ b/src/util/threadpool.h
@@ -24,6 +24,8 @@
 #include <utility>
 #include <vector>
 
+#include <tinyformat.h>
+
 /**
  * @brief Fixed-size thread pool for running arbitrary tasks concurrently.
  *
@@ -62,16 +64,9 @@ private:
         for (;;) {
             std::packaged_task<void()> task;
             {
-                // Wait only if needed; avoid sleeping when a new task was submitted while we were processing another one.
-                if (!m_interrupt && m_work_queue.empty()) {
-                    // Block until the pool is interrupted or a task is available.
-                    m_cv.wait(wait_lock, [&]() EXCLUSIVE_LOCKS_REQUIRED(m_mutex) { return m_interrupt || !m_work_queue.empty(); });
-                }
-
-                // If stopped and no work left, exit worker
-                if (m_interrupt && m_work_queue.empty()) {
-                    return;
-                }
+                // Block until the pool is interrupted or a task is available.
+                m_cv.wait(wait_lock, [&]() EXCLUSIVE_LOCKS_REQUIRED(m_mutex) { return m_interrupt || !m_work_queue.empty(); });
+                if (m_interrupt && m_work_queue.empty()) return;
 
                 task = std::move(m_work_queue.front());
                 m_work_queue.pop();
@@ -101,17 +96,16 @@ public:
      *
      * Must be called from a controller (non-worker) thread.
      */
-    void Start(int num_workers) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
+    void Start(size_t num_workers) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
     {
         assert(num_workers > 0);
         LOCK(m_mutex);
         if (!m_workers.empty()) throw std::runtime_error("Thread pool already started");
         m_interrupt = false; // Reset
 
-        // Create workers
         m_workers.reserve(num_workers);
-        for (int i = 0; i < num_workers; i++) {
-            m_workers.emplace_back(&util::TraceThread, m_name + "_pool_" + util::ToString(i), [this] { WorkerThread(); });
+        for (size_t i{0}; i < num_workers; i++) {
+            m_workers.emplace_back(&util::TraceThread, strprintf("%s_pool_%d", m_name, i), [this] { WorkerThread(); });
         }
     }
 
@@ -179,12 +173,6 @@ public:
         task();
     }
 
-    void Interrupt() EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
-    {
-        WITH_LOCK(m_mutex, m_interrupt = true);
-        m_cv.notify_all();
-    }
-
     size_t WorkQueueSize() EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
     {
         return WITH_LOCK(m_mutex, return m_work_queue.size());


static void setup_threadpool_test()
{
// Disable logging entirely. It seems to cause memory leaks.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we investigate that?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is a known issue. The pcp fuzz test does it too for the same reason (in an undocumented manner). I only document it properly so we don't forget this exists. Feel free to investigate it in a separate issue/PR. I'm not planning to do it. It is not an issue of the code introduced in this PR.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

k, thanks, please resolve the comment

// Create workers
m_workers.reserve(num_workers);
for (int i = 0; i < num_workers; i++) {
m_workers.emplace_back(&util::TraceThread, m_name + "_pool_" + util::ToString(i), [this] { WorkerThread(); });
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: we could use strprintf in a few more places:

Suggested change
m_workers.emplace_back(&util::TraceThread, m_name + "_pool_" + util::ToString(i), [this] { WorkerThread(); });
m_workers.emplace_back(&util::TraceThread, strprintf("%s_pool_%d", m_name, i), [this] { WorkerThread(); });

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure about including extra dependencies on a low-level class for tiny readability improvements. But I'm not really opposed to this one, so done as suggested.

void Stop() EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
{
// Notify workers and join them.
std::vector<std::thread> threads_to_join;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure this is necessarry

ThreadPool threadPool(POOL_NAME);
threadPool.Start(NUM_WORKERS_DEFAULT);

int ROUNDS = 5;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in other cases we called this num_tasks

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done as suggested.


int ROUNDS = 5;
std::string err_msg{"something wrong happened"};
std::vector<std::future<void>> futures;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we need a vector here of can we just consume whatever we just submitted?

BOOST_AUTO_TEST_CASE(task_exception_propagated_to_future)
{
    ThreadPool threadPool{"exception_test"};
    threadPool.Start(NUM_WORKERS_DEFAULT);

    const auto make_err{[&](size_t n) { return strprintf("error on thread #%s", n); }};

    const auto num_tasks{1 + m_rng.randrange<size_t>(20)};
    for (size_t i{0}; i < num_tasks; ++i) {
        BOOST_CHECK_EXCEPTION(threadPool.Submit([&] { throw std::runtime_error(make_err(i)); }).get(), std::runtime_error, HasReason{make_err(i)});
    }
}

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we need a vector here of can we just consume whatever we just submitted?

Consuming right away would wait for the task to be executed; we want to exercise some concurrency too.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we want to exercise some concurrency too

You're right, that's better indeed.
My suggestion updated to keep the vector

// Test 5, throw exceptions and catch it on the consumer side
BOOST_AUTO_TEST_CASE(task_exception_propagates_to_future)
{
    ThreadPool threadPool("exception_test");
    threadPool.Start(NUM_WORKERS_DEFAULT);

    const auto make_err{[&](size_t n) { return strprintf("error on thread #%s", n); }};

    const auto num_tasks{1 + m_rng.randrange<size_t>(20)};
    std::vector<std::future<void>> futures(num_tasks);
    for (size_t i{0}; i < num_tasks; ++i) {
        futures[i] = threadPool.Submit([&make_err, i] { throw std::runtime_error(make_err(i)); });
    }

    for (size_t i{0}; i < num_tasks; ++i) {
        BOOST_CHECK_EXCEPTION(futures[i].get(), std::runtime_error, HasReason{make_err(i)});
    }
}

}
}

// Test case 6, all workers are busy, help them by processing tasks from outside.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can split out the remaining 3 tests as well:

BOOST_AUTO_TEST_CASE(process_task_manually_when_workers_busy)
{
    ThreadPool threadPool{"manual_process"};
    threadPool.Start(NUM_WORKERS_DEFAULT);
    const auto num_tasks{1 + m_rng.randrange<size_t>(20)};

    std::counting_semaphore sem{0};
    const auto blocking_tasks{BlockWorkers(threadPool, sem, NUM_WORKERS_DEFAULT)};

    std::atomic_size_t counter{0};
    std::vector<std::future<void>> futures(num_tasks);
    for (auto& f : futures) f = threadPool.Submit([&counter] { counter.fetch_add(1, std::memory_order_relaxed); });

    UninterruptibleSleep(milliseconds{100});
    BOOST_CHECK_EQUAL(threadPool.WorkQueueSize(), num_tasks);

    for (size_t i{0}; i < num_tasks; ++i) {
        threadPool.ProcessTask();
    }

    BOOST_CHECK_EQUAL(counter.load(), num_tasks);
    BOOST_CHECK_EQUAL(threadPool.WorkQueueSize(), 0);

    sem.release(NUM_WORKERS_DEFAULT);
    WaitFor(blocking_tasks);
}

BOOST_AUTO_TEST_CASE(recursive_task_submission)
{
    ThreadPool threadPool{"recursive"};
    threadPool.Start(NUM_WORKERS_DEFAULT);

    std::promise<void> signal;
    threadPool.Submit([&threadPool, &signal] {
        threadPool.Submit([&signal] {
            signal.set_value();
        });
    });

    signal.get_future().wait();
}

BOOST_AUTO_TEST_CASE(stop_completes_queued_tasks_gracefully)
{
    ThreadPool threadPool{"graceful_stop"};
    threadPool.Start(NUM_WORKERS_DEFAULT);

    std::counting_semaphore sem{0};
    const auto blocking_tasks{BlockWorkers(threadPool, sem, NUM_WORKERS_DEFAULT)};

    auto future{threadPool.Submit([] { return true; })};
    BOOST_CHECK_EQUAL(threadPool.WorkQueueSize(), 1);

    std::thread thread_unblocker{[&sem] {
        std::this_thread::sleep_for(milliseconds{300});
        sem.release(NUM_WORKERS_DEFAULT);
    }};

    threadPool.Stop();

    BOOST_CHECK(future.get());
    thread_unblocker.join();
    WaitFor(blocking_tasks);
    BOOST_CHECK_EQUAL(threadPool.WorkersCount(), 0);
}

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Splitted.

static const size_t MAX_HEADERS_SIZE = 8192;

/** HTTP request work item */
class HTTPWorkItem final : public HTTPClosure
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a way to do this final threadpool migration in smaller steps?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess you wrote this first and then answered yourself in your final comment; which is basically a long version of the PR's "Note 2" description.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not exactly sure what you mean by that - Note 2 does seem like a good idea to me and it's probably similar to what I meant. It would help the review process to gain more confidence in the implementation if we migrated away in smaller steps, documenting how the tests we add for the old implementation also pass when we switch over to the new implementation.

Copy link
Member Author

@furszy furszy Nov 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I imagine the problem is that you haven't compared the current http code with the ThreadPool code, which is pretty much the same but properly documented and test covered. That's one of the reasons behind the not modernization of the underlying sync mechanism in this PR, and why I added the "Note 2" paragraph as well as wrote #33689 (comment).

Look at the current WorkQueue:

void Run() EXCLUSIVE_LOCKS_REQUIRED(!cs)
    {
        while (true) {
            std::unique_ptr<WorkItem> i;
            {
                WAIT_LOCK(cs, lock);
                while (running && queue.empty())
                    cond.wait(lock);
                if (!running && queue.empty())
                    break;
                i = std::move(queue.front());
                queue.pop_front();
            }
            (*i)();
        }
    }

And this is the ThreadPool (stripping all comments)

void WorkerThread() EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
    {
        WAIT_LOCK(m_mutex, wait_lock);
        for (;;) {
            std::packaged_task<void()> task;
            {
                if (!m_interrupt && m_work_queue.empty()) {
                    m_cv.wait(wait_lock, [&]() EXCLUSIVE_LOCKS_REQUIRED(m_mutex) { return m_interrupt || !m_work_queue.empty(); });
                }

                if (m_interrupt && m_work_queue.empty()) return;
               
                task = std::move(m_work_queue.front());
                m_work_queue.pop();
            }

            REVERSE_LOCK(wait_lock, m_mutex);
            task();
        }
    }

In any case, since most reviewers seem ok to proceed with the current approach, I think it’s more productive to keep working on it rather than continue circling around this topic, even if it’s not to your taste.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a big change, other reviewers can just review the unified view if they don't want smaller commits, but I currently cannot view this in small steps, so I insist that we should split it into smaller changes. I want to help, that's why I'm spending so much time with the details, I think this is a really risky change, I want to make sure it's correct. Let me know how I can help.

@marcofleon
Copy link
Contributor

marcofleon commented Oct 30, 2025

I've been playing around with the fuzz test and wanted to update here, even if it's still a bit inconclusive.

I'm running into non-reproducible timeouts when using fork with libFuzzer. I'm overusing my cores by a lot (fork=25 plus the 3 workers each), and I'm not yet sure if these timeouts would happen eventually when using less cores.

I have "fixed" this by changing notify_one in Submit to notify_all, although I can't say I'm exactly sure why this works. It almost seems like some of the workers aren't being woken up at all when only one is being notified. Maybe the same one somehow ends up being reused over and over, so it gets stuck waiting? But then with notify_all all idle workers are woken up with every task, so the thread pool is able to handle the cpu overload more effectively.

edit: This should be reproducible in the sense that if you run with fork close to the number of total cores on your machine and set -timeout=30 you should get timeouts in less than an hour of fuzzing.

Copy link
Contributor

@Eunovo Eunovo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Concept ACK 435e8b5

The PR looks good already, but I think we can block users from calling Threadpool::Start() and Threadpool::Stop() inside Worker threads; We can use a thread local variable to identify worker threads and reject the operation.

* Creates and launches `num_workers` threads that begin executing tasks
* from the queue. If the pool is already started, throws.
*
* Must be called from a controller (non-worker) thread.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

e1eb4cd:

Can we enforce this rule using a thread-local variable?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i remember that in the past we had tons of issues with thread-local variables. They've been a pain in the ass on some platforms, and decided to not use them except for one case. Not sure if this is still the case, but if not, this needs to be updated:
https://github.com/bitcoin/bitcoin/blob/master/src/util/threadnames.cpp#L39

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's also our thread_local clang-tidy plugin: https://github.com/bitcoin/bitcoin/tree/master/contrib/devtools/bitcoin-tidy.

I don't see why we would need a thread local variable with a non-trivial desctructor to implement this.

i remember that in the past we had tons of issues with thread-local variables. They've been a pain in the ass on some platforms, and decided to not use them except for one case. Not sure if this is still the case, but if not, this needs to be updated:
https://github.com/bitcoin/bitcoin/blob/master/src/util/threadnames.cpp#L39

I think it would be fine in this case because the use is limited. A simple thread-local boolean and assertion should be enough.

I don't have a strong opinion here; I just think it would be better to programmatically enforce the rule that certain functions should not be called from Worker Threads.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we enforce this rule using a thread-local variable?

As m_workers is guarded, we could enforce it in a simple way:

for (const auto& worker : m_workers) assert(worker.get_id() != std::this_thread::get_id());

@furszy furszy force-pushed the 2025_threadpool_http_server branch from d504f81 to 57d9bbc Compare January 29, 2026 00:05
@furszy
Copy link
Member Author

furszy commented Jan 29, 2026

Updated per feedback. Thanks everyone!

Unit tests updated with most of l0rinc's feedback. And updated the fuzz test to accommodate to
#33689 (comment) which seems very deep. Thanks marcofleon for the thorough investigation!

Also, just to highlight the main change of the last push:

On master, I was able to crash the server by throwing an exception from the top-level handler,
but in this branch, the same scenario no longer causes a crash, which is great.
Yet, to make the fix and the scenario explicit, I separated it into its own standalone commit.
The diff to reproduce it on master is also in the commit description.

Copy link
Contributor

@Eunovo Eunovo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK 57d9bbc

Left some minor comments.

@furszy furszy force-pushed the 2025_threadpool_http_server branch from 57d9bbc to ad8fb89 Compare January 30, 2026 21:16
furszy and others added 3 commits January 30, 2026 16:17
Co-authored-by: furszy <matiasfurszyfer@protonmail.com>
Replace the HTTP server's WorkQueue implementation and single threads
handling code with ThreadPool for processing HTTP requests. The
ThreadPool class encapsulates all this functionality on a reusable
class, properly unit and fuzz tested (the previous code was not
unit nor fuzz tested at all).

This cleanly separates responsibilities:
The HTTP server now focuses solely on receiving and dispatching requests,
while ThreadPool handles concurrency, queuing, and execution.
It simplifies init, shutdown and requests tracking.

This also allows us to experiment with further performance improvements at
the task queuing and execution level, such as a lock-free structure, task
prioritization or any other performance improvement in the future, without
having to deal with HTTP code that lives on a different layer.
@furszy furszy force-pushed the 2025_threadpool_http_server branch from ad8fb89 to 38fd85c Compare January 30, 2026 21:17
@furszy
Copy link
Member Author

furszy commented Jan 30, 2026

Updated per feedback. Thanks Eunovo.

@Eunovo
Copy link
Contributor

Eunovo commented Feb 2, 2026

ReACK 38fd85c

Reviewed with git diff 57d9bbc 38fd85c

@DrahtBot DrahtBot requested a review from ismaelsadeeq February 2, 2026 13:07
Copy link
Contributor

@sedited sedited left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-ACK 38fd85c

Copy link
Member

@pinheadmz pinheadmz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK 38fd85c

Re-reviewed all commits since a lot has changed since last review. Built and tested on arm64/macos and x86/debian.

Tried breaking it with stuff like -rpcthreads=9000 (expect init failure).
Also tried -rpcthreads=1 with RPC-pummeling scripts.

I roughly rebased #32061 on this branch and tested. Conflicts were extremely minimal.

I'm excited to use this feature to parallelize other tasks in bitcoin!

Several questions below, mostly just about style. No blockers there. RFM 🚀


 /home/zip/bitcoin/build/bin/bitcoind -regtest -rpcthreads=1000
 ├─ b-scheduler
 ├─ b-http_pool_0
 ├─ b-http_pool_1
 ├─ b-http_pool_2
 ├─ b-http_pool_3
 ├─ b-http_pool_4
 ├─ b-http_pool_5
...
Show Signature
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

ACK 38fd85c676a072ebf256e806beda9d7533790baa
-----BEGIN PGP SIGNATURE-----

iQIzBAEBCAAdFiEE5hdzzW4BBA4vG9eM5+KYS2KJyToFAmmLdj0ACgkQ5+KYS2KJ
yTpkNQ//Z8464/u6+Zw6tfIBEtcNCWLi2m3pk2xnJE8q2HIzk2GT6NUzu5f6yRsV
fkB1AJqxwO9aKf+tmF85c+f6PoKhjyBDeA1nFa39ms8Madkn32W3su6fPcfqjeCy
ROS3T18QueM7MkH4qezCWZ4TkYYeZu/yEMQdfZzhLJF14DX/8HdL+/fanqyB0CHc
V8mckYkX9vszKmQz4HZqSSxL9RUvv/ipbLKSU7BgO+EOWHkLAHNr5V27UwySM/9s
uDDDQGDCsnQqtkajRGE+gg230Xq70Fwp12+japQ5yvpn17HjkkDnCsvoLK01BHAO
WHASMt6m+RSZGlIwv7WXd0vM2gqIAcrJwkS3VzoDlkVI0fLdcsyacPn2zKL0cOBg
j7OjaW8KV+MjS1KvRuJR0CAE5akOPTgO9aCi5Aly+LZyyLPoDoQOZYTGDq4TJB3n
REgN6LuvjBoctWQGYM3HTTMDTchQqd+WWTaF7aKoCM8VTsffN8d00c/Y4ADIQ4Fd
xRv6jC0QBw434Nb023h15OHNYVgMNr/xqulfGizZUzXOcrcfEuBNYTyK7zBi4njm
gjEmI2rEoIrCzrgRcwinAF0XpVMca9YyGao4bBtpYY5lmc+LeU7lz2ac1wk3kLGf
SXfHL6jqetA1QWSVuEZ7ZuFJJSxRRqwjuNOl0YtoJ1kHTH8tiSc=
=dFzb
-----END PGP SIGNATURE-----

pinheadmz's public key is on openpgp.org

req->WriteHeader("Connection", "close");
// TODO: Implement specific error formatting for the REST and JSON-RPC servers responses.
req->WriteReply(HTTP_INTERNAL_SERVER_ERROR, err_msg);
return false;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

45930a7

nit: HTTPRequestHandler is defined as returning a bool but I don't think we ever use its return value, can probably be void. No change needed at this time, I just noticed this code either returns a hard coded bool, or the value from some arbitrary function, whose type is not so easy to see on the same page.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, the first commit fixes the possible crash using the existing HTTPRequestHandler, which returns a bool. In the removal commit, when HTTPRequestHandler gets dropped, the bool return value is dropped as well.

self.log.exception(f"Called Process failed with stdout='{e.stdout}'; stderr='{e.stderr}';")
self.success = TestStatus.FAILED
except JSONRPCException as e:
self.log.exception(f"Failure during setup: error={e.error}, http_status={e.http_status}")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

6354b4f

This is good but could even be improved (doesn't have to be here). For example with the diff below and the suggested diff in the first commit message, you can actually get all the information logged out:

current:

test_framework.authproxy.JSONRPCException: non-JSON HTTP response with '500 Internal Server Error' from server (-342)

with diff below:

test_framework.authproxy.JSONRPCException: non-JSON HTTP response with '500 Internal Server Error' from server: error from json rpc handler (-342)

diff --git a/test/functional/test_framework/authproxy.py b/test/functional/test_framework/authproxy.py
index 9b2fc0f7f9..051423928d 100644
--- a/test/functional/test_framework/authproxy.py
+++ b/test/functional/test_framework/authproxy.py
@@ -195,7 +195,7 @@ class AuthServiceProxy():
         content_type = http_response.getheader('Content-Type')
         if content_type != 'application/json':
             raise JSONRPCException(
-                {'code': -342, 'message': 'non-JSON HTTP response with \'%i %s\' from server' % (http_response.status, http_response.reason)},
+                {'code': -342, 'message': 'non-JSON HTTP response with \'%i %s\' from server: %s' % (http_response.status, http_response.reason, http_response.read().decode())},
                 http_response.status)
 
         data = http_response.read()

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The commit message seems wrong, because Unexpected exception will also log all details that are available.

So this seems like the wrong fix. The correct fix would be to add any missing details to the exception string. Fixed in #34575

assert(num_workers > 0);
LOCK(m_mutex);
if (!m_workers.empty()) throw std::runtime_error("Thread pool already started");
m_interrupt = false; // Reset
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

c528dd5

What scenario would we stop and then re-start an instantiated worker pool?

Copy link
Member Author

@furszy furszy Feb 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

c528dd5

What scenario would we stop and then re-start an instantiated worker pool?

I was thinking about single-shot tasks that require a large number of threads, where keeping those threads alive for the entire lifetime of the software would be unnecessary overhead. E.g. RPC commands such as scanblocks, rescanblockchain, dumputxoset, etc.

Right now, the thread pool code is simple enough and not very configurable, but we will likely add more features and tuning options over time. Those settings will likely only be available during the node's initialization, so we need to construct the pool early with them (note: we really don't want to go back to the global ArgsManager dependency). And, at the same time, we don’t want to keep a large number of threads running when there's no work for them.

Comment on lines +154 to +155
template <class F> [[nodiscard]] EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
auto Submit(F&& fn)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

c528dd5

Just curious about your style choice here, I'd've written like this

template <class F>
[[nodiscard]] auto Submit(F&& fn) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm pretty sure I had it like that, and there was a suggestion to change it to the current form. Since it was merely an aesthetic change and there were so many comments, I didn't put much thought into it.

Comment on lines +76 to +77
BOOST_CHECK_EXCEPTION((void)threadPool.Submit([]{ return false; }), std::runtime_error, [&](const std::runtime_error& e) {
BOOST_CHECK_EQUAL(e.what(), "No active workers; cannot accept new tasks");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

c528dd5

Why not use HasReason()?

#include <test/util/setup_common.h>
...
    BOOST_CHECK_EXCEPTION(
        (void)threadPool.Submit([]{ return false; }),
        std::runtime_error,
        HasReason{"No active workers; cannot accept new tasks"
    });

Drahtbot should be complaining about this ;-)
see #34242 (comment)

and in task_exception_propagates_to_future and interrupt_blocks_new_submissions below

Copy link
Member Author

@furszy furszy Feb 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I answered this in a previous comment.

I'm happy using HasReason, but not adding a dependency to the entire unit test framework machinery (<test/util/setup_common.h>). The rationale is that the thread pool lives at a lower level and shouldn't get access to the chainstate, feerate, or any other higher-level concepts. It is also easier for anyone who wants to experiment with the code to be able to pull the thread pool alone into a separate project. This last sentence comes from experience.. it would have been so nice to have constructed the script interpreter and other primitives in this way, not so tied to the whole project machinery.. we would have found many issues and improvements way faster.

So, in short, I agree with using it. I just think we should first move the HasReason class to a general utility file, to beak the general framework dependency. It could be done in a quick follow-up, happy to do it or ACK it if someone wants to tackle it too.

LogWarning("Request rejected because http work queue depth exceeded, it can be increased with the -rpcworkqueue= setting");
item->req->WriteReply(HTTP_SERVICE_UNAVAILABLE, "Work queue depth exceeded");
}
[[maybe_unused]] auto _{g_threadpool_http.Submit(std::move(item))};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

38fd85c

Related to my comment on the first commit about how these workers dont return any thing. So now in the above try/catch wrapper the return values are removed which makes sense to me.

My guess is that for this use case of threadpool, we don't need to examine the return value of the future from the task, but other uses of threadpool will not discard it?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My guess is that for this use case of threadpool, we don't need to examine the return value of the future from the task, but other uses of threadpool will not discard it?

yeah, any parallelizable user single-shot locking command would wait for it to finish. The examples I have in my head are RPC-related like scanblocks, rescanblockchain, dumputxoset, etc. But we could surely find more just by looking at the REST server or the GUI.

@sedited sedited merged commit 4a05825 into bitcoin:master Feb 11, 2026
27 checks passed
@furszy furszy deleted the 2025_threadpool_http_server branch February 11, 2026 17:39
@fanquake
Copy link
Member

fanquake commented Feb 12, 2026

This seems to have introduced a bug: #34573.

@ismaelsadeeq
Copy link
Member

post merge ACK 38fd85c 🧑‍🏭

achow101 added a commit that referenced this pull request Feb 19, 2026
726b366 http: properly respond to HTTP request during shutdown (furszy)
59d24bd threadpool: make Submit return Expected instead of throwing (furszy)

Pull request description:

  Fixes #34573.

  As mentioned in #34573 (comment), the ThreadPool PR (#33689) revealed an existing issue.

  Before that PR, we were returning an incorrect error "Request rejected because http work queue depth exceeded" during shutdown for unhandled requests (we were not differentiating between "queue depth exceeded" and "server interrupted" errors). Now, with the ThreadPool inclusion, we return the proper error but we don't handle it properly.

  This PR improves exactly that. Handling the missing error and properly returning it to the user.

  The race can be reproduced as follows:

  1) The server receives an http request.
  2) Processing of the request is delayed, and shutdown is triggered in the meantime.
  3) During shutdown, the libevent callback is unregistered and the threadpool interrupted.
  4) The delayed request (step 2) resumes and tries to submit a task to the now-interrupted server.

  Reproduction test can be found #34577 (comment).

  Also, to prevent this kind of issue from happening again, this PR changes task submission
  to return the error as part of the function's return value using `util::Expected` instead of
  throwing the exception. Unlike exceptions, which require extra try-catch blocks and can be
  ignored, returning `Expected` forces callers to explicitly handle failures, and attributes
  like `[[nodiscard]]` allow us catch unhandled ones at compile time.

ACKs for top commit:
  achow101:
    ACK 726b366
  sedited:
    ACK 726b366
  pinheadmz:
    re-ACK 726b366
  andrewtoth:
    ACK 726b366
  hodlinator:
    re-ACK 726b366

Tree-SHA512: ef026e299adde1148c9fc575e7d937e957bf0ddedfc1cf081941b568736417c2eefcd8bc8c8aea795d7347040ed05da4371bddcdbda7d385e04bf4dc8d875780
sedited added a commit to sedited/rust-bitcoinkernel that referenced this pull request Feb 23, 2026
…9c7364ac567

d9c7364ac567 Merge bitcoin/bitcoin#34141: miniscript: Use Func and Expr when parsing keys, hashes, and locktimes
6c8d628b74aa Merge bitcoin-core/gui#931: Release: Update `src/qt/locale/bitcoin_en.xlf` after string freeze
fa194fca8e7b Merge bitcoin/bitcoin#34622: test: assert_debug_log timeouts follow-up
d907d65acd13 Merge bitcoin/bitcoin#29770: index: Check all necessary block data is available before starting to sync
ce6898f9a803 Merge bitcoin/bitcoin#34605: build: define CMAKE_COMPILE_WARNING_AS_ERROR as a cache option
a2fd558760ab Merge bitcoin/bitcoin#34572: cmake: Fix NetBSD-specific workaround for Boost
ef987683dc51 qt: Update src/qt/locale/bitcoin_en.xlf after string freeze
cb3473a6804f Merge bitcoin/bitcoin#34568: mining: Break compatibility with existing IPC mining clients
641a1954f7ae Merge bitcoin/bitcoin#34633: Revert "ci: Treat SHA1 LLVM signing key as warning"
3574905cecec Revert "ci: Treat SHA1 LLVM signing key as warning"
1a54886b639a Merge bitcoin/bitcoin#24539: Add a "tx output spender" index
fa4424fd98b6 test: Fixup assert_debug_log timeouts in feature_config_args.py
faed837f274a test: Add missing syncwithvalidationinterfacequeue
ee2065fdeaca Merge bitcoin/bitcoin#34165: coins: don't mutate main cache when connecting block
96bec216ec34 Merge bitcoin/bitcoin#34549: net: reduce log level for PCP/NAT-PMP NOT_AUTHORIZED failures
76de2f8e55f3 Merge bitcoin/bitcoin#34571: test: Fix intermittent issues in feature_assumevalid.py
c808dfbbdcea Merge bitcoin/bitcoin#34329: rpc,net: Add private broadcast RPCs
739f75c0980e Merge bitcoin/bitcoin#33512: coins: use dirty entry count for flush warnings and disk space checks
02c83fef8431 Merge bitcoin/bitcoin#34577: http: fix submission during shutdown race
0b96b9c600e0 Minimize mempool lock, sync txo spender index only when and if needed
d0998cbe348e Merge bitcoin/bitcoin#33199: fees: enable `CBlockPolicyEstimator` return sub 1 sat/vb fee rate estimates
37e449dcc72c Merge bitcoin/bitcoin#34512: rpc: add coinbase_tx field to getblock
097c18239b58 Merge bitcoin/bitcoin#34385: subprocess: Fix `-Wunused-private-field` when building with clang-cl on Windows
910bd1c964b6 Merge bitcoin/bitcoin#34582: rpc: Properly parse -rpcworkqueue/-rpcthreads
e0463b4e8c25 rpc: add coinbase_tx field to getblock
5a8a427610ed Merge bitcoin/bitcoin#32745: scripted-diff: Update DeriveType enum values to mention ranged derivations
3d82ec5bdd01 Add a "tx output spender" index
8ee24d764a28 Merge bitcoin/bitcoin#34604: guix: remove double export of `TZ`
4933d1fbbada Merge bitcoin/bitcoin#28792: build: Embedded ASMap [3/3]: Build binary dump header file
6d482b22de15 Merge bitcoin/bitcoin#32138: wallet, rpc: remove settxfee and paytxfee
726b3663cc8e http: properly respond to HTTP request during shutdown
241ad5853bca Merge bitcoin-core/gui#929: Use plurals where necessary
a849b7e1ff35 Merge bitcoin-core/gui#928: Replace three dots with ellipsis
9e4567b17a28 Merge bitcoin/bitcoin#34581: test: Set assert_debug_log timeout to 0
655b9d12ee17 Merge bitcoin/bitcoin#32950: validation: remove BLOCK_FAILED_CHILD
2706758dc38c Merge bitcoin/bitcoin#34349: util: Remove brittle and confusing sp::Popen(std::string)
59e10a5463dc Merge bitcoin/bitcoin#34023: Optimized SFL cluster linearization
59d24bd5dd2a threadpool: make Submit return Expected instead of throwing
fb3e1bf9c977 test: check LoadBlockIndex correctly recomputes invalidity flags
29740c06ac53 validation: remove BLOCK_FAILED_MASK
b5b2956bda32 validation: reset BLOCK_FAILED_CHILD to BLOCK_FAILED_VALID when loading from disk
37bc20785278 validation: stop using BLOCK_FAILED_CHILD
120c631e1689 refactor: use clearer variables in InvalidateBlock()
fa4cb96bdec2 test: Set assert_debug_log timeout to 0
c2fcf2506973 clusterlin: inline GetReachable into Deactivate (optimization)
d90f98ab4aaa clusterlin: inline UpdateChunk into (De)Activate (optimization)
b684f954bbfc clusterlin: unidirectional MakeTopological initially (optimization)
1daa600c1ca8 clusterlin: track suboptimal chunks (optimization)
63b06d5523f1 clusterlin: keep track of active children (optimization)
ae16485aa94d clusterlin: special-case self-merges (optimization)
3221f1a074e7 clusterlin: make MergeSequence take SetIdx (simplification)
7194de3f7c53 clusterlin: precompute reachable sets (optimization)
6f898dbb8bfa clusterlin: simplify PickMergeCandidate (optimization)
dcf458ffb99c clusterlin: split up OptimizeStep (refactor)
cbd684a4713d clusterlin: abstract out functions from MergeStep (refactor)
b75574a6531e clusterlin: improve TxData::dep_top_idx type (optimization)
73cbd15d4572 clusterlin: get rid of DepData (optimization)
7c6f63a8a9dc clusterlin: pool SetInfos (preparation)
20e2f3e96df3 scripted-diff: rename _rep -> _idx in SFL
268fcb6a53ec clusterlin: add more Assumes and sanity checks (tests)
d69c9f56ea96 clusterlin: count chunk deps without loop (optimization)
f66fa69ce008 clusterlin: split tx/chunk dep counting (preparation)
900e45977889 clusterlin: avoid depgraph argument in SanityCheck (cleanup)
666b37970f15 clusterlin: fix type to count dependencies
a7c29df0e5ac Merge bitcoin/bitcoin#34552: fees: refactor: separate feerate format from fee estimate mode
231dd04b8dcb build: define CMAKE_COMPILE_WARNING_AS_ERROR as a cache option
fa48d421636c test: Stricter unit test
fa626bd14341 util: Remove brittle and confusing sp::Popen(std::string)
fd06157d1465 test: Add coverage for restarted node without any block sync
3d7ab7ecb7df rpc, test: Address feedback from #29668
312919c9dd5d test: Indices can not start based on block data without undo data
a9a3b29dd687 index: Check availability of undo data for indices
c8c9c1e61759 Merge bitcoin/bitcoin#34383: ci: remove commit count limit from `test-each-commit` and fail fast
62e378584e77 guix: don't export TZ twice
badcf1c68dbf guix: fix typo in guix-codesign
8a050b9cb68a Merge bitcoin/bitcoin#34575: test: Avoid empty errmsg in JSONRPCException
746d8cddc191 qt: Use plurals where necessary
fa5672dcafa1 refactor: [gui] Use SettingTo<int64_t> over deprecated SettingToInt
35e6444fdc40 Merge bitcoin/bitcoin#34570: doc: update Windows MSVC build guide to utilize winget to install build requirements
d159b103987f doc: update Windows MSVC build guide to utilize WinGet to install apps
afea2af13913 net: reduce log level for PCP/NAT-PMP NOT_AUTHORIZED failures
fac3ecaf69d6 rpc: Properly parse -rpcworkqueue/-rpcthreads
faee36f63b5f util: Add SettingTo<Int>() and GetArg<Int>()
6df4a045f797 qt: Replace three dots with ellipsis
211111b8048d test: Avoid empty errmsg in JSONRPCException
b65ff0e5a1fd Merge bitcoin/bitcoin#34548: ci: Add and use ci-windows-cross.py helper
03e5f063b5c0 Merge bitcoin/bitcoin#34559: ci: split vcpkg tools cache into restore/save
84e826ddc1cf Merge bitcoin/bitcoin#34511: test: fully reset the state of CConnman in tests
309c51d89dfc Merge bitcoin/bitcoin#34546: kernel: Avoid duplicating symbols in the kernel library
24f93c9af7f6 release note
331a5279d277 wallet, rpc:remove settxfee and paytxfee
eafd530d2032 kernel: avoid potential duplicate object in shared library/binary
24c3b4701003 build: add kernel-specific warnings
cae6d895f8a8 fuzz: add target for CoinsViewOverlay
86eda88c8e48 fuzz: move backend mutating block to end of coins_view
89824fb27b22 fuzz: pass coins_view_cache to TestCoinsView in coins_view
73e99a596655 coins: don't mutate main cache when connecting block
67c0d1798e61 coins: introduce CoinsViewOverlay
69b01af0eb90 coins: add PeekCoin()
f700609e8ada doc: Release notes for mining IPC interface bump
79c934b51cdc cmake: Fix NetBSD-specific workaround for Boost
fa90d44a2283 test: Fix intermittent issues in feature_assumevalid.py
07b924775e4f Merge bitcoin/bitcoin#34427: lint: Flatten lint image entry points
9453c153612a ipc mining: break compatibility with existing clients (version bump)
70de5cc2d205 ipc mining: pass missing context to BlockTemplate methods (incompatible schema change)
2278f017afad ipc mining: remove deprecated methods (incompatible schema change)
c6638fa7c5e9 ipc mining: provide default option values (incompatible schema change)
a4603ac77412 ipc mining: declare constants for default field values
ff995b50cf9e ipc test: add workaround to block_reserved_weight exception test
b970cdf20fce test framework: expand expected_stderr, expected_ret_code options
df53a3e5ec87 rpc refactor: stop using deprecated getCoinbaseCommitment method
0b4cd08fcd22 Merge bitcoin/bitcoin#33965: mining: fix -blockreservedweight shadows IPC option
2a1d0db7994e doc: Mention private broadcast RPCs in release notes
c3378be10b0a test: Cover abortprivatebroadcast in p2p_private_broadcast
557260ca14ac rpc: Add abortprivatebroadcast
15dff452eb61 test: Cover getprivatebroadcastinfo in p2p_private_broadcast
996f20c18af0 rpc: Add getprivatebroadcastinfo
5e64982541f3 net: Add PrivateBroadcast::GetBroadcastInfo
55c49ff8f4b1 Merge bitcoin/bitcoin#34143: build: Prevent system header fallback and include path pollution
c134b1a4bc35 Merge bitcoin/bitcoin#34257: txgraph: deterministic optimal transaction order
4a05825a3f39 Merge bitcoin/bitcoin#33689: http: replace WorkQueue and single threads handling for ThreadPool
c1355493e2c2 refactor: fees: split fee rate format from fee estimate mode
c413cf12c5c6 ci: Split vcpkg tools cache into restore/save
337fef9f2f68 Merge bitcoin/bitcoin#34554: build: avoid exporting secp256k1 symbols
922ebf96ed66 refactor: move-only: move `FeeEstimateMode` enum to `util/fees.h`
cb1798000c25 Merge bitcoin/bitcoin#33861: build: Bump VS minimum supported version to 18.3
7640863a0fbe Merge bitcoin/bitcoin#34555: doc: archive release notes for v29.3
d29bc5e6dd71 doc: archive release notes for v29.3
fd625d84ae9e Merge bitcoin/bitcoin#34539: test: Fixup TODO comment in feature_dbcrash.py; remove unnecessary sleep
6777314310bc Merge bitcoin/bitcoin#34551: ci: Extend diff context for clang-format
452c743951fa refactor: Remove workaround for resolved MSVC bug
7164a0cab650 build: Bump VS minimum supported version to 18.3
2ccfdb582b64 build: avoid exporting secp256k1 symbols
fa8c89511d83 Fixup TODO comment in feature_dbcrash.py; remove unnecessary sleep
f8d2f30bf37d ci: Extend diff context for clang-format
91a8e9b549e9 Merge bitcoin-core/gui#807: refactor: interfaces, make 'createTransaction' less error-prone
573bb542be80 net: Store recipient node address in private broadcast
fa13b13239e5 ci: [refactor] Use pathlib over os.path
fa2719ab1ba2 ci: [refactor] Move run_unit_tests to ci-windows-cross.py
fa99ba5f14d4 ci: Set PREVIOUS_RELEASES_DIR env var in ci-windows-cross.py
fa4a1cab6c17 ci: Move run_functional_tests into ci-windows-cross.py
1111108685ec ci: [refactor] Move pyzmq install and get_previous_releases into ci-windows-cross.py
fac9c7bd6635 ci: [refactor] Move config.ini rewrite to ci-windows-cross.py
faf738946668 ci: Move check_manifests step to ci-windows-cross.py
fa674d55df57 ci: [refactor] Move print_version step into ci-windows-cross.py helper
6f113cb1847c txgraph: use fallback order to sort chunks (feature)
0a3351947e73 txgraph: use fallback order when linearizing (feature)
fba004a3df02 txgraph: pass fallback_order to TxGraph (preparation)
941c432a4637 txgraph test: subclass TxGraph::Ref like mempool does (preparation)
39d0052cbf47 clusterlin: make optimal linearizations deterministic (feature)
8bfbba32077c txgraph: sort distinct-cluster chunks by equal-feerate-prefix size (feature)
e0bc73ba9270 clusterlin: sort tx in chunk by feerate and size (feature)
6c1bcb2c7c1a txgraph: clear cluster's chunk index in ~Ref (preparation)
7427c7d09830 txgraph: update chunk index on Compact (preparation)
3ddafceb9afd txgraph: initialize Ref in AddTransaction (preparation)
64294c89094d Merge bitcoin/bitcoin#34500: ci: Print verbose Windows CI build failure
5f6bfa3649c3 Merge bitcoin/bitcoin#34057: test: add tests for cluster chunks
6ca7782db9b4 Merge bitcoin/bitcoin#34523: doc: Clarify why performance-move-const-arg.CheckTriviallyCopyableMove=false
44afed4cd970 Merge bitcoin/bitcoin#34524: refactor: [rpc] Remove confusing and brittle integral casts (take 2)
3764746404a8 Merge bitcoin/bitcoin#34241: test: Check that interrupt results in EXIT_SUCCESS
18f11695c755 validation: don't update BLOCK_FAILED_VALID to BLOCK_FAILED_CHILD in InvalidateBlock
acefdce08311 Merge bitcoin/bitcoin#34469: consensus/test/doc: cover errors in `CheckTxInputs` with unit tests
7e5e0b20ea3e Merge bitcoin/bitcoin#32773: cmake: Create subdirectories in build tree in advance
fa90277d22e1 ci: Use ubuntu-slim for [meta] runners
fa9627af9f89 ci: Rely on cmake --preset toolchain file
fa3f89acaa7a ci: Add check_manifests to ci-windows.py
1111079a16b9 ci: Add run_tests step to ci-windows.py
6d625af2831b Merge bitcoin/bitcoin#32621: contrib: utxo_to_sqlite.py: add option to store txid/spk as BLOBs
afb1bc120ecc validation: Use dirty entry count in flush warnings and disk space checks
b413491a1cdd coins: Keep track of number of dirty entries in `CCoinsViewCache`
7e52b1b945c4 fuzz: call `EmplaceCoinInternalDANGER` as well in `SimulationTest`
8f0e1f6540be Merge bitcoin/bitcoin#34465: refactor: separate log generation from log handling
b2805eec35ce Merge bitcoin/bitcoin#34528: test: Fix intermittent failure in `feature_assumevalid.py` by ensuring invalid block was processed before checking debug.log
72030efd4b83 Merge bitcoin/bitcoin#34525: Release: Prepare "Open Transifex translations for v31.0" step
fe0b1513a7c5 test: add a test for txgraph staging
ef253a9d3d16 test: add block builder tests for txgraph
4a1ac31e97c2 test: add a chunk test for txgraph
b623fab1ba87 mining: enforce minimum reserved weight for IPC
d3e49528d479 mining: fix -blockreservedweight shadows IPC option
418b7995ddfb test: have mining template helpers return None
54bd49c7e3c7 Merge bitcoin/bitcoin#34452: test: split interface_ipc.py
3b39a8aeb4c6 Merge bitcoin/bitcoin#34483: refactor: Use SpanReader over DataStream
6f68e0c8b760 Merge bitcoin/bitcoin#34181: refactor: [p2p] Make ProcessMessage private again, Use references when non-null
4c0d4f6f93f3 refactor: interfaces, make 'createTransaction' less error-prone
e2c3ec9bf412 refactor: move CreatedTransactionResult to types.h
45372175c35b gui: remove AmountWithFeeExceedsBalance error special case
d88997b809db Merge bitcoin/bitcoin#34299: wallet: remove PreSelectedInputs and re-activate "AmountWithFeeExceedsBalance" error
b73a62f667d0 test: Ensure invalid block was processed before checking debug.log
633d1831199a test: misc interface_ipc_mining.py improvements
52ccd9215e67 test: split interface_ipc_mining.py into subtests
4e49fa2a6884 test: add interface_ipc_mining.py
01a1ae889e5a test: move IPC helpers to ipc_util.py
28160c1e3dc1 Merge bitcoin/bitcoin#34421: ci: add Chimera Linux LTO config
576f89202798 qt: Update the `src/qt/locale/bitcoin_en.xlf` translation source file
4b9f5beafe9e Update Transifex slug for 31.x
46e1288df2b4 Merge bitcoin/bitcoin#34498: iwyu: Fix patch to prefer `<cstdint>`
fa6801366d76 refactor: [rpc] Remove confusing and brittle integral casts (take 2)
d79249d2799e ci: add chimera Linux LTO CI job
48161f6a0503 wallet: introduce "tx amount exceeds balance when fees are included" error
b7fa609ed175 wallet: remove PreSelectedInputs
7819da2c1643 walllet: use CoinsResult instead of PreSelectedInputs
0cd309c75e58 Merge bitcoin/bitcoin#34492: ci: Drop valgrind fuzz from GHA matrix
fa561682ce40 ci: [refactor] Add .github/ci-windows.py prepare_tests step
fa3e607c6dfb ci: Print verbose Windows CI build failure
4444808dd3a7 ci: [refactor] Add .github/ci-windows.py build step
fabdd4e82342 ci: Refactor Windows CI into script
fa88ac3f4f9b doc: Clarify why performance-move-const-arg.CheckTriviallyCopyableMove=false
fa0677d13119 refactor: Use SpanReader over DataStream
e5474079f179 wallet: introduce GetAppropriateTotal() in CoinsResult
d8ea921d0140 wallet: correctly reserve in CoinsResult::All()
7072d825e39d wallet: ensure COutput added in set are unique
fefa3be782ea wallet: fix, make 'total_effective_amount' optional actually optional
9ec1ae0e98c0 Merge bitcoin/bitcoin#34437: rpc: `uptime` should begin on application start
d692e0722813 Merge bitcoin/bitcoin#32894: FUZZ: Test that BnB finds best solution
28d860788286 Merge bitcoin/bitcoin#34504: build: replace `WERROR` with `CMAKE_COMPILE_WARNING_AS_ERROR`
ad1940a006b6 Merge bitcoin/bitcoin#34517: drop my key from trusted-keys
322c4ec4422a build: replace WERROR with CMAKE_COMPILE_WARNING_AS_ERROR
65134c7e5f99 depends: Prefix include path for headers-only `systemtap` package
94a692b6aa09 cmake: Add missed `USDT::headers`
b5375c44ed16 depends: Prefix include path for headers-only `boost` package
d73378ffcca2 cmake: Add missed `Boost::headers`
eb97250421d3 Merge bitcoin/bitcoin#34496: build: don't pass on boost dependency to kernel consumers
9d7694729481 Merge bitcoin/bitcoin#34464: Change BlockRequestAllowed() to take ref (minor refactor)
8966352df3fc doc: add release notes
704a09fe7187 test: ensure fee estimator provide fee rate estimate < 1 s/vb
243e48cf4933 fees: delete unused dummy field
fc4fbda42af1 fees: bump fees file version
b54dedcc8563 fees: reduce `MIN_BUCKET_FEERATE` to 100
2cb7e99deee1 test: also reset CConnman::m_private_broadcast in tests
41b9b76cce6a Merge bitcoin/bitcoin#34510: doc: fix broken bpftrace installation link
91b7c874e2b1 test: add ConnmanTestMsg convenience method Reset()
42ee31e80c99 doc: fix broken bpftrace installation link
54d039305823 FUZZ: Test that BnB finds best solution
eb510f8678ba ci: fail fast in test-each-commit script
04c4d710087b ci: remove commit count limit from `test-each-commit`
4ae00e9a7183 Merge bitcoin/bitcoin#32636: Split `CWallet::Create()` into `CreateNew` and `LoadExisting`
d4bc620ad8cf Merge bitcoin/bitcoin#34488: refactor: Small style and test fixups for bitcoinkernel
eb3dbbaf30fc Merge bitcoin/bitcoin#34493: contrib: Remove valgrind suppression for bug 472219
1e64aeaaecc2 Merge bitcoin/bitcoin#34295: test: Improve STRICTENC/DERSIG unit tests
b65a3d80093b iwyu: Fix patch to prefer `<cstdint>`
a50d0b6720f3 build: don't pass on boost dependency to kernel consumers
3532e242134e Merge bitcoin/bitcoin#32748: fees: fix noisy flushing log
fad9dd1a8891 test: kernel test fixups
fabb58d42dc2 test: Use clang-tidy named args for create_chainman
fa51594c5c0f refactor: Small style fixups in src/kernel/bitcoinkernel.cpp
fa33acec89f0 Revert "valgrind: add suppression for bug 472219"
24699fec8422 doc: Add initial asmap data documentation
bab085d282b1 ci: Use without embedded asmap build option in one ci job
e53934422a29 doc: Expand documentation on asmap feature and tooling
6244212a5532 init, net: Implement usage of binary-embedded asmap data
6202b50fb900 build: Generate ip_asn.dat.h during build process
634cd60dc8f6 build: Add embedded asmap data
faa4ab113cc9 ci: Drop valgrind fuzz from GHA matrix
02b5f6078d65 fees: make flushes log debug only
b58eebf1520f Merge bitcoin/bitcoin#34470: Bump leveldb subtree and remove UB workaround in CI
8bb277c12373 Merge bitcoin/bitcoin#34481: Update secp256k1 subtree to latest master
a4941132d311 Merge bitcoin/bitcoin#34461: ci: Print verbose build error message in test-each-commit
fad7d86d8d17 ci: Remove unused workaround after leveldb subtree bump
fabced56f650 Bump leveldb subtree
be35408c5ad7 Merge bitcoin/bitcoin#34474: ci: update ccache to improve hitrate
2f2952c5f2e3 Squashed 'src/leveldb/' changes from cad64b151d..ab6c84e6f3
7528d18796a2 ci: show more verbose ccache stats
47c9297172b0 Merge bitcoin/bitcoin#32420: mining, ipc: omit dummy extraNonce from coinbase
4b53cbd69220 test: Test for musig() in various miniscript expressions
ec0f47b15cb3 miniscript: Using Func and Expr when parsing keys, hashes, and locktimes
6fd780d4fbc4 descriptors: Increment key_exp_index in ParsePubkey(Inner)
b12281bd86e2 miniscript: Use a reference to key_exp_index in KeyParser
ce4c66eb7c5e test: Test that key expression indexes match key count
8c03318387f6 consensus/doc: explain `GetValueOut()` precondition
82ef92c8d006 consensus/doc: explain unreachable `bad-txns-fee-outofrange` check
fad3eb395645 refactor: Use SpanReader over DataStream
fa06e26764bb refactor: [qt] Use SpanReader to avoid two vector copies
fabd4d2e2e3c refactor: Avoid UB in SpanReader::ignore
37cc2a2d953c logging: use util/log.h where possible
8799eb74406e Merge bitcoin/bitcoin#33878: refactor, docs: Embedded ASMap [2/3]: Refactor asmap internals and add documentation
bb8e9e7c4c8d logging: Move message formatting to util/log.h
001f0a428e3a move-only: Move logging macros to util/log.h
94c0adf4e857 move-onlyish: Move logging levels to util/log.h
56d113cab034 move-only: move logging categories to logging/categories.h
f5233f7e9827 move-only: Move SourceLocation to util/log.h
fa20bc2ec275 refactor: Use empty() over eof() in the streams interface
fa879db73528 test: Read debug log for self-checking comment
d405713197f8 ci: use Alpine 3.23
1cee0e4cd3af ci: detect apk usage generally
1ed3de5a6d97 Update secp256k1 subtree to latest master
9d4c9b00356e Squashed 'src/secp256k1/' changes from 14e56970cb..57315a6985
9f8764c814ea Merge bitcoin/bitcoin#34475: ci: Treat SHA1 LLVM signing key as warning
3c8f5e48f710 ci: Treat SHA1 LLVM signing key as warning
5cb4cf9b428e Merge bitcoin/bitcoin#34036: contrib: update macOS SDK to Xcode-26.1.1-17B100
41034a032f0f Merge bitcoin/bitcoin#34396: fuzz: pull the latest FuzzedDataProvider.h from upstream
580e9eefe39f ci: bump CCACHE_MAXSIZE to 2G
ff095839285d Merge bitcoin/bitcoin#34432: test: Turn ElapseSteady into SteadyClockContext
81e67d9aa134 Merge bitcoin/bitcoin#34179: refactor: Enable transparent lookup for setBlockIndexCandidates to remove const_cast
ec70bead5e1e Merge bitcoin/bitcoin#34433: script: remove unused `SCRIPT_ERR_LAST`
08547ee1b06d Merge bitcoin/bitcoin#34443: validation: follow-up nits for lock-free `IsInitialBlockDownload()`
881ab4fc82fe support multiple block status checks in CheckBlockDataAvailability
232a2bce90a9 consensus/test: add out-of-range output unit tests for `CTransaction::GetValueOut`
aa87aae14f9e consensus/test: add `MoneyRange` unit tests for `CheckTxInputs`
8bb77f348ef3 Merge bitcoin/bitcoin#34455: ci, iwyu: Fix warnings in `src/univalue` and treat them as errors
1bf384222323 ci, iwyu: Fix warnings in `src/univalue` and treat them as errors
3d180d3c7f1f Merge bitcoin/bitcoin#34462: util: Drop *BSD headers in `batchpriority.cpp`
1eed88a3ec65 Merge bitcoin/bitcoin#34460: iwyu: Update mappings
101daa41636a Merge bitcoin/bitcoin#34338: ci, iwyu: Fix warnings in `src/zmq` and treat them as errors
dfb93646093f fuzz: pull latest FuzzedDataProvider.h from upstream
705705e5b195 Merge bitcoin/bitcoin#33701: test: add case where `TOTAL_TRIES` is exceeded yet solution remains
88f802983571 Merge bitcoin/bitcoin#34100: doc: Use multipath descriptors in descriptors.md and linked test
5ad94cf6b7eb Merge bitcoin/bitcoin#34381: script: return proper error for `CScriptNum` errors
4f85b05131bf Merge bitcoin/bitcoin#31713: miniscript refactor: Remove unique_ptr-indirection
1f8f7d477ae0 Change BlockRequestAllowed() to take ref
5d2707307e27 Merge bitcoin/bitcoin#34454: wallet: Rename `RecordType::DELETE` to `RecordType::DELETE_FLAG`
38fd85c676a0 http: replace WorkQueue and threads handling for ThreadPool
c323f882ed38 fuzz: add test case for threadpool
c528dd5f8ccc util: introduce general purpose thread pool
07af50f7896a util: Drop *BSD headers in `batchpriority.cpp`
4dfb6eef70d7 test: Add DERSIG tests to script_tests
884978f3894a test: Fix a STRICTENC test in script_tests
527e8ca7b545 test: Remove outdated comment in script_tests
516be10bb56d wallet: Rename `RecordType::DELETE` to `RecordType::DELETE_FLAG`
bbbb78a4f28f ci: Print verbose build error message in test-each-commit
2222dadabbbd ci: [refactor] Allow overwriting check option in run helper
9c839aa9e3db iwyu: Document mappings for libc symbols
91824646c58a iwyu: Add temporary mapping to work around upstream bug
37de7d19107c iwyu: Drop backported mapping
01651324f4e5 Merge bitcoin/bitcoin#34434: miniscript: correct and_v() properties
c7cf2b8f3aae Merge bitcoin/bitcoin#34445: fuzz: Use `__AFL_SHM_ID` for naming test directories
0d1d393877a7 Merge bitcoin/bitcoin#34429: test: Check that redundant verack message is ignored
23a2e3354edf Merge bitcoin/bitcoin#34453: ci: Always print low ccache hit rate notice
5401e673d561 Merge bitcoin/bitcoin#33604: p2p: Allow block downloads from peers without snapshot block after assumeutxo validation
6750744eb32d Merge bitcoin/bitcoin#34164: validation: add reusable coins view for ConnectBlock
4e4fa0199ee2 Merge bitcoin/bitcoin#33680: validation: do not wipe utxo cache for stats/scans/snapshots
fad2876ec330 ci: Always print low ccache hit rate notice
e67a676df9af fix: uptime RPC returns 0 on first call
a89e1618dd8c contrib: update macOS SDK to Xcode-26.1.1-17B100
57a778ed2526 depends: use -Xclang -fno-cxx-modules in macOS cross build
3e0fd0e4ddd8 refactor: rename will_reuse_cache to reallocate_cache
44b4ee194d3b validation: reuse same CCoinsViewCache for every ConnectBlock call
8fb6043231ea coins: introduce CCoinsViewCache::ResetGuard
041758f5eda5 coins: use hashBlock setter internally for CCoinsViewCache methods
8dd9200fc9b0 coins: add Reset on CCoinsViewCache
efcbf794484e ci, iwyu: Fix warnings in `src/zmq` and treat them as errors
d3e681bc0675 fuzz: Use `__AFL_SHM_ID` for naming test directories
f7e0c3d3d370 Merge bitcoin/bitcoin#34346: test: use IP_PORTRANGE_HIGH on FreeBSD for dynamic port allocation
eeb4d2814803 validation: follow-up nits for lock-free `IsInitialBlockDownload()`
1c2f164d3486 Merge bitcoin/bitcoin#34253: validation: cache tip recency for lock-free `IsInitialBlockDownload()`
8cdf1dcca0ce Merge bitcoin/bitcoin#34373: refactor: Remove remaining std::bind, check via clang-tidy
facb2aab26df test: Turn ElapseSteady into SteadyClockContext
6354b4fd7fe8 tests: log node JSON-RPC errors during test setup
45930a79412d http-server: guard against crashes from unhandled exceptions
a6cdc3ec9b56 Merge bitcoin/bitcoin#34303: test: addrman: test self-announcement time penalty handling
75ec9001ced9 Merge bitcoin/bitcoin#34207: coins/refactor: enforce `GetCoin()` returns only unspent coins
4fab35cf88c0 miniscript: correct and_v() properties
51abf7d15b1d script: remove unused SCRIPT_ERR_LAST
f2b8acc0edb6 remove glozow from trusted keys
cd1af852fa5d Merge bitcoin/bitcoin#34358: wallet: fix removeprunedfunds bug with conflicting transactions
2dd5e7bb38da Merge bitcoin/bitcoin#34409: test: use `ModuleNotFoundError` in `interface_ipc.py`
d3e8c459e776 Merge bitcoin/bitcoin#34417: log: Print warning about privacy-sensitive log info unconditionally
d9851f9a7c1c Merge bitcoin/bitcoin#33472: guix: documented shasum gathering command
a7460b992884 Merge bitcoin/bitcoin#34098: test: [move-only] Move lint functions into modules
8f9ad534a5a5 Merge bitcoin/bitcoin#34352: ci, iwyu: Fix warnings in `src/primitives` and treat them as errors
faba426b3b66 lint: Flatten lint image entry points
1111fff91c76 lint: Add missing --platform=linux to docker build command
feb74a9372be Merge bitcoin/bitcoin#34430: ci: mount git directory as writable in linter
fad042235bd6 refactor: Remove remaining std::bind, check via clang-tidy
c8abac994122 ci: mount .git dir rw
d9e651f9954f Merge bitcoin/bitcoin#33622: docs: add doc comment for SRD selection algorithm
cb128bcedb58 Merge bitcoin/bitcoin#34408: ci: remove gnu-getopt usage
6ae96ed60745 Merge bitcoin/bitcoin#34276: Remove empty caption from user interface (noui, gui)
fafdae46ff0b test: Check that redundant verack message is ignored
289d60f5ab76 Merge bitcoin/bitcoin#34161: refactor: avoid possible UB from `std::distance` for `nullptr` args
1d3243806da6 Merge bitcoin/bitcoin#34391: lint: upgrade lint scripts for worktrees
d931b54d138f Merge bitcoin/bitcoin#34412: Update secp256k1 subtree to latest master
3400db80401d doc: add missing param description to SRD
c0e6556e4f51 Merge bitcoin/bitcoin#34413: doc: Remove outdated -fdebug-prefix-map section in dev notes
9260b20ef175 Merge bitcoin/bitcoin#33962: refactor: replace manual promise with SyncWithValidationInterfaceQueue
ddae1b4efa56 ci: remove gnu-getopt usage
fa43897c1d14 doc: Fix LLM nits in net_processing.cpp
bbbba0fd4b87 scripted-diff: Use references when nullptr is not possible
fac541546604 refactor: Separate peer/maybe_peer in ProcessMessages and SendMessages
fac529188e0d refactor: Pass Peer& to ProcessMessage
fa376095a01c refactor: Pass CNode& to ProcessMessages and SendMessages
fada8380148c refactor: Make ProcessMessage private again
fa80cd3ceed4 test: [refactor] Avoid calling private ProcessMessage() function
d511adb664ed [miner] omit dummy extraNonce via IPC
bf3b5d6d069a test: clarify getCoinbaseRawTx() comparison
78df9003d634 [doc] Update comments on dummy extraNonces in tests
e770392084aa test: addrman: test self-announcement time penalty handling
27aeeff63014 Merge bitcoin/bitcoin#34328: rpc: make `uptime` monotonic across NTP jumps
5aeaa71c77ac lint: pass args from lint.py to cargo run in container
c17a2adb8dc0 lint: upgrade lint scripts for worktrees
fa9c92d7b639 log: Print warning about privacy-sensitive log info unconditionally
f970cb39fb64 Merge bitcoin/bitcoin#34267: net: avoid unconditional `privatebroadcast` logging (+ warn for debug logs)
8593d965191e Merge bitcoin/bitcoin#33067: test: refactor ValidWitnessMalleatedTx class to helper function
2fccbea3c8a0 Squashed 'src/secp256k1/' changes from d543c0d917..14e56970cb
26fbe10873e7 Update secp256k1 subtree to latest master
34a5ecadd720 Merge bitcoin/bitcoin#34397: doc: fix arg name hints so bugprone can validate them
fa2e1b85dd6b build: Remove outdated comment about -ffile-prefix-map
fa06cd4ba730 doc: Remove outdated -fdebug-prefix-map section in dev notes
ab649ce45945 guix: documented shasum gathering command
1cc58d3a0c65 Merge bitcoin/bitcoin#34281: build: Temporarily remove confusing and brittle `-fdebug-prefix-map`
905dfdee86d6 test: use ModuleNotFoundError in interface_ipc.py
2778eb46647a Merge bitcoin/bitcoin#34337: fuzz: Return chrono point from ConsumeTime(), Add ConsumeDuration()
d70fb8a5754f Merge bitcoin/bitcoin#34351: util: Remove `FilterHeaderHasher`
6472ba06c36a Merge bitcoin/bitcoin#34388: doc: Explain that low-effort pull requests may be closed
1f60ca360eb8 wallet: fix removeprunedfunds bug with conflicting transactions
5f66fca633c8 Merge bitcoin-core/gui#920: Set peer version and subversion to N/A when not available or detecting
02240a7698e3 Merge bitcoin/bitcoin#34390: test: allow overriding `tar` in `get_previous_releases.py`
7d9e1a810239 test: Verify peer usage after assumeutxo validation completes
3bd98b45084d refactor: use transparent comparator for setBlockIndexCandidates lookups
a73a3ec5532d doc: fix invalid arg name hints for bugprone validation
eeee3755f8c4 fuzz: Return chrono point from ConsumeTime(), Add ConsumeDuration()
1b36bf0c5d71 subprocess: Fix `-Wunused-private-field` for `Child` class on Windows
9f2b338bc018 subprocess: Fix `-Wunused-private-field` for `Popen` class on Windows
fa15a8d2d03b doc: Explain that low-effort pull requests may be closed
be2b48b9f3e5 test: allow overriding tar in get_previous_releases
db2effaca4cf scripted-diff: refactor: CWallet::Create() -> CreateNew()
27e021ebc0dd wallet: Correctly log stats for encrypted messages.
d8bec61be233 wallet: remove loading logic from CWallet::Create
f35acc893fb3 refactor: wallet: Factor out `WriteVersion()` from `PopulateWalletFromDB()`
e12ff8aca049 test: wallet: Split create and load
70dbc79b09ac wallet: Use CWallet::LoadExisting() for loading existing wallets.
ae66e0116462 wallet: Create separate function for wallet load
bc69070416c6 refactor: Wallet stats logging in its own function
a9d64cd49c69 wallet: Remove redundant birth time update
b4a49cc7275e wallet: Move argument parsing to before DB load
b15a94a618c5 refactor: Split out wallet argument loading
6f7b4323cb46 test: remove UNKNOWN_ERROR from script_tests
bd31a92d6716 script: use SCRIPT_ERR_SCRIPTNUM for CScriptNum errors
0ca4dcd78665 script: add SCRIPT_ERR_SCRIPTNUM error
2845f10a2be0 test: extend FreeBSD ephemeral port range fix to P2P listeners
3f5211cba8e7 test: remove child_one/child_two (w)txid variables
7cfe790820cf test: replace ValidWitnessMalleatedTx class with function
4fec726c4d35 refactor: Simplify Interpret asmap function
79e97d45c16f doc: Add more extensive docs to asmap implementation
cf4943fdcdd1 refactor: Use span instead of vector for data in util/asmap
385c34a05261 refactor: Unify asmap version calculation and naming
fa41fc6a1a7d refactor: Operate on bytes instead of bits in Asmap code
964c44cdcd6b test(miniscript): Prove avoidance of stack overflow
198bbaee4959 refactor(miniscript): Destroy nodes one full subs-vector at a time
50cab8570e8f refactor(miniscript): Remove NodeRef & MakeNodeRef()
15fb34de41cb refactor(miniscript): Remove superfluous unique_ptr-indirection
e55b23c170eb refactor(miniscript): Remove Node::subs mutability
c6f798b22247 refactor(miniscript): Make fields non-const & private
22e4115312b9 doc(miniscript): Remove mention of shared pointers
34bed0ed8c44 test: use IP_PORTRANGE_HIGH on FreeBSD for dynamic port allocation
ccf9172ab3bb util: Remove `FilterHeaderHasher`
fdc9fe2da6a8 ci, iwyu: Fix warnings in `src/primitives` and treat them as errors
477c5504e05f  coins: replace `std::distance` with unambiguous pointer subtraction
81675a781f3a test: use pre-generated chain
14f99cfe53f0 rpc: make `uptime` monotonic across NTP jumps
a9440b1595be util: add `TicksSeconds`
a02c4a82d88a refactor: Move -walletbroadcast setting init
411caf72815b wallet: refactor: PopulateWalletFromDB use switch statement.
a48e23f566cc refactor: wallet: move error handling to PopulateWalletFromDB()
faa5a9ebad15 fuzz: Use min option in ConsumeTime
0972785fd723 wallet: Delete unnecessary PopulateWalletFromDB() calls
f0a046094e4c scripted-diff: refactor: CWallet::LoadWallet->PopulateWalletFromDB
fad7bd9ba3ee noui: Remove always empty caption while formatting
fa8ebeb33232 refactor: [gui] Document that the title is always empty for node message
fafe71b743a0 refactor: Remove empty caption from ThreadSafeMessageBox
fa8d0088e76d refactor: Remove empty caption from ThreadSafeQuestion
fa37928536e0 build: Temporarily remove confusing and brittle -fdebug-prefix-map
b39291f4cde0 doc: fix `-logips` description to clarify that non-debug logs can also contain IP addresses
c7028d3368e9 init: log that additional logs may contain privacy-sensitive information
31b771a9425d net: move `privatebroadcast` logs to debug category
fa16b275fa94 test: Check that interrupt results in EXIT_SUCCESS
fab7c7f56c1d test: Split large init_stress_test into two smaller functions
fa0195499ca6 refactor: [gui] Use lambdas over std::bind
eeee1e341fa5 refactor: Remove trailing semicolon after ADD_SIGNALS_DECL_WRAPPER
557b41a38ccf validation: make `IsInitialBlockDownload()` lock-free
b9c0ab3b75a1 chain: add `CChain::IsTipRecent` helper
8d531c6210eb validation: invert `m_cached_finished_ibd` to `m_cached_is_ibd`
8be54e3b1967 test: cover IBD exit conditions
2ee7f9b25905 coins: assume `GetCoin` only returns unspent coins
eec551aaf1df fuzz: keep `coinscache_sim` backend free of spent coins
3e4155fcefe0 test: do not return spent coins from `CCoinsViewTest::GetCoin`
ee1e40f58000 txdb: assert `CCoinsViewDB::GetCoin` only returns unspent coins
fa578d9434fd lint: [move-only] Move python related lints to lint_py.rs
fa392c31e7b9 lint: [move-only] Move repo related lints to lint_repo_hygiene.rs
fab0cfa987c9 lint: [move-only] Move cpp related lints to lint_cpp.rs
fa3e48e3fd4d lint: [move-only] Move docs related lints to lint_docs.rs
fad09e77dbe5 lint: [move-only] Move text related lints to text_format.rs
faf40c2f848d lint: [move-only] Move util functions to util.rs
c6ca2b85a3e6 validation: do not wipe utxo cache for stats/scans/snapshots
7099e93d0a80 refactor: rename `FlushStateMode::ALWAYS` to `FORCE_FLUSH`
b261100e7169 [qt] Set peer version and subversion to N/A when not available or detecting
552bc82b1796 doc: Use multipath descriptors in descriptors.md and linked test
0067abe15329 p2p: Allow block downloads from peers without snapshot block after assumeutxo validation
e71c4df16851 refactor: replace manual promise with SyncWithValidationInterfaceQueue
b189a3455744 test: add case where `TOTAL_TRIES` is exceeded yet solution remains
76dae5d6911b cmake: Replace recursive globbing with explicit globbing in folders
a099655f2e1b scripted-diff: Update `DeriveType` enum values to mention ranged derivations
88d909257104 cmake: Create subdirectories in build tree in advance
7378f27b4fb5 test: run utxo-to-sqlite script test with spk/txid format option combinations
b30fca7498c9 contrib: utxo_to_sqlite.py: add options to store txid/spk as BLOBs

git-subtree-dir: libbitcoinkernel-sys/bitcoin
git-subtree-split: d9c7364ac56781a16c7224b2c7a6db9db97f17d8
sedited added a commit to sedited/rust-bitcoinkernel that referenced this pull request Feb 23, 2026
…9c7364ac567

d9c7364ac567 Merge bitcoin/bitcoin#34141: miniscript: Use Func and Expr when parsing keys, hashes, and locktimes
6c8d628b74aa Merge bitcoin-core/gui#931: Release: Update `src/qt/locale/bitcoin_en.xlf` after string freeze
fa194fca8e7b Merge bitcoin/bitcoin#34622: test: assert_debug_log timeouts follow-up
d907d65acd13 Merge bitcoin/bitcoin#29770: index: Check all necessary block data is available before starting to sync
ce6898f9a803 Merge bitcoin/bitcoin#34605: build: define CMAKE_COMPILE_WARNING_AS_ERROR as a cache option
a2fd558760ab Merge bitcoin/bitcoin#34572: cmake: Fix NetBSD-specific workaround for Boost
ef987683dc51 qt: Update src/qt/locale/bitcoin_en.xlf after string freeze
cb3473a6804f Merge bitcoin/bitcoin#34568: mining: Break compatibility with existing IPC mining clients
641a1954f7ae Merge bitcoin/bitcoin#34633: Revert "ci: Treat SHA1 LLVM signing key as warning"
3574905cecec Revert "ci: Treat SHA1 LLVM signing key as warning"
1a54886b639a Merge bitcoin/bitcoin#24539: Add a "tx output spender" index
fa4424fd98b6 test: Fixup assert_debug_log timeouts in feature_config_args.py
faed837f274a test: Add missing syncwithvalidationinterfacequeue
ee2065fdeaca Merge bitcoin/bitcoin#34165: coins: don't mutate main cache when connecting block
96bec216ec34 Merge bitcoin/bitcoin#34549: net: reduce log level for PCP/NAT-PMP NOT_AUTHORIZED failures
76de2f8e55f3 Merge bitcoin/bitcoin#34571: test: Fix intermittent issues in feature_assumevalid.py
c808dfbbdcea Merge bitcoin/bitcoin#34329: rpc,net: Add private broadcast RPCs
739f75c0980e Merge bitcoin/bitcoin#33512: coins: use dirty entry count for flush warnings and disk space checks
02c83fef8431 Merge bitcoin/bitcoin#34577: http: fix submission during shutdown race
0b96b9c600e0 Minimize mempool lock, sync txo spender index only when and if needed
d0998cbe348e Merge bitcoin/bitcoin#33199: fees: enable `CBlockPolicyEstimator` return sub 1 sat/vb fee rate estimates
37e449dcc72c Merge bitcoin/bitcoin#34512: rpc: add coinbase_tx field to getblock
097c18239b58 Merge bitcoin/bitcoin#34385: subprocess: Fix `-Wunused-private-field` when building with clang-cl on Windows
910bd1c964b6 Merge bitcoin/bitcoin#34582: rpc: Properly parse -rpcworkqueue/-rpcthreads
e0463b4e8c25 rpc: add coinbase_tx field to getblock
5a8a427610ed Merge bitcoin/bitcoin#32745: scripted-diff: Update DeriveType enum values to mention ranged derivations
3d82ec5bdd01 Add a "tx output spender" index
8ee24d764a28 Merge bitcoin/bitcoin#34604: guix: remove double export of `TZ`
4933d1fbbada Merge bitcoin/bitcoin#28792: build: Embedded ASMap [3/3]: Build binary dump header file
6d482b22de15 Merge bitcoin/bitcoin#32138: wallet, rpc: remove settxfee and paytxfee
726b3663cc8e http: properly respond to HTTP request during shutdown
241ad5853bca Merge bitcoin-core/gui#929: Use plurals where necessary
a849b7e1ff35 Merge bitcoin-core/gui#928: Replace three dots with ellipsis
9e4567b17a28 Merge bitcoin/bitcoin#34581: test: Set assert_debug_log timeout to 0
655b9d12ee17 Merge bitcoin/bitcoin#32950: validation: remove BLOCK_FAILED_CHILD
2706758dc38c Merge bitcoin/bitcoin#34349: util: Remove brittle and confusing sp::Popen(std::string)
59e10a5463dc Merge bitcoin/bitcoin#34023: Optimized SFL cluster linearization
59d24bd5dd2a threadpool: make Submit return Expected instead of throwing
fb3e1bf9c977 test: check LoadBlockIndex correctly recomputes invalidity flags
29740c06ac53 validation: remove BLOCK_FAILED_MASK
b5b2956bda32 validation: reset BLOCK_FAILED_CHILD to BLOCK_FAILED_VALID when loading from disk
37bc20785278 validation: stop using BLOCK_FAILED_CHILD
120c631e1689 refactor: use clearer variables in InvalidateBlock()
fa4cb96bdec2 test: Set assert_debug_log timeout to 0
c2fcf2506973 clusterlin: inline GetReachable into Deactivate (optimization)
d90f98ab4aaa clusterlin: inline UpdateChunk into (De)Activate (optimization)
b684f954bbfc clusterlin: unidirectional MakeTopological initially (optimization)
1daa600c1ca8 clusterlin: track suboptimal chunks (optimization)
63b06d5523f1 clusterlin: keep track of active children (optimization)
ae16485aa94d clusterlin: special-case self-merges (optimization)
3221f1a074e7 clusterlin: make MergeSequence take SetIdx (simplification)
7194de3f7c53 clusterlin: precompute reachable sets (optimization)
6f898dbb8bfa clusterlin: simplify PickMergeCandidate (optimization)
dcf458ffb99c clusterlin: split up OptimizeStep (refactor)
cbd684a4713d clusterlin: abstract out functions from MergeStep (refactor)
b75574a6531e clusterlin: improve TxData::dep_top_idx type (optimization)
73cbd15d4572 clusterlin: get rid of DepData (optimization)
7c6f63a8a9dc clusterlin: pool SetInfos (preparation)
20e2f3e96df3 scripted-diff: rename _rep -> _idx in SFL
268fcb6a53ec clusterlin: add more Assumes and sanity checks (tests)
d69c9f56ea96 clusterlin: count chunk deps without loop (optimization)
f66fa69ce008 clusterlin: split tx/chunk dep counting (preparation)
900e45977889 clusterlin: avoid depgraph argument in SanityCheck (cleanup)
666b37970f15 clusterlin: fix type to count dependencies
a7c29df0e5ac Merge bitcoin/bitcoin#34552: fees: refactor: separate feerate format from fee estimate mode
231dd04b8dcb build: define CMAKE_COMPILE_WARNING_AS_ERROR as a cache option
fa48d421636c test: Stricter unit test
fa626bd14341 util: Remove brittle and confusing sp::Popen(std::string)
fd06157d1465 test: Add coverage for restarted node without any block sync
3d7ab7ecb7df rpc, test: Address feedback from #29668
312919c9dd5d test: Indices can not start based on block data without undo data
a9a3b29dd687 index: Check availability of undo data for indices
c8c9c1e61759 Merge bitcoin/bitcoin#34383: ci: remove commit count limit from `test-each-commit` and fail fast
62e378584e77 guix: don't export TZ twice
badcf1c68dbf guix: fix typo in guix-codesign
8a050b9cb68a Merge bitcoin/bitcoin#34575: test: Avoid empty errmsg in JSONRPCException
746d8cddc191 qt: Use plurals where necessary
fa5672dcafa1 refactor: [gui] Use SettingTo<int64_t> over deprecated SettingToInt
35e6444fdc40 Merge bitcoin/bitcoin#34570: doc: update Windows MSVC build guide to utilize winget to install build requirements
d159b103987f doc: update Windows MSVC build guide to utilize WinGet to install apps
afea2af13913 net: reduce log level for PCP/NAT-PMP NOT_AUTHORIZED failures
fac3ecaf69d6 rpc: Properly parse -rpcworkqueue/-rpcthreads
faee36f63b5f util: Add SettingTo<Int>() and GetArg<Int>()
6df4a045f797 qt: Replace three dots with ellipsis
211111b8048d test: Avoid empty errmsg in JSONRPCException
b65ff0e5a1fd Merge bitcoin/bitcoin#34548: ci: Add and use ci-windows-cross.py helper
03e5f063b5c0 Merge bitcoin/bitcoin#34559: ci: split vcpkg tools cache into restore/save
84e826ddc1cf Merge bitcoin/bitcoin#34511: test: fully reset the state of CConnman in tests
309c51d89dfc Merge bitcoin/bitcoin#34546: kernel: Avoid duplicating symbols in the kernel library
24f93c9af7f6 release note
331a5279d277 wallet, rpc:remove settxfee and paytxfee
eafd530d2032 kernel: avoid potential duplicate object in shared library/binary
24c3b4701003 build: add kernel-specific warnings
cae6d895f8a8 fuzz: add target for CoinsViewOverlay
86eda88c8e48 fuzz: move backend mutating block to end of coins_view
89824fb27b22 fuzz: pass coins_view_cache to TestCoinsView in coins_view
73e99a596655 coins: don't mutate main cache when connecting block
67c0d1798e61 coins: introduce CoinsViewOverlay
69b01af0eb90 coins: add PeekCoin()
f700609e8ada doc: Release notes for mining IPC interface bump
79c934b51cdc cmake: Fix NetBSD-specific workaround for Boost
fa90d44a2283 test: Fix intermittent issues in feature_assumevalid.py
07b924775e4f Merge bitcoin/bitcoin#34427: lint: Flatten lint image entry points
9453c153612a ipc mining: break compatibility with existing clients (version bump)
70de5cc2d205 ipc mining: pass missing context to BlockTemplate methods (incompatible schema change)
2278f017afad ipc mining: remove deprecated methods (incompatible schema change)
c6638fa7c5e9 ipc mining: provide default option values (incompatible schema change)
a4603ac77412 ipc mining: declare constants for default field values
ff995b50cf9e ipc test: add workaround to block_reserved_weight exception test
b970cdf20fce test framework: expand expected_stderr, expected_ret_code options
df53a3e5ec87 rpc refactor: stop using deprecated getCoinbaseCommitment method
0b4cd08fcd22 Merge bitcoin/bitcoin#33965: mining: fix -blockreservedweight shadows IPC option
2a1d0db7994e doc: Mention private broadcast RPCs in release notes
c3378be10b0a test: Cover abortprivatebroadcast in p2p_private_broadcast
557260ca14ac rpc: Add abortprivatebroadcast
15dff452eb61 test: Cover getprivatebroadcastinfo in p2p_private_broadcast
996f20c18af0 rpc: Add getprivatebroadcastinfo
5e64982541f3 net: Add PrivateBroadcast::GetBroadcastInfo
55c49ff8f4b1 Merge bitcoin/bitcoin#34143: build: Prevent system header fallback and include path pollution
c134b1a4bc35 Merge bitcoin/bitcoin#34257: txgraph: deterministic optimal transaction order
4a05825a3f39 Merge bitcoin/bitcoin#33689: http: replace WorkQueue and single threads handling for ThreadPool
c1355493e2c2 refactor: fees: split fee rate format from fee estimate mode
c413cf12c5c6 ci: Split vcpkg tools cache into restore/save
337fef9f2f68 Merge bitcoin/bitcoin#34554: build: avoid exporting secp256k1 symbols
922ebf96ed66 refactor: move-only: move `FeeEstimateMode` enum to `util/fees.h`
cb1798000c25 Merge bitcoin/bitcoin#33861: build: Bump VS minimum supported version to 18.3
7640863a0fbe Merge bitcoin/bitcoin#34555: doc: archive release notes for v29.3
d29bc5e6dd71 doc: archive release notes for v29.3
fd625d84ae9e Merge bitcoin/bitcoin#34539: test: Fixup TODO comment in feature_dbcrash.py; remove unnecessary sleep
6777314310bc Merge bitcoin/bitcoin#34551: ci: Extend diff context for clang-format
452c743951fa refactor: Remove workaround for resolved MSVC bug
7164a0cab650 build: Bump VS minimum supported version to 18.3
2ccfdb582b64 build: avoid exporting secp256k1 symbols
fa8c89511d83 Fixup TODO comment in feature_dbcrash.py; remove unnecessary sleep
f8d2f30bf37d ci: Extend diff context for clang-format
91a8e9b549e9 Merge bitcoin-core/gui#807: refactor: interfaces, make 'createTransaction' less error-prone
573bb542be80 net: Store recipient node address in private broadcast
fa13b13239e5 ci: [refactor] Use pathlib over os.path
fa2719ab1ba2 ci: [refactor] Move run_unit_tests to ci-windows-cross.py
fa99ba5f14d4 ci: Set PREVIOUS_RELEASES_DIR env var in ci-windows-cross.py
fa4a1cab6c17 ci: Move run_functional_tests into ci-windows-cross.py
1111108685ec ci: [refactor] Move pyzmq install and get_previous_releases into ci-windows-cross.py
fac9c7bd6635 ci: [refactor] Move config.ini rewrite to ci-windows-cross.py
faf738946668 ci: Move check_manifests step to ci-windows-cross.py
fa674d55df57 ci: [refactor] Move print_version step into ci-windows-cross.py helper
6f113cb1847c txgraph: use fallback order to sort chunks (feature)
0a3351947e73 txgraph: use fallback order when linearizing (feature)
fba004a3df02 txgraph: pass fallback_order to TxGraph (preparation)
941c432a4637 txgraph test: subclass TxGraph::Ref like mempool does (preparation)
39d0052cbf47 clusterlin: make optimal linearizations deterministic (feature)
8bfbba32077c txgraph: sort distinct-cluster chunks by equal-feerate-prefix size (feature)
e0bc73ba9270 clusterlin: sort tx in chunk by feerate and size (feature)
6c1bcb2c7c1a txgraph: clear cluster's chunk index in ~Ref (preparation)
7427c7d09830 txgraph: update chunk index on Compact (preparation)
3ddafceb9afd txgraph: initialize Ref in AddTransaction (preparation)
64294c89094d Merge bitcoin/bitcoin#34500: ci: Print verbose Windows CI build failure
5f6bfa3649c3 Merge bitcoin/bitcoin#34057: test: add tests for cluster chunks
6ca7782db9b4 Merge bitcoin/bitcoin#34523: doc: Clarify why performance-move-const-arg.CheckTriviallyCopyableMove=false
44afed4cd970 Merge bitcoin/bitcoin#34524: refactor: [rpc] Remove confusing and brittle integral casts (take 2)
3764746404a8 Merge bitcoin/bitcoin#34241: test: Check that interrupt results in EXIT_SUCCESS
18f11695c755 validation: don't update BLOCK_FAILED_VALID to BLOCK_FAILED_CHILD in InvalidateBlock
acefdce08311 Merge bitcoin/bitcoin#34469: consensus/test/doc: cover errors in `CheckTxInputs` with unit tests
7e5e0b20ea3e Merge bitcoin/bitcoin#32773: cmake: Create subdirectories in build tree in advance
fa90277d22e1 ci: Use ubuntu-slim for [meta] runners
fa9627af9f89 ci: Rely on cmake --preset toolchain file
fa3f89acaa7a ci: Add check_manifests to ci-windows.py
1111079a16b9 ci: Add run_tests step to ci-windows.py
6d625af2831b Merge bitcoin/bitcoin#32621: contrib: utxo_to_sqlite.py: add option to store txid/spk as BLOBs
afb1bc120ecc validation: Use dirty entry count in flush warnings and disk space checks
b413491a1cdd coins: Keep track of number of dirty entries in `CCoinsViewCache`
7e52b1b945c4 fuzz: call `EmplaceCoinInternalDANGER` as well in `SimulationTest`
8f0e1f6540be Merge bitcoin/bitcoin#34465: refactor: separate log generation from log handling
b2805eec35ce Merge bitcoin/bitcoin#34528: test: Fix intermittent failure in `feature_assumevalid.py` by ensuring invalid block was processed before checking debug.log
72030efd4b83 Merge bitcoin/bitcoin#34525: Release: Prepare "Open Transifex translations for v31.0" step
fe0b1513a7c5 test: add a test for txgraph staging
ef253a9d3d16 test: add block builder tests for txgraph
4a1ac31e97c2 test: add a chunk test for txgraph
b623fab1ba87 mining: enforce minimum reserved weight for IPC
d3e49528d479 mining: fix -blockreservedweight shadows IPC option
418b7995ddfb test: have mining template helpers return None
54bd49c7e3c7 Merge bitcoin/bitcoin#34452: test: split interface_ipc.py
3b39a8aeb4c6 Merge bitcoin/bitcoin#34483: refactor: Use SpanReader over DataStream
6f68e0c8b760 Merge bitcoin/bitcoin#34181: refactor: [p2p] Make ProcessMessage private again, Use references when non-null
4c0d4f6f93f3 refactor: interfaces, make 'createTransaction' less error-prone
e2c3ec9bf412 refactor: move CreatedTransactionResult to types.h
45372175c35b gui: remove AmountWithFeeExceedsBalance error special case
d88997b809db Merge bitcoin/bitcoin#34299: wallet: remove PreSelectedInputs and re-activate "AmountWithFeeExceedsBalance" error
b73a62f667d0 test: Ensure invalid block was processed before checking debug.log
633d1831199a test: misc interface_ipc_mining.py improvements
52ccd9215e67 test: split interface_ipc_mining.py into subtests
4e49fa2a6884 test: add interface_ipc_mining.py
01a1ae889e5a test: move IPC helpers to ipc_util.py
28160c1e3dc1 Merge bitcoin/bitcoin#34421: ci: add Chimera Linux LTO config
576f89202798 qt: Update the `src/qt/locale/bitcoin_en.xlf` translation source file
4b9f5beafe9e Update Transifex slug for 31.x
46e1288df2b4 Merge bitcoin/bitcoin#34498: iwyu: Fix patch to prefer `<cstdint>`
fa6801366d76 refactor: [rpc] Remove confusing and brittle integral casts (take 2)
d79249d2799e ci: add chimera Linux LTO CI job
48161f6a0503 wallet: introduce "tx amount exceeds balance when fees are included" error
b7fa609ed175 wallet: remove PreSelectedInputs
7819da2c1643 walllet: use CoinsResult instead of PreSelectedInputs
0cd309c75e58 Merge bitcoin/bitcoin#34492: ci: Drop valgrind fuzz from GHA matrix
fa561682ce40 ci: [refactor] Add .github/ci-windows.py prepare_tests step
fa3e607c6dfb ci: Print verbose Windows CI build failure
4444808dd3a7 ci: [refactor] Add .github/ci-windows.py build step
fabdd4e82342 ci: Refactor Windows CI into script
fa88ac3f4f9b doc: Clarify why performance-move-const-arg.CheckTriviallyCopyableMove=false
fa0677d13119 refactor: Use SpanReader over DataStream
e5474079f179 wallet: introduce GetAppropriateTotal() in CoinsResult
d8ea921d0140 wallet: correctly reserve in CoinsResult::All()
7072d825e39d wallet: ensure COutput added in set are unique
fefa3be782ea wallet: fix, make 'total_effective_amount' optional actually optional
9ec1ae0e98c0 Merge bitcoin/bitcoin#34437: rpc: `uptime` should begin on application start
d692e0722813 Merge bitcoin/bitcoin#32894: FUZZ: Test that BnB finds best solution
28d860788286 Merge bitcoin/bitcoin#34504: build: replace `WERROR` with `CMAKE_COMPILE_WARNING_AS_ERROR`
ad1940a006b6 Merge bitcoin/bitcoin#34517: drop my key from trusted-keys
322c4ec4422a build: replace WERROR with CMAKE_COMPILE_WARNING_AS_ERROR
65134c7e5f99 depends: Prefix include path for headers-only `systemtap` package
94a692b6aa09 cmake: Add missed `USDT::headers`
b5375c44ed16 depends: Prefix include path for headers-only `boost` package
d73378ffcca2 cmake: Add missed `Boost::headers`
eb97250421d3 Merge bitcoin/bitcoin#34496: build: don't pass on boost dependency to kernel consumers
9d7694729481 Merge bitcoin/bitcoin#34464: Change BlockRequestAllowed() to take ref (minor refactor)
8966352df3fc doc: add release notes
704a09fe7187 test: ensure fee estimator provide fee rate estimate < 1 s/vb
243e48cf4933 fees: delete unused dummy field
fc4fbda42af1 fees: bump fees file version
b54dedcc8563 fees: reduce `MIN_BUCKET_FEERATE` to 100
2cb7e99deee1 test: also reset CConnman::m_private_broadcast in tests
41b9b76cce6a Merge bitcoin/bitcoin#34510: doc: fix broken bpftrace installation link
91b7c874e2b1 test: add ConnmanTestMsg convenience method Reset()
42ee31e80c99 doc: fix broken bpftrace installation link
54d039305823 FUZZ: Test that BnB finds best solution
eb510f8678ba ci: fail fast in test-each-commit script
04c4d710087b ci: remove commit count limit from `test-each-commit`
4ae00e9a7183 Merge bitcoin/bitcoin#32636: Split `CWallet::Create()` into `CreateNew` and `LoadExisting`
d4bc620ad8cf Merge bitcoin/bitcoin#34488: refactor: Small style and test fixups for bitcoinkernel
eb3dbbaf30fc Merge bitcoin/bitcoin#34493: contrib: Remove valgrind suppression for bug 472219
1e64aeaaecc2 Merge bitcoin/bitcoin#34295: test: Improve STRICTENC/DERSIG unit tests
b65a3d80093b iwyu: Fix patch to prefer `<cstdint>`
a50d0b6720f3 build: don't pass on boost dependency to kernel consumers
3532e242134e Merge bitcoin/bitcoin#32748: fees: fix noisy flushing log
fad9dd1a8891 test: kernel test fixups
fabb58d42dc2 test: Use clang-tidy named args for create_chainman
fa51594c5c0f refactor: Small style fixups in src/kernel/bitcoinkernel.cpp
fa33acec89f0 Revert "valgrind: add suppression for bug 472219"
24699fec8422 doc: Add initial asmap data documentation
bab085d282b1 ci: Use without embedded asmap build option in one ci job
e53934422a29 doc: Expand documentation on asmap feature and tooling
6244212a5532 init, net: Implement usage of binary-embedded asmap data
6202b50fb900 build: Generate ip_asn.dat.h during build process
634cd60dc8f6 build: Add embedded asmap data
faa4ab113cc9 ci: Drop valgrind fuzz from GHA matrix
02b5f6078d65 fees: make flushes log debug only
b58eebf1520f Merge bitcoin/bitcoin#34470: Bump leveldb subtree and remove UB workaround in CI
8bb277c12373 Merge bitcoin/bitcoin#34481: Update secp256k1 subtree to latest master
a4941132d311 Merge bitcoin/bitcoin#34461: ci: Print verbose build error message in test-each-commit
fad7d86d8d17 ci: Remove unused workaround after leveldb subtree bump
fabced56f650 Bump leveldb subtree
be35408c5ad7 Merge bitcoin/bitcoin#34474: ci: update ccache to improve hitrate
2f2952c5f2e3 Squashed 'src/leveldb/' changes from cad64b151d..ab6c84e6f3
7528d18796a2 ci: show more verbose ccache stats
47c9297172b0 Merge bitcoin/bitcoin#32420: mining, ipc: omit dummy extraNonce from coinbase
4b53cbd69220 test: Test for musig() in various miniscript expressions
ec0f47b15cb3 miniscript: Using Func and Expr when parsing keys, hashes, and locktimes
6fd780d4fbc4 descriptors: Increment key_exp_index in ParsePubkey(Inner)
b12281bd86e2 miniscript: Use a reference to key_exp_index in KeyParser
ce4c66eb7c5e test: Test that key expression indexes match key count
8c03318387f6 consensus/doc: explain `GetValueOut()` precondition
82ef92c8d006 consensus/doc: explain unreachable `bad-txns-fee-outofrange` check
fad3eb395645 refactor: Use SpanReader over DataStream
fa06e26764bb refactor: [qt] Use SpanReader to avoid two vector copies
fabd4d2e2e3c refactor: Avoid UB in SpanReader::ignore
37cc2a2d953c logging: use util/log.h where possible
8799eb74406e Merge bitcoin/bitcoin#33878: refactor, docs: Embedded ASMap [2/3]: Refactor asmap internals and add documentation
bb8e9e7c4c8d logging: Move message formatting to util/log.h
001f0a428e3a move-only: Move logging macros to util/log.h
94c0adf4e857 move-onlyish: Move logging levels to util/log.h
56d113cab034 move-only: move logging categories to logging/categories.h
f5233f7e9827 move-only: Move SourceLocation to util/log.h
fa20bc2ec275 refactor: Use empty() over eof() in the streams interface
fa879db73528 test: Read debug log for self-checking comment
d405713197f8 ci: use Alpine 3.23
1cee0e4cd3af ci: detect apk usage generally
1ed3de5a6d97 Update secp256k1 subtree to latest master
9d4c9b00356e Squashed 'src/secp256k1/' changes from 14e56970cb..57315a6985
9f8764c814ea Merge bitcoin/bitcoin#34475: ci: Treat SHA1 LLVM signing key as warning
3c8f5e48f710 ci: Treat SHA1 LLVM signing key as warning
5cb4cf9b428e Merge bitcoin/bitcoin#34036: contrib: update macOS SDK to Xcode-26.1.1-17B100
41034a032f0f Merge bitcoin/bitcoin#34396: fuzz: pull the latest FuzzedDataProvider.h from upstream
580e9eefe39f ci: bump CCACHE_MAXSIZE to 2G
ff095839285d Merge bitcoin/bitcoin#34432: test: Turn ElapseSteady into SteadyClockContext
81e67d9aa134 Merge bitcoin/bitcoin#34179: refactor: Enable transparent lookup for setBlockIndexCandidates to remove const_cast
ec70bead5e1e Merge bitcoin/bitcoin#34433: script: remove unused `SCRIPT_ERR_LAST`
08547ee1b06d Merge bitcoin/bitcoin#34443: validation: follow-up nits for lock-free `IsInitialBlockDownload()`
881ab4fc82fe support multiple block status checks in CheckBlockDataAvailability
232a2bce90a9 consensus/test: add out-of-range output unit tests for `CTransaction::GetValueOut`
aa87aae14f9e consensus/test: add `MoneyRange` unit tests for `CheckTxInputs`
8bb77f348ef3 Merge bitcoin/bitcoin#34455: ci, iwyu: Fix warnings in `src/univalue` and treat them as errors
1bf384222323 ci, iwyu: Fix warnings in `src/univalue` and treat them as errors
3d180d3c7f1f Merge bitcoin/bitcoin#34462: util: Drop *BSD headers in `batchpriority.cpp`
1eed88a3ec65 Merge bitcoin/bitcoin#34460: iwyu: Update mappings
101daa41636a Merge bitcoin/bitcoin#34338: ci, iwyu: Fix warnings in `src/zmq` and treat them as errors
dfb93646093f fuzz: pull latest FuzzedDataProvider.h from upstream
705705e5b195 Merge bitcoin/bitcoin#33701: test: add case where `TOTAL_TRIES` is exceeded yet solution remains
88f802983571 Merge bitcoin/bitcoin#34100: doc: Use multipath descriptors in descriptors.md and linked test
5ad94cf6b7eb Merge bitcoin/bitcoin#34381: script: return proper error for `CScriptNum` errors
4f85b05131bf Merge bitcoin/bitcoin#31713: miniscript refactor: Remove unique_ptr-indirection
1f8f7d477ae0 Change BlockRequestAllowed() to take ref
5d2707307e27 Merge bitcoin/bitcoin#34454: wallet: Rename `RecordType::DELETE` to `RecordType::DELETE_FLAG`
38fd85c676a0 http: replace WorkQueue and threads handling for ThreadPool
c323f882ed38 fuzz: add test case for threadpool
c528dd5f8ccc util: introduce general purpose thread pool
07af50f7896a util: Drop *BSD headers in `batchpriority.cpp`
4dfb6eef70d7 test: Add DERSIG tests to script_tests
884978f3894a test: Fix a STRICTENC test in script_tests
527e8ca7b545 test: Remove outdated comment in script_tests
516be10bb56d wallet: Rename `RecordType::DELETE` to `RecordType::DELETE_FLAG`
bbbb78a4f28f ci: Print verbose build error message in test-each-commit
2222dadabbbd ci: [refactor] Allow overwriting check option in run helper
9c839aa9e3db iwyu: Document mappings for libc symbols
91824646c58a iwyu: Add temporary mapping to work around upstream bug
37de7d19107c iwyu: Drop backported mapping
01651324f4e5 Merge bitcoin/bitcoin#34434: miniscript: correct and_v() properties
c7cf2b8f3aae Merge bitcoin/bitcoin#34445: fuzz: Use `__AFL_SHM_ID` for naming test directories
0d1d393877a7 Merge bitcoin/bitcoin#34429: test: Check that redundant verack message is ignored
23a2e3354edf Merge bitcoin/bitcoin#34453: ci: Always print low ccache hit rate notice
5401e673d561 Merge bitcoin/bitcoin#33604: p2p: Allow block downloads from peers without snapshot block after assumeutxo validation
6750744eb32d Merge bitcoin/bitcoin#34164: validation: add reusable coins view for ConnectBlock
4e4fa0199ee2 Merge bitcoin/bitcoin#33680: validation: do not wipe utxo cache for stats/scans/snapshots
fad2876ec330 ci: Always print low ccache hit rate notice
e67a676df9af fix: uptime RPC returns 0 on first call
a89e1618dd8c contrib: update macOS SDK to Xcode-26.1.1-17B100
57a778ed2526 depends: use -Xclang -fno-cxx-modules in macOS cross build
3e0fd0e4ddd8 refactor: rename will_reuse_cache to reallocate_cache
44b4ee194d3b validation: reuse same CCoinsViewCache for every ConnectBlock call
8fb6043231ea coins: introduce CCoinsViewCache::ResetGuard
041758f5eda5 coins: use hashBlock setter internally for CCoinsViewCache methods
8dd9200fc9b0 coins: add Reset on CCoinsViewCache
efcbf794484e ci, iwyu: Fix warnings in `src/zmq` and treat them as errors
d3e681bc0675 fuzz: Use `__AFL_SHM_ID` for naming test directories
f7e0c3d3d370 Merge bitcoin/bitcoin#34346: test: use IP_PORTRANGE_HIGH on FreeBSD for dynamic port allocation
eeb4d2814803 validation: follow-up nits for lock-free `IsInitialBlockDownload()`
1c2f164d3486 Merge bitcoin/bitcoin#34253: validation: cache tip recency for lock-free `IsInitialBlockDownload()`
8cdf1dcca0ce Merge bitcoin/bitcoin#34373: refactor: Remove remaining std::bind, check via clang-tidy
facb2aab26df test: Turn ElapseSteady into SteadyClockContext
6354b4fd7fe8 tests: log node JSON-RPC errors during test setup
45930a79412d http-server: guard against crashes from unhandled exceptions
a6cdc3ec9b56 Merge bitcoin/bitcoin#34303: test: addrman: test self-announcement time penalty handling
75ec9001ced9 Merge bitcoin/bitcoin#34207: coins/refactor: enforce `GetCoin()` returns only unspent coins
4fab35cf88c0 miniscript: correct and_v() properties
51abf7d15b1d script: remove unused SCRIPT_ERR_LAST
f2b8acc0edb6 remove glozow from trusted keys
cd1af852fa5d Merge bitcoin/bitcoin#34358: wallet: fix removeprunedfunds bug with conflicting transactions
2dd5e7bb38da Merge bitcoin/bitcoin#34409: test: use `ModuleNotFoundError` in `interface_ipc.py`
d3e8c459e776 Merge bitcoin/bitcoin#34417: log: Print warning about privacy-sensitive log info unconditionally
d9851f9a7c1c Merge bitcoin/bitcoin#33472: guix: documented shasum gathering command
a7460b992884 Merge bitcoin/bitcoin#34098: test: [move-only] Move lint functions into modules
8f9ad534a5a5 Merge bitcoin/bitcoin#34352: ci, iwyu: Fix warnings in `src/primitives` and treat them as errors
faba426b3b66 lint: Flatten lint image entry points
1111fff91c76 lint: Add missing --platform=linux to docker build command
feb74a9372be Merge bitcoin/bitcoin#34430: ci: mount git directory as writable in linter
fad042235bd6 refactor: Remove remaining std::bind, check via clang-tidy
c8abac994122 ci: mount .git dir rw
d9e651f9954f Merge bitcoin/bitcoin#33622: docs: add doc comment for SRD selection algorithm
cb128bcedb58 Merge bitcoin/bitcoin#34408: ci: remove gnu-getopt usage
6ae96ed60745 Merge bitcoin/bitcoin#34276: Remove empty caption from user interface (noui, gui)
fafdae46ff0b test: Check that redundant verack message is ignored
289d60f5ab76 Merge bitcoin/bitcoin#34161: refactor: avoid possible UB from `std::distance` for `nullptr` args
1d3243806da6 Merge bitcoin/bitcoin#34391: lint: upgrade lint scripts for worktrees
d931b54d138f Merge bitcoin/bitcoin#34412: Update secp256k1 subtree to latest master
3400db80401d doc: add missing param description to SRD
c0e6556e4f51 Merge bitcoin/bitcoin#34413: doc: Remove outdated -fdebug-prefix-map section in dev notes
9260b20ef175 Merge bitcoin/bitcoin#33962: refactor: replace manual promise with SyncWithValidationInterfaceQueue
ddae1b4efa56 ci: remove gnu-getopt usage
fa43897c1d14 doc: Fix LLM nits in net_processing.cpp
bbbba0fd4b87 scripted-diff: Use references when nullptr is not possible
fac541546604 refactor: Separate peer/maybe_peer in ProcessMessages and SendMessages
fac529188e0d refactor: Pass Peer& to ProcessMessage
fa376095a01c refactor: Pass CNode& to ProcessMessages and SendMessages
fada8380148c refactor: Make ProcessMessage private again
fa80cd3ceed4 test: [refactor] Avoid calling private ProcessMessage() function
d511adb664ed [miner] omit dummy extraNonce via IPC
bf3b5d6d069a test: clarify getCoinbaseRawTx() comparison
78df9003d634 [doc] Update comments on dummy extraNonces in tests
e770392084aa test: addrman: test self-announcement time penalty handling
27aeeff63014 Merge bitcoin/bitcoin#34328: rpc: make `uptime` monotonic across NTP jumps
5aeaa71c77ac lint: pass args from lint.py to cargo run in container
c17a2adb8dc0 lint: upgrade lint scripts for worktrees
fa9c92d7b639 log: Print warning about privacy-sensitive log info unconditionally
f970cb39fb64 Merge bitcoin/bitcoin#34267: net: avoid unconditional `privatebroadcast` logging (+ warn for debug logs)
8593d965191e Merge bitcoin/bitcoin#33067: test: refactor ValidWitnessMalleatedTx class to helper function
2fccbea3c8a0 Squashed 'src/secp256k1/' changes from d543c0d917..14e56970cb
26fbe10873e7 Update secp256k1 subtree to latest master
34a5ecadd720 Merge bitcoin/bitcoin#34397: doc: fix arg name hints so bugprone can validate them
fa2e1b85dd6b build: Remove outdated comment about -ffile-prefix-map
fa06cd4ba730 doc: Remove outdated -fdebug-prefix-map section in dev notes
ab649ce45945 guix: documented shasum gathering command
1cc58d3a0c65 Merge bitcoin/bitcoin#34281: build: Temporarily remove confusing and brittle `-fdebug-prefix-map`
905dfdee86d6 test: use ModuleNotFoundError in interface_ipc.py
2778eb46647a Merge bitcoin/bitcoin#34337: fuzz: Return chrono point from ConsumeTime(), Add ConsumeDuration()
d70fb8a5754f Merge bitcoin/bitcoin#34351: util: Remove `FilterHeaderHasher`
6472ba06c36a Merge bitcoin/bitcoin#34388: doc: Explain that low-effort pull requests may be closed
1f60ca360eb8 wallet: fix removeprunedfunds bug with conflicting transactions
5f66fca633c8 Merge bitcoin-core/gui#920: Set peer version and subversion to N/A when not available or detecting
02240a7698e3 Merge bitcoin/bitcoin#34390: test: allow overriding `tar` in `get_previous_releases.py`
7d9e1a810239 test: Verify peer usage after assumeutxo validation completes
3bd98b45084d refactor: use transparent comparator for setBlockIndexCandidates lookups
a73a3ec5532d doc: fix invalid arg name hints for bugprone validation
eeee3755f8c4 fuzz: Return chrono point from ConsumeTime(), Add ConsumeDuration()
1b36bf0c5d71 subprocess: Fix `-Wunused-private-field` for `Child` class on Windows
9f2b338bc018 subprocess: Fix `-Wunused-private-field` for `Popen` class on Windows
fa15a8d2d03b doc: Explain that low-effort pull requests may be closed
be2b48b9f3e5 test: allow overriding tar in get_previous_releases
db2effaca4cf scripted-diff: refactor: CWallet::Create() -> CreateNew()
27e021ebc0dd wallet: Correctly log stats for encrypted messages.
d8bec61be233 wallet: remove loading logic from CWallet::Create
f35acc893fb3 refactor: wallet: Factor out `WriteVersion()` from `PopulateWalletFromDB()`
e12ff8aca049 test: wallet: Split create and load
70dbc79b09ac wallet: Use CWallet::LoadExisting() for loading existing wallets.
ae66e0116462 wallet: Create separate function for wallet load
bc69070416c6 refactor: Wallet stats logging in its own function
a9d64cd49c69 wallet: Remove redundant birth time update
b4a49cc7275e wallet: Move argument parsing to before DB load
b15a94a618c5 refactor: Split out wallet argument loading
6f7b4323cb46 test: remove UNKNOWN_ERROR from script_tests
bd31a92d6716 script: use SCRIPT_ERR_SCRIPTNUM for CScriptNum errors
0ca4dcd78665 script: add SCRIPT_ERR_SCRIPTNUM error
2845f10a2be0 test: extend FreeBSD ephemeral port range fix to P2P listeners
3f5211cba8e7 test: remove child_one/child_two (w)txid variables
7cfe790820cf test: replace ValidWitnessMalleatedTx class with function
4fec726c4d35 refactor: Simplify Interpret asmap function
79e97d45c16f doc: Add more extensive docs to asmap implementation
cf4943fdcdd1 refactor: Use span instead of vector for data in util/asmap
385c34a05261 refactor: Unify asmap version calculation and naming
fa41fc6a1a7d refactor: Operate on bytes instead of bits in Asmap code
964c44cdcd6b test(miniscript): Prove avoidance of stack overflow
198bbaee4959 refactor(miniscript): Destroy nodes one full subs-vector at a time
50cab8570e8f refactor(miniscript): Remove NodeRef & MakeNodeRef()
15fb34de41cb refactor(miniscript): Remove superfluous unique_ptr-indirection
e55b23c170eb refactor(miniscript): Remove Node::subs mutability
c6f798b22247 refactor(miniscript): Make fields non-const & private
22e4115312b9 doc(miniscript): Remove mention of shared pointers
34bed0ed8c44 test: use IP_PORTRANGE_HIGH on FreeBSD for dynamic port allocation
ccf9172ab3bb util: Remove `FilterHeaderHasher`
fdc9fe2da6a8 ci, iwyu: Fix warnings in `src/primitives` and treat them as errors
477c5504e05f  coins: replace `std::distance` with unambiguous pointer subtraction
81675a781f3a test: use pre-generated chain
14f99cfe53f0 rpc: make `uptime` monotonic across NTP jumps
a9440b1595be util: add `TicksSeconds`
a02c4a82d88a refactor: Move -walletbroadcast setting init
411caf72815b wallet: refactor: PopulateWalletFromDB use switch statement.
a48e23f566cc refactor: wallet: move error handling to PopulateWalletFromDB()
faa5a9ebad15 fuzz: Use min option in ConsumeTime
0972785fd723 wallet: Delete unnecessary PopulateWalletFromDB() calls
f0a046094e4c scripted-diff: refactor: CWallet::LoadWallet->PopulateWalletFromDB
fad7bd9ba3ee noui: Remove always empty caption while formatting
fa8ebeb33232 refactor: [gui] Document that the title is always empty for node message
fafe71b743a0 refactor: Remove empty caption from ThreadSafeMessageBox
fa8d0088e76d refactor: Remove empty caption from ThreadSafeQuestion
fa37928536e0 build: Temporarily remove confusing and brittle -fdebug-prefix-map
b39291f4cde0 doc: fix `-logips` description to clarify that non-debug logs can also contain IP addresses
c7028d3368e9 init: log that additional logs may contain privacy-sensitive information
31b771a9425d net: move `privatebroadcast` logs to debug category
fa16b275fa94 test: Check that interrupt results in EXIT_SUCCESS
fab7c7f56c1d test: Split large init_stress_test into two smaller functions
fa0195499ca6 refactor: [gui] Use lambdas over std::bind
eeee1e341fa5 refactor: Remove trailing semicolon after ADD_SIGNALS_DECL_WRAPPER
557b41a38ccf validation: make `IsInitialBlockDownload()` lock-free
b9c0ab3b75a1 chain: add `CChain::IsTipRecent` helper
8d531c6210eb validation: invert `m_cached_finished_ibd` to `m_cached_is_ibd`
8be54e3b1967 test: cover IBD exit conditions
2ee7f9b25905 coins: assume `GetCoin` only returns unspent coins
eec551aaf1df fuzz: keep `coinscache_sim` backend free of spent coins
3e4155fcefe0 test: do not return spent coins from `CCoinsViewTest::GetCoin`
ee1e40f58000 txdb: assert `CCoinsViewDB::GetCoin` only returns unspent coins
fa578d9434fd lint: [move-only] Move python related lints to lint_py.rs
fa392c31e7b9 lint: [move-only] Move repo related lints to lint_repo_hygiene.rs
fab0cfa987c9 lint: [move-only] Move cpp related lints to lint_cpp.rs
fa3e48e3fd4d lint: [move-only] Move docs related lints to lint_docs.rs
fad09e77dbe5 lint: [move-only] Move text related lints to text_format.rs
faf40c2f848d lint: [move-only] Move util functions to util.rs
c6ca2b85a3e6 validation: do not wipe utxo cache for stats/scans/snapshots
7099e93d0a80 refactor: rename `FlushStateMode::ALWAYS` to `FORCE_FLUSH`
b261100e7169 [qt] Set peer version and subversion to N/A when not available or detecting
552bc82b1796 doc: Use multipath descriptors in descriptors.md and linked test
0067abe15329 p2p: Allow block downloads from peers without snapshot block after assumeutxo validation
e71c4df16851 refactor: replace manual promise with SyncWithValidationInterfaceQueue
b189a3455744 test: add case where `TOTAL_TRIES` is exceeded yet solution remains
76dae5d6911b cmake: Replace recursive globbing with explicit globbing in folders
a099655f2e1b scripted-diff: Update `DeriveType` enum values to mention ranged derivations
88d909257104 cmake: Create subdirectories in build tree in advance
7378f27b4fb5 test: run utxo-to-sqlite script test with spk/txid format option combinations
b30fca7498c9 contrib: utxo_to_sqlite.py: add options to store txid/spk as BLOBs

git-subtree-dir: libbitcoinkernel-sys/bitcoin
git-subtree-split: d9c7364ac56781a16c7224b2c7a6db9db97f17d8
achow101 added a commit that referenced this pull request Feb 26, 2026
… dependency cleanup

408d5b1 test: include response body in non-JSON HTTP error msg (Matthew Zipkin)
9dc653b test: threadpool, add coverage for all Submit() errors (furszy)
ce2a984 test: cleanup, use HasReason in threadpool_tests.cpp (l0rinc)
d9c6769 test: refactor, decouple HasReason from test framework machinery (furszy)
dbbb780 test: move and simplify BOOST_CHECK ostream helpers (Hodlinator)
3b7cbca test: ensure Stop() thread helps drain the queue (seduless)
ca101a2 test: coverage for queued tasks completion after interrupt (furszy)
bf2c607 threadpool: active-wait during shutdown (furszy)
e88d274 test: add threadpool Start-Stop race coverage (furszy)
8cd4a43 threadpool: guard against Start-Stop race (furszy)
9ff1e82 test: cleanup, block threads via semaphore instead of shared_future (l0rinc)

Pull request description:

  A few follow-ups to #33689, includes:

  1) `ThreadPool` active-wait during shutdown:
  Instead of just waiting for workers to finish processing tasks, `Stop()` now helps them actively.
  This speeds up the JSON-RPC and REST server shutdown, resulting in a faster node shutdown when many requests remain unhandled. This wasn't included in the original PR due to the behavior change this introduces.

  2) Decouple `HasReason` from the unit test framework machinery
  This avoids providing the entire unit test framework dependency to low-level tests that only require access to the `HasReason` utility class. Examples are: `reverselock_tests.cpp`, `sync_tests.cpp`, `util_check_tests.cpp`, `util_string_tests.cpp`, `script_parse_tests.cpp` and `threadpool_tests.cpp`. These tests no longer gain access to unnecessary components like the chainstate, node context, caches, etc. It includes l0rinc's `threadpool_tests.cpp` `HasReason` changes.

  3) Include response body in non-JSON HTTP error messages
  Straight from pinheadmz [comment](#33689 (comment)), it makes debugging CI issues easier.

ACKs for top commit:
  maflcko:
    review ACK 408d5b1 🕗
  achow101:
    ACK 408d5b1
  hodlinator:
    re-ACK 408d5b1

Tree-SHA512: 57aa0ef96886f32bf95a0bd7f87c878d31c9df9e34cb96de615eee703ce0824b5cfdf8f5c9cd19a3594559994295b5810c38c94f5efd6291cbbd83a95473357a
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.