From 6a3540b95731902833dbee03055b968221967dcb Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 24 Jun 2026 21:02:09 +0000 Subject: [PATCH 01/10] Initial plan From 37ca54491756f9b9c55ac832411a911c1bc57206 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 24 Jun 2026 21:28:40 +0000 Subject: [PATCH 02/10] Remove logger thread ID link dependency Co-authored-by: achamayou <4016369+achamayou@users.noreply.github.com> --- CMakeLists.txt | 7 ++--- cmake/ccf_app.cmake | 7 ----- cmake/common.cmake | 7 ++--- include/ccf/threading/thread_ids.h | 35 +++++++++++++++++++--- src/ds/test/logger.cpp | 23 ++++++++++++++ src/enclave/thread_local.cpp | 32 -------------------- tests/perf-system/submitter/CMakeLists.txt | 1 - 7 files changed, 59 insertions(+), 53 deletions(-) delete mode 100644 src/enclave/thread_local.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 29672d4aec3e..4bb04625c594 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -432,7 +432,6 @@ endif() set( CCF_IMPL_SOURCE ${CCF_DIR}/src/enclave/main.cpp - ${CCF_DIR}/src/enclave/thread_local.cpp ${CCF_DIR}/src/node/quote.cpp ${CCF_DIR}/src/node/uvm_endorsements.cpp ${CCF_DIR}/src/node/recovery_decision_protocol.cpp @@ -946,7 +945,6 @@ if(BUILD_TESTS) add_executable( merkle_mem src/node/test/merkle_mem.cpp - ${CCF_DIR}/src/enclave/thread_local.cpp ) add_warning_checks(merkle_mem) target_link_libraries( @@ -958,7 +956,6 @@ if(BUILD_TESTS) add_executable( raft_driver ${CMAKE_CURRENT_SOURCE_DIR}/src/consensus/aft/test/driver.cpp - src/enclave/thread_local.cpp ) add_warning_checks(raft_driver) target_link_libraries(raft_driver PRIVATE ccfcrypto ccf_tasks) @@ -1002,13 +999,13 @@ if(BUILD_TESTS) add_picobench(cose_bench SRCS src/crypto/test/cose_bench.cpp LINK_LIBS) add_picobench( history_bench - SRCS src/node/test/history_bench.cpp src/enclave/thread_local.cpp + SRCS src/node/test/history_bench.cpp LINK_LIBS ccf_kv ccf_tasks ) add_picobench( kv_bench - SRCS src/kv/test/kv_bench.cpp src/enclave/thread_local.cpp + SRCS src/kv/test/kv_bench.cpp LINK_LIBS ccf_kv ) add_picobench(merkle_bench SRCS src/node/test/merkle_bench.cpp) diff --git a/cmake/ccf_app.cmake b/cmake/ccf_app.cmake index d104052bac24..2f119beae2bf 100644 --- a/cmake/ccf_app.cmake +++ b/cmake/ccf_app.cmake @@ -31,13 +31,6 @@ function(add_ccf_app name) target_link_options(${name} PRIVATE LINKER:--no-undefined) endif() - # Tracked in https://github.com/microsoft/CCF/issues/7596. Workaround for a - # circular dependency between ccf.a and ccfcrypto.a - target_link_options( - ${name} - PRIVATE LINKER:--undefined=_ZN3ccf9threading21get_current_thread_idEv - ) - set_property(TARGET ${name} PROPERTY POSITION_INDEPENDENT_CODE ON) add_san(${name}) diff --git a/cmake/common.cmake b/cmake/common.cmake index abe43085a3e3..08ed3513ca5d 100644 --- a/cmake/common.cmake +++ b/cmake/common.cmake @@ -28,7 +28,7 @@ endfunction() # Unit test wrapper function(add_unit_test name) - add_executable(${name} ${CCF_DIR}/src/enclave/thread_local.cpp ${ARGN}) + add_executable(${name} ${ARGN}) target_include_directories( ${name} PRIVATE src ${CCFCRYPTO_INC} ${CCF_DIR}/3rdparty/test @@ -54,7 +54,7 @@ endfunction() # Fuzz test wrapper (requires -DFUZZING=ON) function(add_fuzz_test name) - add_executable(${name} ${CCF_DIR}/src/enclave/thread_local.cpp ${ARGN}) + add_executable(${name} ${ARGN}) target_compile_options(${name} PRIVATE -fsanitize=fuzzer) target_link_options(${name} PRIVATE -fsanitize=fuzzer) target_include_directories(${name} PRIVATE src ${CCFCRYPTO_INC}) @@ -82,7 +82,7 @@ endfunction() # Test binary wrapper function(add_test_bin name) - add_executable(${name} ${CCF_DIR}/src/enclave/thread_local.cpp ${ARGN}) + add_executable(${name} ${ARGN}) target_include_directories( ${name} PRIVATE src ${CCFCRYPTO_INC} ${CCF_DIR}/3rdparty/test @@ -259,7 +259,6 @@ function(add_picobench name) add_executable( ${name} ${PARSED_ARGS_SRCS} - ${CCF_DIR}/src/enclave/thread_local.cpp ) target_include_directories(${name} PRIVATE src ${PARSED_ARGS_INCLUDE_DIRS}) diff --git a/include/ccf/threading/thread_ids.h b/include/ccf/threading/thread_ids.h index 2def60951587..ba021f55fa6e 100644 --- a/include/ccf/threading/thread_ids.h +++ b/include/ccf/threading/thread_ids.h @@ -3,6 +3,7 @@ #pragma once #define FMT_HEADER_ONLY +#include #include #include #include @@ -19,7 +20,33 @@ namespace ccf::threading static constexpr ThreadID MAIN_THREAD_ID = 0; - uint16_t get_current_thread_id(); - void set_current_thread_id(ThreadID to); - void reset_thread_id_generator(ThreadID to = MAIN_THREAD_ID); -} \ No newline at end of file + namespace detail + { + inline std::atomic& next_thread_id() + { + static std::atomic next = MAIN_THREAD_ID; + return next; + } + + inline ThreadID& current_thread_id() + { + thread_local ThreadID current = next_thread_id().fetch_add(1); + return current; + } + } + + inline uint16_t get_current_thread_id() + { + return detail::current_thread_id(); + } + + inline void set_current_thread_id(ThreadID to) + { + detail::current_thread_id() = to; + } + + inline void reset_thread_id_generator(ThreadID to = MAIN_THREAD_ID) + { + detail::next_thread_id().store(to); + } +} diff --git a/src/ds/test/logger.cpp b/src/ds/test/logger.cpp index 42916f8981c8..ef33892cdde9 100644 --- a/src/ds/test/logger.cpp +++ b/src/ds/test/logger.cpp @@ -5,6 +5,29 @@ #define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN #include +#include + +TEST_CASE("Thread IDs are provided by the logger headers") +{ + ccf::threading::reset_thread_id_generator(); + ccf::threading::set_current_thread_id(ccf::threading::MAIN_THREAD_ID); + + REQUIRE( + ccf::threading::get_current_thread_id() == ccf::threading::MAIN_THREAD_ID); + + ccf::threading::set_current_thread_id(42); + REQUIRE(ccf::threading::get_current_thread_id() == 42); + + ccf::threading::reset_thread_id_generator(7); + ccf::threading::ThreadID thread_id = ccf::threading::invalid_thread_id; + std::thread t( + [&thread_id] { thread_id = ccf::threading::get_current_thread_id(); }); + t.join(); + REQUIRE(thread_id == 7); + + ccf::threading::reset_thread_id_generator(); + ccf::threading::set_current_thread_id(ccf::threading::MAIN_THREAD_ID); +} template class TestLogger : public Base diff --git a/src/enclave/thread_local.cpp b/src/enclave/thread_local.cpp deleted file mode 100644 index 23c8bdeda858..000000000000 --- a/src/enclave/thread_local.cpp +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the Apache 2.0 License. -#include "ccf/threading/thread_ids.h" - -namespace ccf::threading -{ - namespace - { - std::atomic next_thread_id = MAIN_THREAD_ID; - } - - uint16_t& current_thread_id() - { - thread_local ThreadID this_thread_id = next_thread_id.fetch_add(1); - return this_thread_id; - } - - uint16_t get_current_thread_id() - { - return current_thread_id(); - } - - void set_current_thread_id(ThreadID to) - { - current_thread_id() = to; - } - - void reset_thread_id_generator(ThreadID to) - { - next_thread_id.store(to); - } -} \ No newline at end of file diff --git a/tests/perf-system/submitter/CMakeLists.txt b/tests/perf-system/submitter/CMakeLists.txt index 2e3a67263fe9..0531bd650aa6 100644 --- a/tests/perf-system/submitter/CMakeLists.txt +++ b/tests/perf-system/submitter/CMakeLists.txt @@ -5,7 +5,6 @@ add_executable( ${SUBMITTER_DIR}/submit.cpp ${SUBMITTER_DIR}/handle_arguments.h ${SUBMITTER_DIR}/parquet_data.h - ${CCF_DIR}/src/enclave/thread_local.cpp ) add_warning_checks(submit) From e5f8f646da43c2accc4626a23ee9af38843139e6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 24 Jun 2026 21:30:17 +0000 Subject: [PATCH 03/10] Document header-only thread ID state Co-authored-by: achamayou <4016369+achamayou@users.noreply.github.com> --- include/ccf/threading/thread_ids.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/ccf/threading/thread_ids.h b/include/ccf/threading/thread_ids.h index ba021f55fa6e..d37ad91b8983 100644 --- a/include/ccf/threading/thread_ids.h +++ b/include/ccf/threading/thread_ids.h @@ -22,6 +22,11 @@ namespace ccf::threading namespace detail { + // These local statics keep thread ID state header-only, so users of logger + // do not need to link libccf for a separate implementation object. + // Resetting the generator only affects threads that initialise their + // thread-local ID after the reset; callers can use set_current_thread_id() + // for the current thread. inline std::atomic& next_thread_id() { static std::atomic next = MAIN_THREAD_ID; From aca4c8b2a0920d22aabf1eb55454b13378bb66db Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 25 Jun 2026 07:06:26 +0000 Subject: [PATCH 04/10] Move thread IDs into ccfcrypto Co-authored-by: achamayou <4016369+achamayou@users.noreply.github.com> --- cmake/crypto.cmake | 1 + include/ccf/threading/thread_ids.h | 38 +++--------------------------- src/threading/thread_ids.cpp | 34 ++++++++++++++++++++++++++ 3 files changed, 38 insertions(+), 35 deletions(-) create mode 100644 src/threading/thread_ids.cpp diff --git a/cmake/crypto.cmake b/cmake/crypto.cmake index 097f42efa7eb..d235f7a28bad 100644 --- a/cmake/crypto.cmake +++ b/cmake/crypto.cmake @@ -28,6 +28,7 @@ set( ${CCF_DIR}/src/crypto/openssl/cose_verifier.cpp ${CCF_DIR}/src/crypto/sharing.cpp ${CCF_DIR}/src/crypto/cbor.cpp + ${CCF_DIR}/src/threading/thread_ids.cpp ) find_library(CRYPTO_LIBRARY crypto) diff --git a/include/ccf/threading/thread_ids.h b/include/ccf/threading/thread_ids.h index d37ad91b8983..51b07c44e5fb 100644 --- a/include/ccf/threading/thread_ids.h +++ b/include/ccf/threading/thread_ids.h @@ -3,7 +3,6 @@ #pragma once #define FMT_HEADER_ONLY -#include #include #include #include @@ -20,38 +19,7 @@ namespace ccf::threading static constexpr ThreadID MAIN_THREAD_ID = 0; - namespace detail - { - // These local statics keep thread ID state header-only, so users of logger - // do not need to link libccf for a separate implementation object. - // Resetting the generator only affects threads that initialise their - // thread-local ID after the reset; callers can use set_current_thread_id() - // for the current thread. - inline std::atomic& next_thread_id() - { - static std::atomic next = MAIN_THREAD_ID; - return next; - } - - inline ThreadID& current_thread_id() - { - thread_local ThreadID current = next_thread_id().fetch_add(1); - return current; - } - } - - inline uint16_t get_current_thread_id() - { - return detail::current_thread_id(); - } - - inline void set_current_thread_id(ThreadID to) - { - detail::current_thread_id() = to; - } - - inline void reset_thread_id_generator(ThreadID to = MAIN_THREAD_ID) - { - detail::next_thread_id().store(to); - } + uint16_t get_current_thread_id(); + void set_current_thread_id(ThreadID to); + void reset_thread_id_generator(ThreadID to = MAIN_THREAD_ID); } diff --git a/src/threading/thread_ids.cpp b/src/threading/thread_ids.cpp new file mode 100644 index 000000000000..1bbf1b9f44d2 --- /dev/null +++ b/src/threading/thread_ids.cpp @@ -0,0 +1,34 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the Apache 2.0 License. +#include "ccf/threading/thread_ids.h" + +#include + +namespace ccf::threading +{ + namespace + { + std::atomic next_thread_id = MAIN_THREAD_ID; + + ThreadID& current_thread_id() + { + thread_local ThreadID this_thread_id = next_thread_id.fetch_add(1); + return this_thread_id; + } + } + + uint16_t get_current_thread_id() + { + return current_thread_id(); + } + + void set_current_thread_id(ThreadID to) + { + current_thread_id() = to; + } + + void reset_thread_id_generator(ThreadID to) + { + next_thread_id.store(to); + } +} From 025bba1f8278b8e4f6a75d5f47bcd3179027b992 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 26 Jun 2026 06:59:32 +0000 Subject: [PATCH 05/10] Fix ccf_tasks link dependency on ccfcrypto Co-authored-by: achamayou <4016369+achamayou@users.noreply.github.com> --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4bb04625c594..dc18c0c3e80a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -320,6 +320,7 @@ add_ccf_static_library( ${CCF_DIR}/src/tasks/fan_in_tasks.cpp ${CCF_DIR}/src/tasks/thread_manager.cpp ${CCF_DIR}/src/tasks/worker.cpp + LINK_LIBS ccfcrypto ) target_link_libraries(ccf_tasks PRIVATE ${CMAKE_DL_LIBS}) From 23efd65f1b33ba44707d24cd640072bed1761d69 Mon Sep 17 00:00:00 2001 From: Copilot <223556219+Copilot@users.noreply.github.com> Date: Fri, 10 Jul 2026 09:13:04 +0000 Subject: [PATCH 06/10] Extract thread-id support into a standalone ccf_threading library The logger headers (ccf/ds/logger.h) call ccf::threading::get_current_thread_id, whose definition previously lived in libccf. Low-level libraries such as ccfcrypto use the logger but are themselves dependencies of ccf, creating an implicit circular dependency that was worked around with a per-app linker flag and by compiling the thread-id source into individual test/bench/tool binaries. Move the implementation into a new ccf_threading static library (cmake/threading.cmake), linked publicly by ccfcrypto so every logger user resolves the symbol through it. Repoint ccf_tasks and ccf_kv - which use the logger but not crypto - to depend on ccf_threading directly instead of ccfcrypto. Bump the version to 7.0.8 and add a CHANGELOG entry describing the build-graph change for downstream consumers that link CCF component libraries directly. --- CHANGELOG.md | 9 +++++++++ CMakeLists.txt | 15 +++++---------- cmake/crypto.cmake | 3 +-- cmake/threading.cmake | 15 +++++++++++++++ python/pyproject.toml | 2 +- 5 files changed, 31 insertions(+), 13 deletions(-) create mode 100644 cmake/threading.cmake diff --git a/CHANGELOG.md b/CHANGELOG.md index c1cae74bbec7..edd4fc627372 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,15 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +## [7.0.8] + +[7.0.8]: https://github.com/microsoft/CCF/releases/tag/ccf-7.0.8 + +### Changed + +- **The framework logger no longer depends on `libccf`.** The thread-identifier helpers used by `ccf/ds/logger.h` (`ccf::threading::get_current_thread_id`, `set_current_thread_id`, and `reset_thread_id_generator`) have moved out of `libccf` into a new standalone `ccf_threading` static library, which `find_package(ccf)` exports automatically. This removes a long-standing implicit circular dependency in which low-level libraries such as `ccfcrypto` — themselves dependencies of `ccf` — required a symbol that was only defined in `ccf`, and the per-application linker workaround that force-resolved `get_current_thread_id` from `ccf` has been removed (#7977). +- **Build-graph change for consumers that link CCF component libraries directly.** `ccfcrypto` now links the new `ccf_threading` library, and `ccf_tasks` and `ccf_kv` link `ccf_threading` directly instead of `ccfcrypto`. Downstream targets that linked `ccf_tasks` or `ccf_kv` directly and relied on them transitively supplying CCF cryptography must now link `ccfcrypto` explicitly. Applications built with `add_ccf_app` (which link `ccf` and `ccf_launcher`) are unaffected (#7977). + ## [7.0.7] [7.0.7]: https://github.com/microsoft/CCF/releases/tag/ccf-7.0.7 diff --git a/CMakeLists.txt b/CMakeLists.txt index f1921c9162ee..c7204f6f53aa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -227,6 +227,7 @@ set( ) include(${CCF_DIR}/cmake/cose_openssl.cmake) +include(${CCF_DIR}/cmake/threading.cmake) include(${CCF_DIR}/cmake/crypto.cmake) include(${CCF_DIR}/cmake/quickjs.cmake) include(${CCF_DIR}/cmake/evercbor.cmake) @@ -299,6 +300,7 @@ add_ccf_static_library( ${CCF_DIR}/src/kv/tx.cpp ${CCF_DIR}/src/kv/untyped_map_handle.cpp ${CCF_DIR}/src/kv/untyped_map_diff.cpp + LINK_LIBS ccf_threading ) # CCF endpoints lib @@ -337,7 +339,7 @@ add_ccf_static_library( ${CCF_DIR}/src/tasks/fan_in_tasks.cpp ${CCF_DIR}/src/tasks/thread_manager.cpp ${CCF_DIR}/src/tasks/worker.cpp - LINK_LIBS ccfcrypto + LINK_LIBS ccf_threading ) find_library(BACKTRACE_LIBRARY backtrace) @@ -973,10 +975,7 @@ if(BUILD_TESTS) ) # Merkle Tree memory test - add_executable( - merkle_mem - src/node/test/merkle_mem.cpp - ) + add_executable(merkle_mem src/node/test/merkle_mem.cpp) add_warning_checks(merkle_mem) target_link_libraries( merkle_mem @@ -1047,11 +1046,7 @@ if(BUILD_TESTS) LINK_LIBS ccf_kv ccf_tasks ) - add_picobench( - kv_bench - SRCS src/kv/test/kv_bench.cpp - LINK_LIBS ccf_kv - ) + add_picobench(kv_bench SRCS src/kv/test/kv_bench.cpp LINK_LIBS ccf_kv) add_picobench(merkle_bench SRCS src/node/test/merkle_bench.cpp) add_picobench(hash_bench SRCS src/ds/test/hash_bench.cpp) diff --git a/cmake/crypto.cmake b/cmake/crypto.cmake index d235f7a28bad..1644f706a7cb 100644 --- a/cmake/crypto.cmake +++ b/cmake/crypto.cmake @@ -28,7 +28,6 @@ set( ${CCF_DIR}/src/crypto/openssl/cose_verifier.cpp ${CCF_DIR}/src/crypto/sharing.cpp ${CCF_DIR}/src/crypto/cbor.cpp - ${CCF_DIR}/src/threading/thread_ids.cpp ) find_library(CRYPTO_LIBRARY crypto) @@ -44,7 +43,7 @@ add_san(ccfcrypto) add_hardening(ccfcrypto) add_tidy(ccfcrypto) -target_link_libraries(ccfcrypto PUBLIC crypto ssl evercbor) +target_link_libraries(ccfcrypto PUBLIC crypto ssl evercbor ccf_threading) target_link_libraries( ccfcrypto PUBLIC diff --git a/cmake/threading.cmake b/cmake/threading.cmake new file mode 100644 index 000000000000..65e7480fdc1e --- /dev/null +++ b/cmake/threading.cmake @@ -0,0 +1,15 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the Apache 2.0 License. + +# Minimal foundational library owning the thread-id support that the logger +# headers depend on (ccf::threading::get_current_thread_id and friends). +# +# Keeping this in its own library lets every logger user resolve the symbol by +# depending on ccf_threading, without having to link libccf. This is what +# avoids the circular dependency tracked in +# https://github.com/microsoft/CCF/issues/7596: ccfcrypto (and the other +# low-level libraries) use the logger, but are themselves dependencies of ccf. +add_ccf_static_library( + ccf_threading + SRCS ${CCF_DIR}/src/threading/thread_ids.cpp +) diff --git a/python/pyproject.toml b/python/pyproject.toml index d1e6734c4903..3baeb3875cf6 100644 --- a/python/pyproject.toml +++ b/python/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "ccf" -version = "7.0.7" +version = "7.0.8" authors = [ { name="CCF Team", email="CCF-Sec@microsoft.com" }, ] From bc3e53ff8e6ecbfe1b86b10953a57a8ab59c780b Mon Sep 17 00:00:00 2001 From: Copilot <223556219+Copilot@users.noreply.github.com> Date: Fri, 10 Jul 2026 11:17:04 +0000 Subject: [PATCH 07/10] Fix CMake formatting --- cmake/common.cmake | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/cmake/common.cmake b/cmake/common.cmake index 08ed3513ca5d..9a2efd6117b7 100644 --- a/cmake/common.cmake +++ b/cmake/common.cmake @@ -256,10 +256,7 @@ function(add_picobench name) "SRCS;INCLUDE_DIRS;LINK_LIBS" ) - add_executable( - ${name} - ${PARSED_ARGS_SRCS} - ) + add_executable(${name} ${PARSED_ARGS_SRCS}) target_include_directories(${name} PRIVATE src ${PARSED_ARGS_INCLUDE_DIRS}) From f2e6fa3d6431ea76b6f50afba5ab56024ed4b728 Mon Sep 17 00:00:00 2001 From: Amaury Chamayou Date: Fri, 10 Jul 2026 13:53:03 +0100 Subject: [PATCH 08/10] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 317dbb94da01..dfcb686b28ef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,7 +13,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - The node join protocol client now uses the curl multi singleton client (introduced in #7102) instead of the legacy enclave `RPCSessions::create_client()` HTTP client, matching the JWT refresh and snapshot-fetch clients. The service certificate remains the sole trust anchor for the join connection (the host certificate store is never consulted) (#8040). - **Node joins now check the target RPC address against the target node's certificate SANs.** TLS certificate hostname verification (`CURLOPT_SSL_VERIFYHOST`) is now enforced on the join connection: the host in `join.target_rpc_address` must be covered by one of the target node's certificate Subject Alternative Names (SANs), and a join to an address absent from the target's SANs is now rejected (the previous join client did not check the target certificate name at all). CCF derives node-certificate SANs from `node_certificate.subject_alt_names`, or by default from each RPC interface's `published_address`, so standard deployments are unaffected; operators that configure a bespoke `join.target_rpc_address` must ensure it is present in the target node's certificate SANs (#8040). -- **The framework logger no longer depends on `libccf`.** The thread-identifier helpers used by `ccf/ds/logger.h` (`ccf::threading::get_current_thread_id`, `set_current_thread_id`, and `reset_thread_id_generator`) have moved out of `libccf` into a new standalone `ccf_threading` static library, which `find_package(ccf)` exports automatically. This removes a long-standing implicit circular dependency in which low-level libraries such as `ccfcrypto` — themselves dependencies of `ccf` — required a symbol that was only defined in `ccf`, and the per-application linker workaround that force-resolved `get_current_thread_id` from `ccf` has been removed (#7977). +- **The framework logger no longer depends on `libccf`.** The thread-identifier helpers used by `ccf/ds/logger.h` (`ccf::threading::get_current_thread_id`, `set_current_thread_id`, and `reset_thread_id_generator`) have moved out of `libccf` into a new standalone `ccf_threading` static library, which `find_package(ccf)` exports automatically. This removes a long-standing implicit circular dependency in which low-level libraries such as `ccfcrypto` -- themselves dependencies of `ccf` -- required a symbol that was only defined in `ccf`, and the per-application linker workaround that force-resolved `get_current_thread_id` from `ccf` has been removed (#7977). - **Build-graph change for consumers that link CCF component libraries directly.** `ccfcrypto` now links the new `ccf_threading` library, and `ccf_tasks` and `ccf_kv` link `ccf_threading` directly instead of `ccfcrypto`. Downstream targets that linked `ccf_tasks` or `ccf_kv` directly and relied on them transitively supplying CCF cryptography must now link `ccfcrypto` explicitly. Applications built with `add_ccf_app` (which link `ccf` and `ccf_launcher`) are unaffected (#7977). ### Removed From 0188ce34e7c3cc712a23d29441d5a212bf9f8f54 Mon Sep 17 00:00:00 2001 From: Amaury Chamayou <4016369+achamayou@users.noreply.github.com> Date: Fri, 10 Jul 2026 21:30:42 +0000 Subject: [PATCH 09/10] Move logger changelog entries to 7.0.10 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 80bad87c53a8..e6cec44ad51b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Fixed - HTTP query parameters are now split before URL-decoding, so escaped ampersands in query parameter names and values are preserved correctly (#8024). +- **The framework logger no longer depends on `libccf`.** The thread-identifier helpers used by `ccf/ds/logger.h` (`ccf::threading::get_current_thread_id`, `set_current_thread_id`, and `reset_thread_id_generator`) have moved out of `libccf` into a new standalone `ccf_threading` static library, which `find_package(ccf)` exports automatically. This removes a long-standing implicit circular dependency in which low-level libraries such as `ccfcrypto` -- themselves dependencies of `ccf` -- required a symbol that was only defined in `ccf`, and the per-application linker workaround that force-resolved `get_current_thread_id` from `ccf` has been removed (#7977). +- **Build-graph change for consumers that link CCF component libraries directly.** `ccfcrypto` now links the new `ccf_threading` library, and `ccf_tasks` and `ccf_kv` link `ccf_threading` directly instead of `ccfcrypto`. Downstream targets that linked `ccf_tasks` or `ccf_kv` directly and relied on them transitively supplying CCF cryptography must now link `ccfcrypto` explicitly. Applications built with `add_ccf_app` (which link `ccf` and `ccf_launcher`) are unaffected (#7977). ## [7.0.9] @@ -34,8 +36,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - The node join protocol client now uses the curl multi singleton client (introduced in #7102) instead of the legacy enclave `RPCSessions::create_client()` HTTP client, matching the JWT refresh and snapshot-fetch clients. The service certificate remains the sole trust anchor for the join connection (the host certificate store is never consulted) (#8040). - **Node joins now check the target RPC address against the target node's certificate SANs.** TLS certificate hostname verification (`CURLOPT_SSL_VERIFYHOST`) is now enforced on the join connection: the host in `join.target_rpc_address` must be covered by one of the target node's certificate Subject Alternative Names (SANs), and a join to an address absent from the target's SANs is now rejected (the previous join client did not check the target certificate name at all). CCF derives node-certificate SANs from `node_certificate.subject_alt_names`, or by default from each RPC interface's `published_address`, so standard deployments are unaffected; operators that configure a bespoke `join.target_rpc_address` must ensure it is present in the target node's certificate SANs (#8040). -- **The framework logger no longer depends on `libccf`.** The thread-identifier helpers used by `ccf/ds/logger.h` (`ccf::threading::get_current_thread_id`, `set_current_thread_id`, and `reset_thread_id_generator`) have moved out of `libccf` into a new standalone `ccf_threading` static library, which `find_package(ccf)` exports automatically. This removes a long-standing implicit circular dependency in which low-level libraries such as `ccfcrypto` -- themselves dependencies of `ccf` -- required a symbol that was only defined in `ccf`, and the per-application linker workaround that force-resolved `get_current_thread_id` from `ccf` has been removed (#7977). -- **Build-graph change for consumers that link CCF component libraries directly.** `ccfcrypto` now links the new `ccf_threading` library, and `ccf_tasks` and `ccf_kv` link `ccf_threading` directly instead of `ccfcrypto`. Downstream targets that linked `ccf_tasks` or `ccf_kv` directly and relied on them transitively supplying CCF cryptography must now link `ccfcrypto` explicitly. Applications built with `add_ccf_app` (which link `ccf` and `ccf_launcher`) are unaffected (#7977). ### Removed From b2dc363465f6532baf58dec85e8296f1a2635770 Mon Sep 17 00:00:00 2001 From: Amaury Chamayou Date: Mon, 13 Jul 2026 18:13:56 +0100 Subject: [PATCH 10/10] Apply suggestions from code review Co-authored-by: Amaury Chamayou --- CHANGELOG.md | 2 +- cmake/threading.cmake | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e6cec44ad51b..16cd17dbf8ee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,7 +17,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Fixed - HTTP query parameters are now split before URL-decoding, so escaped ampersands in query parameter names and values are preserved correctly (#8024). -- **The framework logger no longer depends on `libccf`.** The thread-identifier helpers used by `ccf/ds/logger.h` (`ccf::threading::get_current_thread_id`, `set_current_thread_id`, and `reset_thread_id_generator`) have moved out of `libccf` into a new standalone `ccf_threading` static library, which `find_package(ccf)` exports automatically. This removes a long-standing implicit circular dependency in which low-level libraries such as `ccfcrypto` -- themselves dependencies of `ccf` -- required a symbol that was only defined in `ccf`, and the per-application linker workaround that force-resolved `get_current_thread_id` from `ccf` has been removed (#7977). +- The thread-identifier helpers used by `ccf/ds/logger.h` (`ccf::threading::get_current_thread_id`, `set_current_thread_id`, and `reset_thread_id_generator`) have moved out of `libccf` into a new standalone `ccf_threading` static library, which `find_package(ccf)` exports automatically. This removes a long-standing implicit circular dependency (#7977). - **Build-graph change for consumers that link CCF component libraries directly.** `ccfcrypto` now links the new `ccf_threading` library, and `ccf_tasks` and `ccf_kv` link `ccf_threading` directly instead of `ccfcrypto`. Downstream targets that linked `ccf_tasks` or `ccf_kv` directly and relied on them transitively supplying CCF cryptography must now link `ccfcrypto` explicitly. Applications built with `add_ccf_app` (which link `ccf` and `ccf_launcher`) are unaffected (#7977). ## [7.0.9] diff --git a/cmake/threading.cmake b/cmake/threading.cmake index 65e7480fdc1e..0fa5a144e1a5 100644 --- a/cmake/threading.cmake +++ b/cmake/threading.cmake @@ -5,10 +5,7 @@ # headers depend on (ccf::threading::get_current_thread_id and friends). # # Keeping this in its own library lets every logger user resolve the symbol by -# depending on ccf_threading, without having to link libccf. This is what -# avoids the circular dependency tracked in -# https://github.com/microsoft/CCF/issues/7596: ccfcrypto (and the other -# low-level libraries) use the logger, but are themselves dependencies of ccf. +# depending on ccf_threading, without having to link libccf. add_ccf_static_library( ccf_threading SRCS ${CCF_DIR}/src/threading/thread_ids.cpp