From f5b2256dadf70ab991316acecb6f722eececdd8a Mon Sep 17 00:00:00 2001 From: Amaury Chamayou Date: Thu, 4 Dec 2025 10:02:40 +0000 Subject: [PATCH 01/18] Tidy src/http headers --- .clang-tidy | 2 +- src/http/curl.h | 30 +++++++------ src/http/error_reporter.h | 2 +- src/http/http2_callbacks.h | 24 +++++------ src/http/http2_parser.h | 31 +++++++------ src/http/http2_session.h | 42 +++++++++--------- src/http/http2_types.h | 14 +++--- src/http/http2_utils.h | 10 +++-- src/http/http_builder.h | 47 ++++++++++---------- src/http/http_exceptions.h | 2 +- src/http/http_jwt.h | 8 ++-- src/http/http_parser.h | 50 +++++++++++++-------- src/http/http_proc.h | 4 ++ src/http/http_rpc_context.h | 86 +++++++++++++++++++------------------ src/http/http_session.h | 40 ++++++++--------- src/kv/kv_types.h | 5 --- 16 files changed, 209 insertions(+), 188 deletions(-) diff --git a/.clang-tidy b/.clang-tidy index 67090674a886..cc5646a59e1e 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -59,5 +59,5 @@ Checks: > -readability-magic-numbers, WarningsAsErrors: '*' -HeaderFilterRegex: '(include\/ccf\/|src\/(udp|tcp|tls|tasks|snapshots|service|quic|pal|apps|clients|common|consensus|ds|enclave|endpoints|host|indexing)\/).*' +HeaderFilterRegex: '(include\/ccf\/|src\/(udp|tcp|tls|tasks|snapshots|service|quic|pal|apps|clients|common|consensus|ds|enclave|endpoints|host|indexing|http)\/).*' FormatStyle: 'file' \ No newline at end of file diff --git a/src/http/curl.h b/src/http/curl.h index 0b953372244f..34f7f90f073d 100644 --- a/src/http/curl.h +++ b/src/http/curl.h @@ -189,7 +189,7 @@ namespace ccf::curl unsent = std::span(buffer.data(), buffer.size()); } - RequestBody(std::vector&& buffer) : buffer(std::move(buffer)) + RequestBody(std::vector&& buffer_) : buffer(std::move(buffer_)) { unsent = std::span(buffer.data(), buffer.size()); } @@ -242,7 +242,7 @@ namespace ccf::curl ResponseBody(size_t max_size_) : maximum_size(max_size_) {} static size_t write_response_chunk( - uint8_t* ptr, size_t size, size_t nmemb, ResponseBody* response) + const uint8_t* ptr, size_t size, size_t nmemb, ResponseBody* response) { if (response == nullptr) { @@ -275,7 +275,7 @@ namespace ccf::curl } static size_t noop_write_function( - uint8_t* ptr, size_t size, size_t nmemb, ResponseBody* response) + const uint8_t* ptr, size_t size, size_t nmemb, ResponseBody* response) { (void)ptr; (void)response; @@ -392,7 +392,7 @@ namespace ccf::curl CurlRequest( UniqueCURL&& curl_handle_, RESTVerb method_, - const std::string& url_, + std::string url_, UniqueSlist&& headers_, std::unique_ptr&& request_body_, std::unique_ptr&& response_, @@ -411,13 +411,14 @@ namespace ccf::curl } CHECK_CURL_EASY_SETOPT(curl_handle, CURLOPT_URL, url.c_str()); - if (!method.get_http_method().has_value()) + auto http_method = method.get_http_method(); + if (!http_method.has_value()) { throw std::logic_error( fmt::format("Unsupported HTTP method: {}", method.c_str())); } - switch (method.get_http_method().value()) + switch (http_method.value()) { case HTTP_GET: CHECK_CURL_EASY_SETOPT(curl_handle, CURLOPT_HTTPGET, 1L); @@ -475,11 +476,15 @@ namespace ccf::curl LOG_TRACE_FMT("Handling response for {}", request->url); if (request->response_callback.has_value()) { - long status_code = 0; - CHECK_CURL_EASY_GETINFO( - request->curl_handle, CURLINFO_RESPONSE_CODE, &status_code); - request->response_callback.value()( - std::move(request), curl_response_code, status_code); + // NOLINTNEXTLINE(bugprone-unchecked-optional-access) + auto& callback = *request->response_callback; + if (callback != nullptr) + { + long status_code = 0; + CHECK_CURL_EASY_GETINFO( + request->curl_handle, CURLINFO_RESPONSE_CODE, &status_code); + callback(std::move(request), curl_response_code, status_code); + } } } @@ -955,7 +960,8 @@ namespace ccf::curl // remove, stop and cleanup all curl easy handles std::unique_ptr easy_handles( curl_multi_get_handles(curl_request_curlm), - [](CURL** handles) { curl_free(handles); }); + // NOLINTNEXTLINE(bugprone-multi-level-implicit-pointer-conversion) + [](CURL** handles) { curl_free(static_cast(handles)); }); // curl_multi_get_handles returns the handles as a null-terminated array for (size_t i = 0; easy_handles.get()[i] != nullptr; ++i) { diff --git a/src/http/error_reporter.h b/src/http/error_reporter.h index b79a32c2390d..6609ed4ec03b 100644 --- a/src/http/error_reporter.h +++ b/src/http/error_reporter.h @@ -7,7 +7,7 @@ namespace http class ErrorReporter { public: - virtual ~ErrorReporter() {} + virtual ~ErrorReporter() = default; virtual void report_parsing_error(const ccf::ListenInterfaceID&) = 0; virtual void report_request_payload_too_large_error( const ccf::ListenInterfaceID&) = 0; diff --git a/src/http/http2_callbacks.h b/src/http/http2_callbacks.h index 487ce3cff15d..f9f85caa622f 100644 --- a/src/http/http2_callbacks.h +++ b/src/http/http2_callbacks.h @@ -16,8 +16,8 @@ namespace http2 uint8_t* buf, size_t length, uint32_t* data_flags, - nghttp2_data_source* source, - void* user_data) + nghttp2_data_source* /*source*/, + void* /*user_data*/) { auto* stream_data = get_stream_data(session, stream_id); if (stream_data->outgoing.state == StreamResponseState::Uninitialised) @@ -64,7 +64,7 @@ namespace http2 } static int on_begin_frame_recv_callback( - nghttp2_session* session, const nghttp2_frame_hd* hd, void* user_data) + nghttp2_session* /*session*/, const nghttp2_frame_hd* hd, void* user_data) { const auto& stream_id = hd->stream_id; LOG_TRACE_FMT( @@ -124,7 +124,7 @@ namespace http2 } // If the request is complete, process it - if (frame->hd.flags & NGHTTP2_FLAG_END_STREAM) + if ((frame->hd.flags & NGHTTP2_FLAG_END_STREAM) != 0) { auto* p = get_parser(user_data); p->handle_completed(stream_id, stream_data); @@ -176,7 +176,7 @@ namespace http2 size_t namelen, const uint8_t* value, size_t valuelen, - uint8_t flags, + uint8_t /*flags*/, void* user_data) { const auto& stream_id = frame->hd.stream_id; @@ -227,7 +227,7 @@ namespace http2 static int on_data_callback( nghttp2_session* session, - uint8_t flags, + uint8_t /*flags*/, StreamId stream_id, const uint8_t* data, size_t len, @@ -257,7 +257,7 @@ namespace http2 } static int on_stream_close_callback( - nghttp2_session* session, + nghttp2_session* /*session*/, StreamId stream_id, uint32_t error_code, void* user_data) @@ -272,8 +272,8 @@ namespace http2 } static ssize_t on_data_source_read_length_callback( - nghttp2_session* session, - uint8_t frame_type, + nghttp2_session* /*session*/, + uint8_t /*frame_type*/, int32_t stream_id, int32_t session_remote_window_size, int32_t stream_remote_window_size, @@ -298,11 +298,11 @@ namespace http2 } static int on_error_callback( - nghttp2_session* session, - int lib_error_code, + nghttp2_session* /*session*/, + int /*lib_error_code*/, const char* msg, size_t len, - void* user_data) + void* /*user_data*/) { LOG_DEBUG_FMT("HTTP/2 error: {}", std::string(msg, msg + len)); return 0; diff --git a/src/http/http2_parser.h b/src/http/http2_parser.h index 07af1c609ce5..813c183a9edd 100644 --- a/src/http/http2_parser.h +++ b/src/http/http2_parser.h @@ -25,17 +25,16 @@ namespace http2 protected: std::map> streams; - nghttp2_session* session; + nghttp2_session* session = nullptr; public: Parser( - const ccf::http::ParserConfiguration& configuration_, - bool is_client = false) : - configuration(configuration_) + ccf::http::ParserConfiguration configuration_, bool is_client = false) : + configuration(std::move(configuration_)) { LOG_TRACE_FMT("Creating HTTP2 parser"); - nghttp2_session_callbacks* callbacks; + nghttp2_session_callbacks* callbacks = nullptr; nghttp2_session_callbacks_new(&callbacks); nghttp2_session_callbacks_set_on_stream_close_callback( callbacks, on_stream_close_callback); @@ -107,17 +106,18 @@ namespace http2 nghttp2_session_callbacks_del(callbacks); } - virtual ~Parser() + ~Parser() override { nghttp2_session_del(session); } - StreamId get_last_stream_id() const override + [[nodiscard]] StreamId get_last_stream_id() const override { return last_stream_id; } - ccf::http::ParserConfiguration get_configuration() const override + [[nodiscard]] ccf::http::ParserConfiguration get_configuration() + const override { return configuration; } @@ -274,17 +274,16 @@ namespace http2 std::vector hdrs = {}; auto status_str = fmt::format( - "{}", - static_cast::type>(status)); + "{}", static_cast>(status)); hdrs.emplace_back( make_nv(ccf::http2::headers::STATUS, status_str.data())); - for (auto& [k, v] : base_headers) + for (const auto& [k, v] : base_headers) { hdrs.emplace_back(make_nv(k.data(), v.data())); } - for (auto& [k, v] : extra_headers) + for (const auto& [k, v] : extra_headers) { hdrs.emplace_back(make_nv(k.data(), v.data())); } @@ -457,8 +456,7 @@ namespace http2 // trailers } - virtual void handle_completed( - StreamId stream_id, StreamData* stream_data) override + void handle_completed(StreamId stream_id, StreamData* stream_data) override { LOG_TRACE_FMT("http2::ServerParser: handle_completed"); @@ -484,7 +482,7 @@ namespace http2 const auto method_it = headers.find(ccf::http2::headers::METHOD); if (method_it != headers.end()) { - method = ccf::http_method_from_str(method_it->second.c_str()); + method = ccf::http_method_from_str(method_it->second); } } @@ -548,7 +546,8 @@ namespace http2 LOG_DEBUG_FMT("Successfully sent request with stream id: {}", stream_id); } - void handle_completed(StreamId stream_id, StreamData* stream_data) override + void handle_completed( + StreamId /*stream_id*/, StreamData* stream_data) override { LOG_TRACE_FMT("http2::ClientParser: handle_completed"); diff --git a/src/http/http2_session.h b/src/http/http2_session.h index e54e50e778b2..ac0cb5a8354f 100644 --- a/src/http/http2_session.h +++ b/src/http/http2_session.h @@ -61,7 +61,7 @@ namespace http sp->respond( stream_id, status_code, - std::move(headers), + headers, std::move(trailers), std::move(body)); } @@ -200,10 +200,9 @@ namespace http { it = session_ctxs.emplace_hint( it, - std::make_pair( - stream_id, - std::make_shared( - session_id, tls_io->peer_cert(), interface_id, stream_id))); + stream_id, + std::make_shared( + session_id, tls_io->peer_cert(), interface_id, stream_id)); } return it->second; @@ -226,8 +225,8 @@ namespace http void respond_with_error( http2::StreamId stream_id, const ccf::ErrorDetails& error) { - nlohmann::json body = ccf::ODataErrorResponse{ - ccf::ODataError{std::move(error.code), std::move(error.msg), {}}}; + nlohmann::json body = + ccf::ODataErrorResponse{ccf::ODataError{error.code, error.msg, {}}}; const std::string s = body.dump(); std::vector v(s.begin(), s.end()); @@ -241,19 +240,19 @@ namespace http public: HTTP2ServerSession( - std::shared_ptr rpc_map, + std::shared_ptr rpc_map_, int64_t session_id_, - const ccf::ListenInterfaceID& interface_id, + ccf::ListenInterfaceID interface_id_, ringbuffer::AbstractWriterFactory& writer_factory, std::unique_ptr ctx, const ccf::http::ParserConfiguration& configuration, - const std::shared_ptr& error_reporter) : + const std::shared_ptr& error_reporter_) : HTTP2Session(session_id_, writer_factory, std::move(ctx)), server_parser( std::make_shared(*this, configuration)), - rpc_map(rpc_map), - error_reporter(error_reporter), - interface_id(interface_id) + rpc_map(std::move(rpc_map_)), + error_reporter(error_reporter_), + interface_id(std::move(interface_id_)) { server_parser->set_outgoing_data_handler( [this](std::span data) { @@ -375,14 +374,12 @@ namespace http LOG_TRACE_FMT("Pending"); return; } - else - { - responder->send_response( - rpc_ctx->get_response_http_status(), - rpc_ctx->get_response_headers(), - rpc_ctx->get_response_trailers(), - std::move(rpc_ctx->take_response_body())); - } + + responder->send_response( + rpc_ctx->get_response_http_status(), + rpc_ctx->get_response_headers(), + rpc_ctx->get_response_trailers(), + std::move(rpc_ctx->take_response_body())); } catch (const std::exception& e) { @@ -478,7 +475,8 @@ namespace http LOG_DEBUG_FMT( "Error occurred while parsing fragment {} byte fragment:\n{}", data.size(), - std::string_view((char const*)data.data(), data.size())); + std::string_view( + reinterpret_cast(data.data()), data.size())); close_session(); } diff --git a/src/http/http2_types.h b/src/http/http2_types.h index f8f845bb6c67..317ae3a9ad83 100644 --- a/src/http/http2_types.h +++ b/src/http/http2_types.h @@ -24,7 +24,7 @@ namespace http2 // Used to keep track of response state between nghttp2 callbacks and to // differentiate unary from streaming responses - enum class StreamResponseState + enum class StreamResponseState : uint8_t { Uninitialised = 0, // No response to send yet Closing, // Unary or last frame in stream @@ -36,14 +36,11 @@ namespace http2 // Utility class to consume data from underlying data vector in chunks from // nghttp2_data_source_read_callback std::vector data; - size_t consumed; + size_t consumed = 0; DataSource() = default; - DataSource(std::vector&& data_) : - data(std::move(data_)), - consumed(0) - {} + DataSource(std::vector&& data_) : data(std::move(data_)) {} }; struct StreamData @@ -75,7 +72,8 @@ namespace http2 virtual std::shared_ptr create_stream(StreamId stream_id) = 0; virtual std::shared_ptr get_stream(StreamId stream_id) = 0; virtual void destroy_stream(StreamId stream_id) = 0; - virtual StreamId get_last_stream_id() const = 0; - virtual ccf::http::ParserConfiguration get_configuration() const = 0; + [[nodiscard]] virtual StreamId get_last_stream_id() const = 0; + [[nodiscard]] virtual ccf::http::ParserConfiguration get_configuration() + const = 0; }; } \ No newline at end of file diff --git a/src/http/http2_utils.h b/src/http/http2_utils.h index e1ad5f21b51a..362b5c3095ba 100644 --- a/src/http/http2_utils.h +++ b/src/http/http2_utils.h @@ -17,14 +17,16 @@ namespace http2 return { const_cast(key), const_cast(value), - strlen((char*)key), - strlen((char*)value), + strlen(reinterpret_cast(key)), + strlen(reinterpret_cast(value)), NGHTTP2_NV_FLAG_NONE}; } static inline nghttp2_nv make_nv(const char* key, const char* value) { - return make_nv((uint8_t*)key, (uint8_t*)value); + return make_nv( + reinterpret_cast(key), + reinterpret_cast(value)); } static inline AbstractParser* get_parser(void* user_data) @@ -43,7 +45,7 @@ namespace http2 using HeaderKeysIt = ccf::nonstd::KeyIterator; - const auto trailer_header_val = fmt::format( + auto trailer_header_val = fmt::format( "{}", fmt::join( HeaderKeysIt(trailers.begin()), HeaderKeysIt(trailers.end()), ",")); diff --git a/src/http/http_builder.h b/src/http/http_builder.h index b0380e1a6834..053956870c11 100644 --- a/src/http/http_builder.h +++ b/src/http/http_builder.h @@ -37,7 +37,7 @@ namespace http Message() = default; public: - const ccf::http::HeaderMap& get_headers() const + [[nodiscard]] const ccf::http::HeaderMap& get_headers() const { return headers; } @@ -54,19 +54,17 @@ namespace http headers.clear(); } - size_t get_content_length() const + [[nodiscard]] size_t get_content_length() const { if (body == nullptr) { return 0; } - else - { - return body_size; - } + + return body_size; } - const uint8_t* get_content_data() const + [[nodiscard]] const uint8_t* get_content_data() const { return body; } @@ -101,7 +99,8 @@ namespace http void set_body(const std::string& s, bool overwrite_content_length = true) { - body = (uint8_t*)s.data(); + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) + body = reinterpret_cast(s.data()); body_size = s.size(); if ( @@ -119,11 +118,10 @@ namespace http private: llhttp_method method; std::string path = "/"; - std::map query_params = {}; + std::map query_params; public: Request(const std::string_view& p = "/", llhttp_method m = HTTP_POST) : - Message(), method(m) { set_path(p); @@ -134,14 +132,14 @@ namespace http method = m; } - llhttp_method get_method() const + [[nodiscard]] llhttp_method get_method() const { return method; } void set_path(const std::string_view& p) { - if (p.size() > 0 && p[0] == '/') + if (!p.empty() && p[0] == '/') { path = p; } @@ -151,7 +149,7 @@ namespace http } } - std::string get_path() const + [[nodiscard]] std::string get_path() const { return path; } @@ -161,7 +159,7 @@ namespace http query_params[k] = v; } - std::string get_formatted_query() const + [[nodiscard]] std::string get_formatted_query() const { std::string formatted_query; bool first = true; @@ -174,13 +172,15 @@ namespace http return formatted_query; } - std::vector build_request(bool header_only = false) const + [[nodiscard]] std::vector build_request( + bool header_only = false) const { const auto uri = fmt::format("{}{}", path, get_formatted_query()); const auto body_view = (header_only || body == nullptr) ? std::string_view() : - std::string_view((char const*)body, body_size); + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) + std::string_view(reinterpret_cast(body), body_size); const auto request_string = fmt::format( "{} {} HTTP/1.1\r\n" @@ -192,7 +192,7 @@ namespace http get_header_string(headers), body_view); - return std::vector(request_string.begin(), request_string.end()); + return {request_string.begin(), request_string.end()}; } }; @@ -204,11 +204,13 @@ namespace http public: Response(ccf::http_status s = HTTP_STATUS_OK) : status(s) {} - std::vector build_response(bool header_only = false) const + [[nodiscard]] std::vector build_response( + bool header_only = false) const { const auto body_view = (header_only || body == nullptr) ? std::string_view() : - std::string_view((char const*)body, body_size); + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) + std::string_view(reinterpret_cast(body), body_size); const auto response_string = fmt::format( "HTTP/1.1 {} {}\r\n" @@ -220,12 +222,9 @@ namespace http get_header_string(headers), body_view); - return std::vector( - response_string.begin(), response_string.end()); + return {response_string.begin(), response_string.end()}; } - }; - -// Most builder function are unused from enclave + }; // Most builder function are unused from enclave #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunused-function" diff --git a/src/http/http_exceptions.h b/src/http/http_exceptions.h index 129a586b72bc..a7e1d0dde1d7 100644 --- a/src/http/http_exceptions.h +++ b/src/http/http_exceptions.h @@ -21,7 +21,7 @@ namespace http stream_id(stream_id) {} - http2::StreamId get_stream_id() const + [[nodiscard]] http2::StreamId get_stream_id() const { return stream_id; } diff --git a/src/http/http_jwt.h b/src/http/http_jwt.h index 580ba5c6757b..2eee1d8c176d 100644 --- a/src/http/http_jwt.h +++ b/src/http/http_jwt.h @@ -14,7 +14,7 @@ namespace http { - enum class JwtCryptoAlgorithm + enum class JwtCryptoAlgorithm : uint8_t { RS256, ES256, @@ -26,7 +26,7 @@ namespace http struct JwtHeader { - JwtCryptoAlgorithm alg; + JwtCryptoAlgorithm alg{}; std::string kid; }; DECLARE_JSON_TYPE(JwtHeader) @@ -34,7 +34,7 @@ namespace http struct JwtPayload { - size_t exp; + size_t exp{}; std::string iss; std::optional nbf; std::optional tid; @@ -59,7 +59,7 @@ namespace http static bool parse_auth_scheme( std::string_view& auth_header_value, std::string& error_reason) { - auto next_space = auth_header_value.find(" "); + auto next_space = auth_header_value.find(' '); if (next_space == std::string::npos) { error_reason = "Authorization header only contains one field"; diff --git a/src/http/http_parser.h b/src/http/http_parser.h index c4ea34dba0aa..2e1c62ecc933 100644 --- a/src/http/http_parser.h +++ b/src/http/http_parser.h @@ -48,7 +48,9 @@ namespace http while (src < end) { char const c = *src++; - if (c == '%' && (src + 1) < end && isxdigit(src[0]) && isxdigit(src[1])) + if ( + c == '%' && (src + 1) < end && (isxdigit(src[0]) != 0) && + (isxdigit(src[1]) != 0)) { const auto a = ccf::ds::hex_char_to_int(*src++); const auto b = ccf::ds::hex_char_to_int(*src++); @@ -76,6 +78,8 @@ namespace http struct SimpleRequestProcessor : public http::RequestProcessor { public: + ~SimpleRequestProcessor() override = default; + struct Request { llhttp_method method; @@ -86,12 +90,12 @@ namespace http std::queue received; - virtual void handle_request( + void handle_request( llhttp_method method, const std::string_view& url, ccf::http::HeaderMap&& headers, std::vector&& body, - int32_t) override + int32_t /*stream_id*/) override { received.emplace(Request{method, std::string(url), headers, body}); } @@ -100,6 +104,8 @@ namespace http struct SimpleResponseProcessor : public ::http::ResponseProcessor { public: + ~SimpleResponseProcessor() override = default; + struct Response { ccf::http_status status; @@ -109,7 +115,7 @@ namespace http std::queue received; - virtual void handle_response( + void handle_response( ccf::http_status status, ccf::http::HeaderMap&& headers, std::vector&& body) override @@ -118,7 +124,7 @@ namespace http } }; - enum State + enum State : uint8_t { DONE, IN_MESSAGE @@ -180,6 +186,9 @@ namespace http class Parser { + public: + virtual ~Parser() = default; + protected: llhttp_t parser; llhttp_settings_t settings; @@ -189,7 +198,7 @@ namespace http std::vector body_buf; ccf::http::HeaderMap headers; - std::pair partial_parsed_header = {}; + std::pair partial_parsed_header; void complete_header() { @@ -200,9 +209,11 @@ namespace http Parser( llhttp_type_t type, - const ccf::http::ParserConfiguration& config = + ccf::http::ParserConfiguration config = ccf::http::ParserConfiguration{}) : - configuration(config) + parser{}, + settings{}, + configuration(std::move(config)) { llhttp_settings_init(&settings); @@ -220,7 +231,8 @@ namespace http public: void execute(const uint8_t* data, size_t size) { - const auto data_char = (const char*)data; + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) + const auto* const data_char = reinterpret_cast(data); auto err_no = llhttp_execute(&parser, data_char, size); if (err_no == HPE_PAUSED_UPGRADE) @@ -349,42 +361,42 @@ namespace http static int on_msg_begin(llhttp_t* parser) { - Parser* p = reinterpret_cast(parser->data); + auto* p = reinterpret_cast(parser->data); p->new_message(); return HPE_OK; } static int on_header_field(llhttp_t* parser, const char* at, size_t length) { - Parser* p = reinterpret_cast(parser->data); + auto* p = reinterpret_cast(parser->data); p->header_field(at, length); return HPE_OK; } static int on_header_value(llhttp_t* parser, const char* at, size_t length) { - Parser* p = reinterpret_cast(parser->data); + auto* p = reinterpret_cast(parser->data); p->header_value(at, length); return HPE_OK; } static int on_headers_complete(llhttp_t* parser) { - Parser* p = reinterpret_cast(parser->data); + auto* p = reinterpret_cast(parser->data); p->headers_complete(); return HPE_OK; } static int on_body(llhttp_t* parser, const char* at, size_t length) { - Parser* p = reinterpret_cast(parser->data); + auto* p = reinterpret_cast(parser->data); p->append_body(at, length); return HPE_OK; } static int on_msg_end(llhttp_t* parser) { - Parser* p = reinterpret_cast(parser->data); + auto* p = reinterpret_cast(parser->data); p->end_message(); return HPE_OK; } @@ -395,9 +407,11 @@ namespace http private: RequestProcessor& proc; - std::string url = ""; + std::string url; public: + ~RequestParser() override = default; + RequestParser( RequestProcessor& proc_, const ccf::http::ParserConfiguration& config = @@ -442,7 +456,7 @@ namespace http static int on_url(llhttp_t* parser, const char* at, size_t length) { - RequestParser* p = reinterpret_cast(parser->data); + auto* p = reinterpret_cast(parser->data); p->append_url(at, length); return HPE_OK; } @@ -454,6 +468,8 @@ namespace http ResponseProcessor& proc; public: + ~ResponseParser() override = default; + ResponseParser(ResponseProcessor& proc_) : Parser(HTTP_RESPONSE, ccf::http::ParserConfiguration{}), proc(proc_) diff --git a/src/http/http_proc.h b/src/http/http_proc.h index 273306d9be56..74e93e3f2c4e 100644 --- a/src/http/http_proc.h +++ b/src/http/http_proc.h @@ -19,6 +19,8 @@ namespace http class RequestProcessor { public: + virtual ~RequestProcessor() = default; + virtual void handle_request( llhttp_method method, const std::string_view& url, @@ -30,6 +32,8 @@ namespace http class ResponseProcessor { public: + virtual ~ResponseProcessor() = default; + virtual void handle_response( ccf::http_status status, ccf::http::HeaderMap&& headers, diff --git a/src/http/http_rpc_context.h b/src/http/http_rpc_context.h index 9de326d4643a..097aa28aa96e 100644 --- a/src/http/http_rpc_context.h +++ b/src/http/http_rpc_context.h @@ -38,24 +38,24 @@ namespace http { private: ccf::RESTVerb verb; - std::string url = {}; + std::string url; - std::string whole_path = {}; - std::string path = {}; - std::string query = {}; - std::string fragment = {}; + std::string whole_path; + std::string path; + std::string query; + std::string fragment; - ccf::http::HeaderMap request_headers = {}; + ccf::http::HeaderMap request_headers; - std::vector request_body = {}; + std::vector request_body; std::shared_ptr responder = nullptr; - std::vector serialised_request = {}; + std::vector serialised_request; ccf::http::HeaderMap response_headers; ccf::http::HeaderMap response_trailers; - std::vector response_body = {}; + std::vector response_body; ccf::http_status response_status = HTTP_STATUS_OK; bool serialised = false; @@ -97,19 +97,20 @@ namespace http ccf::HttpVersion http_version, llhttp_method verb_, const std::string_view& url_, - const ccf::http::HeaderMap& headers_, + ccf::http::HeaderMap headers_, const std::vector& body_, const std::shared_ptr& responder_ = nullptr, const std::vector& raw_request_ = {}) : RpcContextImpl(s, http_version), verb(verb_), url(url_), - request_headers(headers_), + request_headers(std::move(headers_)), request_body(body_), responder(responder_), serialised_request(raw_request_) { const auto [path_, query_, fragment_] = split_url_path(url); + // NOLINTBEGIN(cppcoreguidelines-prefer-member-initializer) path = path_; whole_path = path_; query = url_decode(query_); @@ -119,60 +120,61 @@ namespace http { serialised = true; } + // NOLINTEND(cppcoreguidelines-prefer-member-initializer) } - ccf::http::HeaderMap get_response_headers() const + [[nodiscard]] ccf::http::HeaderMap get_response_headers() const { return response_headers; } - ccf::http::HeaderMap get_response_trailers() const + [[nodiscard]] ccf::http::HeaderMap get_response_trailers() const { return response_trailers; } - ccf::http_status get_response_http_status() const + [[nodiscard]] ccf::http_status get_response_http_status() const { return response_status; } - virtual ccf::FrameFormat frame_format() const override + [[nodiscard]] ccf::FrameFormat frame_format() const override { return ccf::FrameFormat::http; } - virtual void set_tx_id(const ccf::TxID& tx_id) override + void set_tx_id(const ccf::TxID& tx_id) override { set_response_header(ccf::http::headers::CCF_TX_ID, tx_id.to_str()); } - virtual const std::vector& get_request_body() const override + [[nodiscard]] const std::vector& get_request_body() const override { return request_body; } - virtual const std::string& get_request_query() const override + [[nodiscard]] const std::string& get_request_query() const override { return query; } - virtual const ccf::RESTVerb& get_request_verb() const override + [[nodiscard]] const ccf::RESTVerb& get_request_verb() const override { return verb; } - virtual std::string get_request_path() const override + [[nodiscard]] std::string get_request_path() const override { return whole_path; } - virtual const std::vector& get_serialised_request() override + const std::vector& get_serialised_request() override { serialise(); return serialised_request; } - virtual std::string get_method() const override + [[nodiscard]] std::string get_method() const override { return path; } @@ -182,12 +184,13 @@ namespace http path = p; } - virtual const ccf::http::HeaderMap& get_request_headers() const override + [[nodiscard]] const ccf::http::HeaderMap& get_request_headers() + const override { return request_headers; } - virtual std::optional get_request_header( + [[nodiscard]] std::optional get_request_header( const std::string_view& name) const override { const auto it = request_headers.find(name); @@ -199,12 +202,12 @@ namespace http return std::nullopt; } - virtual const std::string& get_request_url() const override + [[nodiscard]] const std::string& get_request_url() const override { return url; } - virtual std::shared_ptr get_responder() + [[nodiscard]] std::shared_ptr get_responder() const override { return responder; @@ -227,64 +230,64 @@ namespace http } } - virtual void set_response_body(const std::vector& body) override + void set_response_body(const std::vector& body) override { _set_response_body(body); } - virtual void set_response_body(std::vector&& body) override + void set_response_body(std::vector&& body) override { _set_response_body(std::move(body)); } - virtual void set_response_body(std::string&& body) override + void set_response_body(std::string&& body) override { _set_response_body(std::move(body)); } - virtual const std::vector& get_response_body() const override + [[nodiscard]] const std::vector& get_response_body() const override { return response_body; } - virtual std::vector&& take_response_body() override + std::vector&& take_response_body() override { return std::move(response_body); } - virtual void set_response_status(int status) override + void set_response_status(int status) override { response_status = (ccf::http_status)status; } - virtual int get_response_status() const override + [[nodiscard]] int get_response_status() const override { return response_status; } - virtual void set_response_header( + void set_response_header( const std::string_view& name, const std::string_view& value) override { response_headers[std::string(name)] = value; } - virtual void clear_response_headers() override + void clear_response_headers() override { response_headers.clear(); } - virtual void set_response_trailer( + void set_response_trailer( const std::string_view& name, const std::string_view& value) override { response_trailers[std::string(name)] = value; } - virtual void set_apply_writes(bool apply) override + void set_apply_writes(bool apply) override { explicit_apply_writes = apply; } - virtual bool should_apply_writes() const override + [[nodiscard]] bool should_apply_writes() const override { if (explicit_apply_writes.has_value()) { @@ -295,7 +298,7 @@ namespace http return status_success(response_status); } - virtual void reset_response() override + void reset_response() override { response_headers.clear(); response_body.clear(); @@ -303,7 +306,7 @@ namespace http explicit_apply_writes.reset(); } - virtual std::vector serialise_response() const override + [[nodiscard]] std::vector serialise_response() const override { auto http_response = ::http::Response(response_status); @@ -366,7 +369,8 @@ namespace http // process the request search = rpc_map->find(ccf::ActorsType::users); } - return search.value(); + // NOLINTNEXTLINE(bugprone-unchecked-optional-access) + return *search; } } diff --git a/src/http/http_session.h b/src/http/http_session.h index 89aa7bfe1ff9..847ede2d4acd 100644 --- a/src/http/http_session.h +++ b/src/http/http_session.h @@ -30,18 +30,18 @@ namespace http public: HTTPServerSession( - std::shared_ptr rpc_map, + std::shared_ptr rpc_map_, ::tcp::ConnID session_id_, - const ccf::ListenInterfaceID& interface_id, + ccf::ListenInterfaceID interface_id_, ringbuffer::AbstractWriterFactory& writer_factory, std::unique_ptr ctx, const ccf::http::ParserConfiguration& configuration, - const std::shared_ptr& error_reporter = nullptr) : + const std::shared_ptr& error_reporter_ = nullptr) : HTTPSession(session_id_, writer_factory, std::move(ctx)), request_parser(*this, configuration), - rpc_map(rpc_map), - error_reporter(error_reporter), - interface_id(interface_id) + rpc_map(std::move(rpc_map_)), + error_reporter(error_reporter_), + interface_id(std::move(interface_id_)) {} bool parse(std::span data) override @@ -124,7 +124,7 @@ namespace http const std::string_view& url, ccf::http::HeaderMap&& headers, std::vector&& body, - int32_t) override + int32_t /*stream_id*/) override { LOG_TRACE_FMT( "Processing msg({}, {} [{} bytes])", @@ -171,18 +171,16 @@ namespace http LOG_TRACE_FMT("Pending"); return; } - else + + send_response( + rpc_ctx->get_response_http_status(), + rpc_ctx->get_response_headers(), + rpc_ctx->get_response_trailers(), + std::move(rpc_ctx->take_response_body())); + + if (rpc_ctx->terminate_session) { - send_response( - rpc_ctx->get_response_http_status(), - rpc_ctx->get_response_headers(), - rpc_ctx->get_response_trailers(), - std::move(rpc_ctx->take_response_body())); - - if (rpc_ctx->terminate_session) - { - close_session(); - } + close_session(); } } catch (const std::exception& e) @@ -261,7 +259,8 @@ namespace http LOG_DEBUG_FMT( "Error occurred while parsing fragment {} byte fragment:\n{}", data.size(), - std::string_view((char const*)data.data(), data.size())); + std::string_view( + reinterpret_cast(data.data()), data.size())); close_session(); } @@ -338,7 +337,8 @@ namespace http LOG_DEBUG_FMT( "Error occurred while parsing fragment {} byte fragment:\n{}", data.size(), - std::string_view((char const*)data.data(), data.size())); + std::string_view( + reinterpret_cast(data.data()), data.size())); close_session(); } diff --git a/src/kv/kv_types.h b/src/kv/kv_types.h index dd987409b022..e3a661665369 100644 --- a/src/kv/kv_types.h +++ b/src/kv/kv_types.h @@ -34,11 +34,6 @@ namespace ccf struct PrimarySignature; } -namespace aft -{ - struct Request; -} - namespace ccf::kv { // Term describes an epoch of Versions. It is incremented when global kv's From 62106106e30854adc351a54d6b35953bdf458806 Mon Sep 17 00:00:00 2001 From: Amaury Chamayou Date: Thu, 4 Dec 2025 10:45:06 +0000 Subject: [PATCH 02/18] init --- .clang-tidy | 2 +- src/crypto/openssl/base64.h | 8 ++++-- src/crypto/openssl/ec_key_pair.h | 36 +++++++++++++-------------- src/crypto/openssl/ec_public_key.h | 20 +++++++-------- src/crypto/openssl/eddsa_key_pair.h | 10 ++++---- src/crypto/openssl/eddsa_public_key.h | 10 ++++---- src/crypto/openssl/entropy.h | 6 +++-- src/crypto/openssl/hash.h | 14 ++++++----- src/crypto/openssl/public_key.h | 2 +- src/crypto/openssl/rsa_key_pair.h | 28 ++++++++++----------- src/crypto/openssl/rsa_public_key.h | 18 +++++++------- src/crypto/openssl/symmetric_key.h | 16 ++++++------ src/crypto/openssl/verifier.h | 20 +++++++-------- src/crypto/openssl/x509_time.h | 2 +- 14 files changed, 100 insertions(+), 92 deletions(-) diff --git a/.clang-tidy b/.clang-tidy index cc5646a59e1e..2288915368cc 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -59,5 +59,5 @@ Checks: > -readability-magic-numbers, WarningsAsErrors: '*' -HeaderFilterRegex: '(include\/ccf\/|src\/(udp|tcp|tls|tasks|snapshots|service|quic|pal|apps|clients|common|consensus|ds|enclave|endpoints|host|indexing|http)\/).*' +HeaderFilterRegex: '(include\/ccf\/|src\/(udp|tcp|tls|tasks|snapshots|service|quic|pal|apps|clients|common|consensus|ds|enclave|endpoints|host|indexing|http|crypto)\/).*' FormatStyle: 'file' \ No newline at end of file diff --git a/src/crypto/openssl/base64.h b/src/crypto/openssl/base64.h index 8137d1ba0d14..e66aabf98edc 100644 --- a/src/crypto/openssl/base64.h +++ b/src/crypto/openssl/base64.h @@ -20,11 +20,13 @@ namespace ccf::crypto // Decode Base64 into byte stream static std::vector raw_from_b64(const std::string_view& b64_string) { - const auto data = reinterpret_cast(b64_string.data()); + const auto* const data = reinterpret_cast(b64_string.data()); const auto size = b64_string.size(); if (size == 0) + { return {}; + } // Make sure the error queue is clean before we start // Trying to ameliorate #3677 and #3368 @@ -79,7 +81,9 @@ namespace ccf::crypto static std::string b64_from_raw(const uint8_t* data, size_t size) { if (size == 0) + { return ""; + } // Make sure the error queue is clean before we start // Trying to ameliorate #3677 and #3368 @@ -125,7 +129,7 @@ namespace ccf::crypto } // Clean up result (last \0, newlines) - std::string ret = (const char*)output; + std::string ret = reinterpret_cast(output); ret.pop_back(); ret.erase(std::remove(ret.begin(), ret.end(), '\n'), ret.end()); diff --git a/src/crypto/openssl/ec_key_pair.h b/src/crypto/openssl/ec_key_pair.h index d6c4c696c476..8e8336a21cb6 100644 --- a/src/crypto/openssl/ec_key_pair.h +++ b/src/crypto/openssl/ec_key_pair.h @@ -19,26 +19,26 @@ namespace ccf::crypto ECKeyPair_OpenSSL(const ECKeyPair_OpenSSL&) = delete; ECKeyPair_OpenSSL(const Pem& pem); ECKeyPair_OpenSSL(const JsonWebKeyECPrivate& jwk); - virtual ~ECKeyPair_OpenSSL() = default; + ~ECKeyPair_OpenSSL() override = default; - virtual Pem private_key_pem() const override; - virtual Pem public_key_pem() const override; - virtual std::vector public_key_der() const override; - virtual std::vector private_key_der() const override; + [[nodiscard]] Pem private_key_pem() const override; + [[nodiscard]] Pem public_key_pem() const override; + [[nodiscard]] std::vector public_key_der() const override; + [[nodiscard]] std::vector private_key_der() const override; using ECPublicKey_OpenSSL::verify; - virtual bool verify( + bool verify( const std::vector& contents, const std::vector& signature) override; - virtual bool verify( + bool verify( const uint8_t* contents, size_t contents_size, const uint8_t* signature, size_t signature_size) override; - virtual std::vector sign( + [[nodiscard]] std::vector sign( std::span d, MDType md_type = {}) const override; int sign( @@ -50,23 +50,23 @@ namespace ccf::crypto std::vector sign_hash( const uint8_t* hash, size_t hash_size) const override; - virtual int sign_hash( + int sign_hash( const uint8_t* hash, size_t hash_size, size_t* sig_size, uint8_t* sig) const override; - virtual Pem create_csr( + [[nodiscard]] Pem create_csr( const std::string& subject_name, const std::vector& subject_alt_names, const std::optional& public_key = std::nullopt) const override; - virtual std::vector create_csr_der( + [[nodiscard]] std::vector create_csr_der( const std::string& subject_name, const std::vector& subject_alt_names, const std::optional& public_key = std::nullopt) const override; - virtual Pem sign_csr_impl( + [[nodiscard]] Pem sign_csr_impl( const std::optional& issuer_cert, const Pem& signing_request, const std::string& valid_from, @@ -74,20 +74,20 @@ namespace ccf::crypto bool ca = false, Signer signer = Signer::SUBJECT) const override; - virtual std::vector derive_shared_secret( + std::vector derive_shared_secret( const ECPublicKey& peer_key) override; - virtual CurveID get_curve_id() const override; + [[nodiscard]] CurveID get_curve_id() const override; - virtual std::vector public_key_raw() const override; + [[nodiscard]] std::vector public_key_raw() const override; - virtual ECPublicKey::Coordinates coordinates() const override; + [[nodiscard]] ECPublicKey::Coordinates coordinates() const override; - virtual JsonWebKeyECPrivate private_key_jwk( + [[nodiscard]] JsonWebKeyECPrivate private_key_jwk( const std::optional& kid = std::nullopt) const override; protected: - OpenSSL::Unique_X509_REQ create_req( + [[nodiscard]] OpenSSL::Unique_X509_REQ create_req( const std::string& subject_name, const std::vector& subject_alt_names, const std::optional& public_key) const; diff --git a/src/crypto/openssl/ec_public_key.h b/src/crypto/openssl/ec_public_key.h index 3c02e362360b..d17c2b1070cf 100644 --- a/src/crypto/openssl/ec_public_key.h +++ b/src/crypto/openssl/ec_public_key.h @@ -27,12 +27,12 @@ namespace ccf::crypto ECPublicKey_OpenSSL(ECPublicKey_OpenSSL&& key) = default; ECPublicKey_OpenSSL(std::span der); ECPublicKey_OpenSSL(const JsonWebKeyECPublic& jwk); - virtual ~ECPublicKey_OpenSSL(); + ~ECPublicKey_OpenSSL() override; using ECPublicKey::verify; using ECPublicKey::verify_hash; - virtual bool verify( + bool verify( const uint8_t* contents, size_t contents_size, const uint8_t* sig, @@ -40,25 +40,25 @@ namespace ccf::crypto MDType md_type, HashBytes& bytes) override; - virtual bool verify_hash( + bool verify_hash( const uint8_t* hash, size_t hash_size, const uint8_t* sig, size_t sig_size, MDType md_type) override; - virtual Pem public_key_pem() const override; - virtual std::vector public_key_der() const override; - virtual std::vector public_key_raw() const override; + [[nodiscard]] Pem public_key_pem() const override; + [[nodiscard]] std::vector public_key_der() const override; + [[nodiscard]] std::vector public_key_raw() const override; - virtual CurveID get_curve_id() const override; + [[nodiscard]] CurveID get_curve_id() const override; - int get_openssl_group_id() const; + [[nodiscard]] int get_openssl_group_id() const; static int get_openssl_group_id(CurveID gid); - virtual Coordinates coordinates() const override; + [[nodiscard]] Coordinates coordinates() const override; - virtual JsonWebKeyECPublic public_key_jwk( + [[nodiscard]] JsonWebKeyECPublic public_key_jwk( const std::optional& kid = std::nullopt) const override; }; diff --git a/src/crypto/openssl/eddsa_key_pair.h b/src/crypto/openssl/eddsa_key_pair.h index 7cc9bc2e079e..199285ecc51e 100644 --- a/src/crypto/openssl/eddsa_key_pair.h +++ b/src/crypto/openssl/eddsa_key_pair.h @@ -16,11 +16,11 @@ namespace ccf::crypto EdDSAKeyPair_OpenSSL(const Pem& pem); EdDSAKeyPair_OpenSSL(const JsonWebKeyEdDSAPrivate& jwk); - Pem private_key_pem() const override; + [[nodiscard]] Pem private_key_pem() const override; - Pem public_key_pem() const override; + [[nodiscard]] Pem public_key_pem() const override; - std::vector sign(std::span d) const override; + [[nodiscard]] std::vector sign(std::span d) const override; bool verify( const uint8_t* contents, @@ -28,9 +28,9 @@ namespace ccf::crypto const uint8_t* signature, size_t signature_size) override; - virtual CurveID get_curve_id() const override; + [[nodiscard]] CurveID get_curve_id() const override; - virtual JsonWebKeyEdDSAPrivate private_key_jwk_eddsa( + [[nodiscard]] JsonWebKeyEdDSAPrivate private_key_jwk_eddsa( const std::optional& kid = std::nullopt) const override; }; } diff --git a/src/crypto/openssl/eddsa_public_key.h b/src/crypto/openssl/eddsa_public_key.h index 4d447a783fb7..6a9361af934e 100644 --- a/src/crypto/openssl/eddsa_public_key.h +++ b/src/crypto/openssl/eddsa_public_key.h @@ -21,11 +21,11 @@ namespace ccf::crypto EdDSAPublicKey_OpenSSL() = default; EdDSAPublicKey_OpenSSL(const Pem& pem); EdDSAPublicKey_OpenSSL(const JsonWebKeyEdDSAPublic& jwk); - virtual ~EdDSAPublicKey_OpenSSL(); + ~EdDSAPublicKey_OpenSSL() override; - virtual Pem public_key_pem() const override; + [[nodiscard]] Pem public_key_pem() const override; - virtual bool verify( + bool verify( const uint8_t* contents, size_t contents_size, const uint8_t* sig, @@ -33,9 +33,9 @@ namespace ccf::crypto static int get_openssl_group_id(CurveID gid); - virtual CurveID get_curve_id() const override; + [[nodiscard]] CurveID get_curve_id() const override; - virtual JsonWebKeyEdDSAPublic public_key_jwk_eddsa( + [[nodiscard]] JsonWebKeyEdDSAPublic public_key_jwk_eddsa( const std::optional& kid = std::nullopt) const override; }; } diff --git a/src/crypto/openssl/entropy.h b/src/crypto/openssl/entropy.h index 037535d6ff4c..5803c1986868 100644 --- a/src/crypto/openssl/entropy.h +++ b/src/crypto/openssl/entropy.h @@ -25,16 +25,18 @@ namespace ccf::crypto std::vector data(len); if (RAND_bytes(data.data(), data.size()) != 1) + { throw std::logic_error("Couldn't create random data"); + } return data; } uint64_t random64() override { - uint64_t rnd; + uint64_t rnd = 0; - if (RAND_bytes((unsigned char*)&rnd, sizeof(uint64_t)) != 1) + if (RAND_bytes(reinterpret_cast(&rnd), sizeof(uint64_t)) != 1) { throw std::logic_error("Couldn't create random data"); } diff --git a/src/crypto/openssl/hash.h b/src/crypto/openssl/hash.h index f3de1d48317c..6b154da8a9e2 100644 --- a/src/crypto/openssl/hash.h +++ b/src/crypto/openssl/hash.h @@ -53,14 +53,16 @@ namespace ccf::crypto * @param size The size of @p data * @param type The type of hash to compute */ - virtual HashBytes Hash(const uint8_t* data, size_t size, MDType type) const + HashBytes Hash(const uint8_t* data, size_t size, MDType type) const override { - auto o_md_type = OpenSSL::get_md_type(type); + const auto* o_md_type = OpenSSL::get_md_type(type); HashBytes r(EVP_MD_size(o_md_type)); unsigned int len = 0; - if (EVP_Digest(data, size, r.data(), &len, o_md_type, NULL) != 1) + if (EVP_Digest(data, size, r.data(), &len, o_md_type, nullptr) != 1) + { throw std::runtime_error("OpenSSL hash update error"); + } return r; } @@ -70,9 +72,9 @@ namespace ccf::crypto { public: ISha256OpenSSL(); - ~ISha256OpenSSL(); - virtual void update_hash(std::span data); - virtual Sha256Hash finalise(); + ~ISha256OpenSSL() override; + void update_hash(std::span data) override; + Sha256Hash finalise() override; protected: EVP_MD_CTX* ctx = nullptr; diff --git a/src/crypto/openssl/public_key.h b/src/crypto/openssl/public_key.h index 31aecc57298f..ef56af94ed19 100644 --- a/src/crypto/openssl/public_key.h +++ b/src/crypto/openssl/public_key.h @@ -33,7 +33,7 @@ namespace ccf::crypto void check_is_cose_compatible(int cose_alg) { - if (!key) + if (key == nullptr) { throw std::logic_error("Public key is not initialized"); } diff --git a/src/crypto/openssl/rsa_key_pair.h b/src/crypto/openssl/rsa_key_pair.h index 17bf28c777b7..68a44716fadc 100644 --- a/src/crypto/openssl/rsa_key_pair.h +++ b/src/crypto/openssl/rsa_key_pair.h @@ -18,31 +18,31 @@ namespace ccf::crypto RSAKeyPair_OpenSSL(size_t public_key_size, size_t public_exponent); RSAKeyPair_OpenSSL(const Pem& pem); RSAKeyPair_OpenSSL(const JsonWebKeyRSAPrivate& jwk); - virtual ~RSAKeyPair_OpenSSL() = default; + ~RSAKeyPair_OpenSSL() override = default; RSAKeyPair_OpenSSL(EVP_PKEY* k); - virtual Pem private_key_pem() const override; - virtual std::vector private_key_der() const override; - virtual JsonWebKeyRSAPrivate private_key_jwk( + [[nodiscard]] Pem private_key_pem() const override; + [[nodiscard]] std::vector private_key_der() const override; + [[nodiscard]] JsonWebKeyRSAPrivate private_key_jwk( const std::optional& kid = std::nullopt) const override; - virtual std::vector sign( + [[nodiscard]] std::vector sign( std::span d, MDType md_type = MDType::NONE, size_t salt_length = 0) const override; - virtual std::vector rsa_oaep_unwrap( + std::vector rsa_oaep_unwrap( const std::vector& input, const std::optional>& label = std::nullopt) override; - virtual size_t key_size() const override + [[nodiscard]] size_t key_size() const override { return RSAPublicKey_OpenSSL::key_size(); } - virtual std::vector rsa_oaep_wrap( + std::vector rsa_oaep_wrap( const uint8_t* input, size_t input_size, const uint8_t* label = nullptr, @@ -52,7 +52,7 @@ namespace ccf::crypto input, input_size, label, label_size); } - virtual std::vector rsa_oaep_wrap( + std::vector rsa_oaep_wrap( const std::vector& input, const std::optional>& label = std::nullopt) override @@ -60,22 +60,22 @@ namespace ccf::crypto return RSAPublicKey_OpenSSL::rsa_oaep_wrap(input, label); } - virtual Pem public_key_pem() const override + [[nodiscard]] Pem public_key_pem() const override { return RSAPublicKey_OpenSSL::public_key_pem(); } - virtual std::vector public_key_der() const override + [[nodiscard]] std::vector public_key_der() const override { return RSAPublicKey_OpenSSL::public_key_der(); } - virtual JsonWebKeyRSAPublic public_key_jwk( + [[nodiscard]] JsonWebKeyRSAPublic public_key_jwk( const std::optional& kid = std::nullopt) const override { return RSAPublicKey_OpenSSL::public_key_jwk(kid); } - virtual bool verify( + bool verify( const uint8_t* contents, size_t contents_size, const uint8_t* signature, @@ -94,7 +94,7 @@ namespace ccf::crypto salt_length); } - virtual bool verify_hash( + bool verify_hash( const uint8_t* hash, size_t hash_size, const uint8_t* signature, diff --git a/src/crypto/openssl/rsa_public_key.h b/src/crypto/openssl/rsa_public_key.h index 705b6773c7c3..58c232855f60 100644 --- a/src/crypto/openssl/rsa_public_key.h +++ b/src/crypto/openssl/rsa_public_key.h @@ -25,28 +25,28 @@ namespace ccf::crypto RSAPublicKey_OpenSSL(std::span der); RSAPublicKey_OpenSSL(const JsonWebKeyRSAPublic& jwk); - virtual ~RSAPublicKey_OpenSSL(); + ~RSAPublicKey_OpenSSL() override; - virtual size_t key_size() const override; + [[nodiscard]] size_t key_size() const override; - virtual std::vector rsa_oaep_wrap( + std::vector rsa_oaep_wrap( const uint8_t* input, size_t input_size, const uint8_t* label = nullptr, size_t label_size = 0) override; - virtual std::vector rsa_oaep_wrap( + std::vector rsa_oaep_wrap( const std::vector& input, const std::optional>& label = std::nullopt) override; - virtual Pem public_key_pem() const override; - virtual std::vector public_key_der() const override; + [[nodiscard]] Pem public_key_pem() const override; + [[nodiscard]] std::vector public_key_der() const override; - virtual JsonWebKeyRSAPublic public_key_jwk( + [[nodiscard]] JsonWebKeyRSAPublic public_key_jwk( const std::optional& kid = std::nullopt) const override; - virtual bool verify( + bool verify( const uint8_t* contents, size_t contents_size, const uint8_t* signature, @@ -55,7 +55,7 @@ namespace ccf::crypto RSAPadding padding, size_t salt_length) override; - virtual bool verify_hash( + bool verify_hash( const uint8_t* hash, size_t hash_size, const uint8_t* signature, diff --git a/src/crypto/openssl/symmetric_key.h b/src/crypto/openssl/symmetric_key.h index 332b3fde14d5..3729cdb7c9b7 100644 --- a/src/crypto/openssl/symmetric_key.h +++ b/src/crypto/openssl/symmetric_key.h @@ -13,28 +13,28 @@ namespace ccf::crypto { private: const std::vector key; - const EVP_CIPHER* evp_cipher; + const EVP_CIPHER* evp_cipher = nullptr; const EVP_CIPHER* evp_cipher_wrap_pad; public: KeyAesGcm_OpenSSL(std::span rawKey); KeyAesGcm_OpenSSL(const KeyAesGcm_OpenSSL& that) = delete; - KeyAesGcm_OpenSSL(KeyAesGcm_OpenSSL&& that); - virtual ~KeyAesGcm_OpenSSL() + KeyAesGcm_OpenSSL(KeyAesGcm_OpenSSL&& that) noexcept; + ~KeyAesGcm_OpenSSL() override { OPENSSL_cleanse(const_cast(key.data()), key.size()); } - virtual size_t key_size() const override; + [[nodiscard]] size_t key_size() const override; - virtual void encrypt( + void encrypt( std::span iv, std::span plain, std::span aad, std::vector& cipher, uint8_t tag[GCM_SIZE_TAG]) const override; - virtual bool decrypt( + bool decrypt( std::span iv, const uint8_t tag[GCM_SIZE_TAG], std::span cipher, @@ -43,12 +43,12 @@ namespace ccf::crypto // @brief RFC 5649 AES key wrap with padding (CKM_AES_KEY_WRAP_PAD) // @param plain Plaintext key to wrap - std::vector ckm_aes_key_wrap_pad( + [[nodiscard]] std::vector ckm_aes_key_wrap_pad( std::span plain) const; // @brief RFC 5649 AES key unwrap (with padding, CKM_AES_KEY_WRAP_PAD) // @param cipher Wrapped key to unwrap - std::vector ckm_aes_key_unwrap_pad( + [[nodiscard]] std::vector ckm_aes_key_unwrap_pad( std::span cipher) const; }; } diff --git a/src/crypto/openssl/verifier.h b/src/crypto/openssl/verifier.h index be54673cf0a2..8e883456c5df 100644 --- a/src/crypto/openssl/verifier.h +++ b/src/crypto/openssl/verifier.h @@ -21,29 +21,29 @@ namespace ccf::crypto Verifier_OpenSSL(const std::vector& c); Verifier_OpenSSL(Verifier_OpenSSL&& v) = default; Verifier_OpenSSL(const Verifier_OpenSSL&) = delete; - virtual ~Verifier_OpenSSL(); + ~Verifier_OpenSSL() override; - virtual std::vector cert_der() override; - virtual Pem cert_pem() override; + std::vector cert_der() override; + Pem cert_pem() override; - virtual bool verify_certificate( + bool verify_certificate( const std::vector& trusted_certs, const std::vector& chain = {}, bool ignore_time = false) override; - virtual bool is_self_signed() const override; + bool is_self_signed() const override; - virtual std::string serial_number() const override; + std::string serial_number() const override; - virtual std::pair validity_period() + std::pair validity_period() const override; - virtual size_t remaining_seconds( + size_t remaining_seconds( const std::chrono::system_clock::time_point& now) const override; - virtual double remaining_percentage( + double remaining_percentage( const std::chrono::system_clock::time_point& now) const override; - virtual std::string subject() const override; + std::string subject() const override; }; } diff --git a/src/crypto/openssl/x509_time.h b/src/crypto/openssl/x509_time.h index 715b55aca6ac..b9befafe0ce3 100644 --- a/src/crypto/openssl/x509_time.h +++ b/src/crypto/openssl/x509_time.h @@ -28,7 +28,7 @@ namespace ccf::crypto::OpenSSL static inline std::string to_x509_time_string(const ASN1_TIME* time) { - std::tm t; + std::tm t{}; CHECK1(ASN1_TIME_to_tm(time, &t)); return ccf::ds::to_x509_time_string(t); } From bfdd15a1b346dd510f4b7105fbea9ff3b27f56a0 Mon Sep 17 00:00:00 2001 From: Amaury Chamayou Date: Thu, 4 Dec 2025 13:31:05 +0000 Subject: [PATCH 03/18] tidy --- src/crypto/csr.h | 6 +- src/crypto/key_exchange.h | 12 +- src/crypto/openssl/cose_sign.h | 20 +-- src/crypto/openssl/cose_verifier.h | 6 +- src/crypto/openssl/symmetric_key.cpp | 3 +- src/crypto/sharing.h | 204 +++++++++++++-------------- 6 files changed, 124 insertions(+), 127 deletions(-) diff --git a/src/crypto/csr.h b/src/crypto/csr.h index 46f9bf94bf66..35af7bfbfa43 100644 --- a/src/crypto/csr.h +++ b/src/crypto/csr.h @@ -13,7 +13,7 @@ namespace ccf::crypto * @param signing_request CSR to extract the public key from * @return extracted public key */ - Pem public_key_pem_from_csr(const Pem& signing_request) + inline Pem public_key_pem_from_csr(const Pem& signing_request) { OpenSSL::Unique_BIO mem(signing_request); OpenSSL::Unique_X509_REQ csr(mem); @@ -23,8 +23,8 @@ namespace ccf::crypto OpenSSL::CHECK1(PEM_write_bio_PUBKEY(buf, req_pubkey)); - BUF_MEM* bptr; + BUF_MEM* bptr = nullptr; BIO_get_mem_ptr(buf, &bptr); - return Pem((uint8_t*)bptr->data, bptr->length); + return {reinterpret_cast(bptr->data), bptr->length}; } } \ No newline at end of file diff --git a/src/crypto/key_exchange.h b/src/crypto/key_exchange.h index 1a70ab0af1a2..eb4b14b79839 100644 --- a/src/crypto/key_exchange.h +++ b/src/crypto/key_exchange.h @@ -21,7 +21,7 @@ namespace tls private: ccf::crypto::ECKeyPairPtr own_key; ccf::crypto::ECPublicKeyPtr peer_key; - ccf::crypto::CurveID curve; + ccf::crypto::CurveID curve{ccf::crypto::CurveID::SECP384R1}; std::vector shared_secret; void compute_shared_secret() @@ -41,9 +41,9 @@ namespace tls } public: - KeyExchangeContext() : curve(ccf::crypto::CurveID::SECP384R1) {} + KeyExchangeContext() = default; - ~KeyExchangeContext() {} + ~KeyExchangeContext() = default; std::vector get_own_key_share() { @@ -61,7 +61,7 @@ namespace tls return tmp; } - std::vector get_peer_key_share() const + [[nodiscard]] std::vector get_peer_key_share() const { if (!peer_key) { @@ -83,7 +83,7 @@ namespace tls void load_peer_key_share(std::span ks) { - if (ks.size() == 0) + if (ks.empty()) { throw std::runtime_error("Provided peer key share is empty"); } @@ -94,7 +94,7 @@ namespace tls int nid = ccf::crypto::ECPublicKey_OpenSSL::get_openssl_group_id(curve); auto pk = ccf::crypto::key_from_raw_ec_point(tmp, nid); - if (!pk) + if (pk == nullptr) { throw std::runtime_error("Failed to parse peer key share"); } diff --git a/src/crypto/openssl/cose_sign.h b/src/crypto/openssl/cose_sign.h index c235bb565275..8aec44bdb068 100644 --- a/src/crypto/openssl/cose_sign.h +++ b/src/crypto/openssl/cose_sign.h @@ -59,7 +59,7 @@ namespace ccf::crypto { public: virtual void apply(QCBOREncodeContext* ctx) const = 0; - virtual size_t estimated_size() const = 0; + [[nodiscard]] virtual size_t estimated_size() const = 0; virtual ~COSEMapKey() = default; }; @@ -71,7 +71,7 @@ namespace ccf::crypto ~COSEMapIntKey() override = default; void apply(QCBOREncodeContext* ctx) const override; - size_t estimated_size() const override; + [[nodiscard]] size_t estimated_size() const override; private: int64_t key; @@ -84,7 +84,7 @@ namespace ccf::crypto ~COSEMapStringKey() override = default; void apply(QCBOREncodeContext* ctx) const override; - size_t estimated_size() const override; + [[nodiscard]] size_t estimated_size() const override; private: std::string key; @@ -94,7 +94,7 @@ namespace ccf::crypto { public: virtual void apply(QCBOREncodeContext* ctx) const = 0; - virtual size_t estimated_size() const = 0; + [[nodiscard]] virtual size_t estimated_size() const = 0; virtual ~COSEParametersFactory() = default; }; @@ -107,13 +107,13 @@ namespace ccf::crypto const std::vector>& factories_); void apply(QCBOREncodeContext* ctx) const override; - size_t estimated_size() const override; + [[nodiscard]] size_t estimated_size() const override; - virtual ~COSEParametersMap() = default; + ~COSEParametersMap() override = default; private: std::shared_ptr key; - std::vector> factories{}; + std::vector> factories; }; std::shared_ptr cose_params_int_int( @@ -143,20 +143,20 @@ namespace ccf::crypto args_size{args_size} {} - virtual ~COSEParametersPair() = default; + ~COSEParametersPair() override = default; void apply(QCBOREncodeContext* ctx) const override { impl(ctx); } - size_t estimated_size() const override + [[nodiscard]] size_t estimated_size() const override { return args_size; } private: - std::function impl{}; + std::function impl; size_t args_size{}; }; diff --git a/src/crypto/openssl/cose_verifier.h b/src/crypto/openssl/cose_verifier.h index e922b465e996..1111c3b84494 100644 --- a/src/crypto/openssl/cose_verifier.h +++ b/src/crypto/openssl/cose_verifier.h @@ -21,11 +21,11 @@ namespace ccf::crypto std::shared_ptr public_key; public: - virtual ~COSEVerifier_OpenSSL() override; - virtual bool verify( + ~COSEVerifier_OpenSSL() override; + bool verify( const std::span& envelope, std::span& authned_content) const override; - virtual bool verify_detached( + [[nodiscard]] bool verify_detached( std::span envelope, std::span payload) const override; }; diff --git a/src/crypto/openssl/symmetric_key.cpp b/src/crypto/openssl/symmetric_key.cpp index f073d8725788..7570e494945d 100644 --- a/src/crypto/openssl/symmetric_key.cpp +++ b/src/crypto/openssl/symmetric_key.cpp @@ -20,8 +20,7 @@ namespace ccf::crypto static constexpr size_t KEY_SIZE_128 = 128; KeyAesGcm_OpenSSL::KeyAesGcm_OpenSSL(std::span rawKey) : - key(std::vector(rawKey.data(), rawKey.data() + rawKey.size())), - evp_cipher(nullptr) + key(std::vector(rawKey.data(), rawKey.data() + rawKey.size())) { const auto n = static_cast(rawKey.size() * CHAR_BIT); if (n >= KEY_SIZE_256) diff --git a/src/crypto/sharing.h b/src/crypto/sharing.h index cedb4cb8d7fa..eee55c88b054 100644 --- a/src/crypto/sharing.h +++ b/src/crypto/sharing.h @@ -14,119 +14,117 @@ #include -namespace ccf::crypto +namespace ccf::crypto::sharing { - namespace sharing - { - // We get (almost) 31 bits of entropy per limb, hence to get 256 bits of - // entropy of derived key material, with 80 bits of safety margin, - // ((256+80)/31) = 10 limbs. - static constexpr size_t LIMBS = 10; - static constexpr const char* key_label = "CCF Wrapping Key v1"; +// We get (almost) 31 bits of entropy per limb, hence to get 256 bits of +// entropy of derived key material, with 80 bits of safety margin, +// ((256+80)/31) = 10 limbs. +static constexpr size_t LIMBS = 10; +static constexpr const char* key_label = "CCF Wrapping Key v1"; - struct Share - { - // Index in a re-share, 0 is a full key, and 1+ is a partial share - uint32_t x = 0; - uint32_t y[LIMBS]; - constexpr static size_t serialised_size = - sizeof(uint32_t) + sizeof(uint32_t) * LIMBS; +struct Share +{ + // Index in a re-share, 0 is a full key, and 1+ is a partial share + uint32_t x = 0; + uint32_t y[LIMBS] = {}; + constexpr static size_t serialised_size = + sizeof(uint32_t) + sizeof(uint32_t) * LIMBS; - Share() = default; - bool operator==(const Share& other) const = default; + Share() = default; + bool operator==(const Share& other) const = default; - ~Share() - { - OPENSSL_cleanse(y, sizeof(y)); - }; + ~Share() + { + OPENSSL_cleanse(y, sizeof(y)); + }; - HashBytes key(size_t key_size) const - { - if (x != 0) - { - throw std::invalid_argument( - "Cannot derive a key from a partial share"); - } - const std::span ikm( - reinterpret_cast(y), sizeof(y)); - const std::span label( - reinterpret_cast(y), sizeof(y)); - auto k = ccf::crypto::hkdf( - ccf::crypto::MDType::SHA256, key_size, ikm, {}, label); - return k; - } + [[nodiscard]] HashBytes key(size_t key_size) const + { + if (x != 0) + { + throw std::invalid_argument("Cannot derive a key from a partial share"); + } + const std::span ikm( + reinterpret_cast(y), sizeof(y)); + const std::span label( + reinterpret_cast(y), sizeof(y)); + auto k = ccf::crypto::hkdf( + ccf::crypto::MDType::SHA256, key_size, ikm, {}, label); + return k; + } - void serialise(std::vector& serialised) const - { - auto size = serialised_size; - if (serialised.size() != size) - { - throw std::invalid_argument("Invalid serialised share size"); - } + void serialise(std::vector& serialised) const + { + auto size = serialised_size; + if (serialised.size() != size) + { + throw std::invalid_argument("Invalid serialised share size"); + } - auto data = serialised.data(); - serialized::write(data, size, x); - for (size_t i = 0; i < LIMBS; ++i) - { - serialized::write(data, size, y[i]); - } - } + auto* data = serialised.data(); + serialized::write(data, size, x); + // NOLINTNEXTLINE(modernize-loop-convert) + for (size_t i = 0; i < LIMBS; ++i) + { + serialized::write(data, size, y[i]); + } + } - Share(const std::span& serialised) - { - if (serialised.size() != serialised_size) - { - throw std::invalid_argument("Invalid serialised share size"); - } - auto data = serialised.data(); - auto size = serialised.size(); - x = serialized::read(data, size); - for (size_t i = 0; i < LIMBS; ++i) - { - y[i] = serialized::read(data, size); - } - } + Share(const std::span& serialised) + { + if (serialised.size() != serialised_size) + { + throw std::invalid_argument("Invalid serialised share size"); + } + const auto* data = serialised.data(); + auto size = serialised.size(); + x = serialized::read(data, size); + // NOLINTNEXTLINE(modernize-loop-convert) + for (size_t i = 0; i < LIMBS; ++i) + { + y[i] = serialized::read(data, size); + } + } - std::string to_str() const - { - return fmt::format("x: {} y: {}", x, fmt::join(y, ", ")); - } - }; + [[nodiscard]] std::string to_str() const + { + return fmt::format("x: {} y: {}", x, fmt::join(y, ", ")); + } +}; - // Exposed for testing only - using element = uint64_t; - element ct_reduce(element x); +// Exposed for testing only +using element = uint64_t; +element ct_reduce(element x); - /** Sample a secret into @p raw_secret, and split it into @p shares. - * Enforces 1 < @p threshold <= number of shares. - * - * @param[out] raw_secret Sampled secret value. - * @param[out] shares Shares of raw_secret. Note that the size of the span - * determines the number of shares. - * @param[in] threshold Number of shares necessary to recover the secret. - * - * The secret is guaranteed to contain at least 256 bits of entropy. - * Note that is it not safe to use the secret as a key directly, - * and that a round of key derivation is necessary (Share::key()). - */ - void sample_secret_and_shares( - Share& raw_secret, const std::span& shares, size_t threshold); +/** Sample a secret into @p raw_secret, and split it into @p shares. + * Enforces 1 < @p threshold <= number of shares. + * + * @param[out] raw_secret Sampled secret value. + * @param[out] shares Shares of raw_secret. Note that the size of the span + * determines the number of shares. + * @param[in] threshold Number of shares necessary to recover the secret. + * + * The secret is guaranteed to contain at least 256 bits of entropy. + * Note that is it not safe to use the secret as a key directly, + * and that a round of key derivation is necessary (Share::key()). + */ +void sample_secret_and_shares( + Share& raw_secret, const std::span& shares, size_t threshold); - /** Using @p shares, recover @p secret, without authentication. - * - * @param[out] raw_secret Recovered secret value. - * @param[in] shares Shares of raw_secret. - * @param threshold Number of shares necessary to recover the secret. - * - * Note that shares passed in excess of the threshold are ignored, - * and that recovery does not authenticate the shares or the threshold. - * - * @throws std::invalid_argument if the number of shares is insufficient, - * or if two shares have the same x coordinate. - */ - void recover_unauthenticated_secret( - Share& raw_secret, - const std::span& shares, - size_t threshold); - } +/** Using @p shares, recover @p secret, without authentication. + * + * @param[out] raw_secret Recovered secret value. + * @param[in] shares Shares of raw_secret. + * @param threshold Number of shares necessary to recover the secret. + * + * Note that shares passed in excess of the threshold are ignored, + * and that recovery does not authenticate the shares or the threshold. + * + * @throws std::invalid_argument if the number of shares is insufficient, + * or if two shares have the same x coordinate. + */ +void recover_unauthenticated_secret( + Share& raw_secret, + const std::span& shares, + size_t threshold); } \ No newline at end of file From 871275c9f1f19b85e6729fa2df425f530218e8ec Mon Sep 17 00:00:00 2001 From: Amaury Chamayou Date: Thu, 4 Dec 2025 13:48:18 +0000 Subject: [PATCH 04/18] fmt --- src/crypto/openssl/base64.h | 3 +- src/crypto/openssl/eddsa_key_pair.h | 3 +- src/crypto/openssl/entropy.h | 4 +- src/crypto/openssl/verifier.h | 3 +- src/crypto/sharing.h | 184 ++++++++++++++-------------- src/http/http2_session.h | 2 +- 6 files changed, 100 insertions(+), 99 deletions(-) diff --git a/src/crypto/openssl/base64.h b/src/crypto/openssl/base64.h index e66aabf98edc..8eac2d23afc0 100644 --- a/src/crypto/openssl/base64.h +++ b/src/crypto/openssl/base64.h @@ -20,7 +20,8 @@ namespace ccf::crypto // Decode Base64 into byte stream static std::vector raw_from_b64(const std::string_view& b64_string) { - const auto* const data = reinterpret_cast(b64_string.data()); + const auto* const data = + reinterpret_cast(b64_string.data()); const auto size = b64_string.size(); if (size == 0) diff --git a/src/crypto/openssl/eddsa_key_pair.h b/src/crypto/openssl/eddsa_key_pair.h index 199285ecc51e..8bdaa4cbc42e 100644 --- a/src/crypto/openssl/eddsa_key_pair.h +++ b/src/crypto/openssl/eddsa_key_pair.h @@ -20,7 +20,8 @@ namespace ccf::crypto [[nodiscard]] Pem public_key_pem() const override; - [[nodiscard]] std::vector sign(std::span d) const override; + [[nodiscard]] std::vector sign( + std::span d) const override; bool verify( const uint8_t* contents, diff --git a/src/crypto/openssl/entropy.h b/src/crypto/openssl/entropy.h index 5803c1986868..bf3f806f1890 100644 --- a/src/crypto/openssl/entropy.h +++ b/src/crypto/openssl/entropy.h @@ -36,7 +36,9 @@ namespace ccf::crypto { uint64_t rnd = 0; - if (RAND_bytes(reinterpret_cast(&rnd), sizeof(uint64_t)) != 1) + if ( + RAND_bytes(reinterpret_cast(&rnd), sizeof(uint64_t)) != + 1) { throw std::logic_error("Couldn't create random data"); } diff --git a/src/crypto/openssl/verifier.h b/src/crypto/openssl/verifier.h index 8e883456c5df..7302764d908e 100644 --- a/src/crypto/openssl/verifier.h +++ b/src/crypto/openssl/verifier.h @@ -35,8 +35,7 @@ namespace ccf::crypto std::string serial_number() const override; - std::pair validity_period() - const override; + std::pair validity_period() const override; size_t remaining_seconds( const std::chrono::system_clock::time_point& now) const override; diff --git a/src/crypto/sharing.h b/src/crypto/sharing.h index eee55c88b054..a8171716f9fa 100644 --- a/src/crypto/sharing.h +++ b/src/crypto/sharing.h @@ -16,115 +16,113 @@ namespace ccf::crypto::sharing { -// We get (almost) 31 bits of entropy per limb, hence to get 256 bits of -// entropy of derived key material, with 80 bits of safety margin, -// ((256+80)/31) = 10 limbs. -static constexpr size_t LIMBS = 10; -static constexpr const char* key_label = "CCF Wrapping Key v1"; + // We get (almost) 31 bits of entropy per limb, hence to get 256 bits of + // entropy of derived key material, with 80 bits of safety margin, + // ((256+80)/31) = 10 limbs. + static constexpr size_t LIMBS = 10; + static constexpr const char* key_label = "CCF Wrapping Key v1"; -struct Share -{ - // Index in a re-share, 0 is a full key, and 1+ is a partial share - uint32_t x = 0; - uint32_t y[LIMBS] = {}; - constexpr static size_t serialised_size = - sizeof(uint32_t) + sizeof(uint32_t) * LIMBS; - - Share() = default; - bool operator==(const Share& other) const = default; - - ~Share() + struct Share { - OPENSSL_cleanse(y, sizeof(y)); - }; + // Index in a re-share, 0 is a full key, and 1+ is a partial share + uint32_t x = 0; + uint32_t y[LIMBS] = {}; + constexpr static size_t serialised_size = + sizeof(uint32_t) + sizeof(uint32_t) * LIMBS; - [[nodiscard]] HashBytes key(size_t key_size) const - { - if (x != 0) + Share() = default; + bool operator==(const Share& other) const = default; + + ~Share() { - throw std::invalid_argument("Cannot derive a key from a partial share"); - } - const std::span ikm( - reinterpret_cast(y), sizeof(y)); - const std::span label( - reinterpret_cast(y), sizeof(y)); - auto k = ccf::crypto::hkdf( - ccf::crypto::MDType::SHA256, key_size, ikm, {}, label); - return k; - } + OPENSSL_cleanse(y, sizeof(y)); + }; - void serialise(std::vector& serialised) const - { - auto size = serialised_size; - if (serialised.size() != size) + [[nodiscard]] HashBytes key(size_t key_size) const { - throw std::invalid_argument("Invalid serialised share size"); + if (x != 0) + { + throw std::invalid_argument("Cannot derive a key from a partial share"); + } + const std::span ikm( + reinterpret_cast(y), sizeof(y)); + const std::span label( + reinterpret_cast(y), sizeof(y)); + auto k = ccf::crypto::hkdf( + ccf::crypto::MDType::SHA256, key_size, ikm, {}, label); + return k; } - auto* data = serialised.data(); - serialized::write(data, size, x); - // NOLINTNEXTLINE(modernize-loop-convert) - for (size_t i = 0; i < LIMBS; ++i) + void serialise(std::vector& serialised) const { - serialized::write(data, size, y[i]); + auto size = serialised_size; + if (serialised.size() != size) + { + throw std::invalid_argument("Invalid serialised share size"); + } + + auto* data = serialised.data(); + serialized::write(data, size, x); + // NOLINTNEXTLINE(modernize-loop-convert) + for (size_t i = 0; i < LIMBS; ++i) + { + serialized::write(data, size, y[i]); + } } - } - Share(const std::span& serialised) - { - if (serialised.size() != serialised_size) + Share(const std::span& serialised) { - throw std::invalid_argument("Invalid serialised share size"); + if (serialised.size() != serialised_size) + { + throw std::invalid_argument("Invalid serialised share size"); + } + const auto* data = serialised.data(); + auto size = serialised.size(); + x = serialized::read(data, size); + // NOLINTNEXTLINE(modernize-loop-convert) + for (size_t i = 0; i < LIMBS; ++i) + { + y[i] = serialized::read(data, size); + } } - const auto* data = serialised.data(); - auto size = serialised.size(); - x = serialized::read(data, size); - // NOLINTNEXTLINE(modernize-loop-convert) - for (size_t i = 0; i < LIMBS; ++i) + + [[nodiscard]] std::string to_str() const { - y[i] = serialized::read(data, size); + return fmt::format("x: {} y: {}", x, fmt::join(y, ", ")); } - } - - [[nodiscard]] std::string to_str() const - { - return fmt::format("x: {} y: {}", x, fmt::join(y, ", ")); - } -}; + }; -// Exposed for testing only -using element = uint64_t; -element ct_reduce(element x); + // Exposed for testing only + using element = uint64_t; + element ct_reduce(element x); -/** Sample a secret into @p raw_secret, and split it into @p shares. - * Enforces 1 < @p threshold <= number of shares. - * - * @param[out] raw_secret Sampled secret value. - * @param[out] shares Shares of raw_secret. Note that the size of the span - * determines the number of shares. - * @param[in] threshold Number of shares necessary to recover the secret. - * - * The secret is guaranteed to contain at least 256 bits of entropy. - * Note that is it not safe to use the secret as a key directly, - * and that a round of key derivation is necessary (Share::key()). - */ -void sample_secret_and_shares( - Share& raw_secret, const std::span& shares, size_t threshold); + /** Sample a secret into @p raw_secret, and split it into @p shares. + * Enforces 1 < @p threshold <= number of shares. + * + * @param[out] raw_secret Sampled secret value. + * @param[out] shares Shares of raw_secret. Note that the size of the span + * determines the number of shares. + * @param[in] threshold Number of shares necessary to recover the secret. + * + * The secret is guaranteed to contain at least 256 bits of entropy. + * Note that is it not safe to use the secret as a key directly, + * and that a round of key derivation is necessary (Share::key()). + */ + void sample_secret_and_shares( + Share& raw_secret, const std::span& shares, size_t threshold); -/** Using @p shares, recover @p secret, without authentication. - * - * @param[out] raw_secret Recovered secret value. - * @param[in] shares Shares of raw_secret. - * @param threshold Number of shares necessary to recover the secret. - * - * Note that shares passed in excess of the threshold are ignored, - * and that recovery does not authenticate the shares or the threshold. - * - * @throws std::invalid_argument if the number of shares is insufficient, - * or if two shares have the same x coordinate. - */ -void recover_unauthenticated_secret( - Share& raw_secret, - const std::span& shares, - size_t threshold); + /** Using @p shares, recover @p secret, without authentication. + * + * @param[out] raw_secret Recovered secret value. + * @param[in] shares Shares of raw_secret. + * @param threshold Number of shares necessary to recover the secret. + * + * Note that shares passed in excess of the threshold are ignored, + * and that recovery does not authenticate the shares or the threshold. + * + * @throws std::invalid_argument if the number of shares is insufficient, + * or if two shares have the same x coordinate. + */ + void recover_unauthenticated_secret( + Share& raw_secret, const std::span& shares, size_t threshold); } \ No newline at end of file diff --git a/src/http/http2_session.h b/src/http/http2_session.h index a7411f92a914..82350f56c328 100644 --- a/src/http/http2_session.h +++ b/src/http/http2_session.h @@ -61,7 +61,7 @@ namespace http sp->respond( stream_id, status_code, - headers, + std::move(headers), std::move(trailers), std::move(body)); } From 2b6653b7db61d446c4f98db0b8bc1fcf18c974f9 Mon Sep 17 00:00:00 2001 From: Amaury Chamayou Date: Thu, 4 Dec 2025 16:13:07 +0000 Subject: [PATCH 05/18] gov --- .clang-tidy | 2 +- src/node/gov/api_version.h | 10 ++-- src/node/gov/handlers/acks.h | 4 +- src/node/gov/handlers/helpers.h | 16 +++--- src/node/gov/handlers/proposals.h | 74 +++++++++++++-------------- src/node/gov/handlers/recovery.h | 2 +- src/node/gov/handlers/service_state.h | 10 ++-- src/node/gov/handlers/transactions.h | 13 ++--- 8 files changed, 66 insertions(+), 65 deletions(-) diff --git a/.clang-tidy b/.clang-tidy index cc5646a59e1e..bb121c427321 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -59,5 +59,5 @@ Checks: > -readability-magic-numbers, WarningsAsErrors: '*' -HeaderFilterRegex: '(include\/ccf\/|src\/(udp|tcp|tls|tasks|snapshots|service|quic|pal|apps|clients|common|consensus|ds|enclave|endpoints|host|indexing|http)\/).*' +HeaderFilterRegex: '(include\/ccf\/|src\/(udp|tcp|tls|tasks|snapshots|service|quic|pal|apps|clients|common|consensus|ds|enclave|endpoints|host|indexing|http|node\/gov)\/).*' FormatStyle: 'file' \ No newline at end of file diff --git a/src/node/gov/api_version.h b/src/node/gov/api_version.h index 76ecf53d0753..edc7710706e6 100644 --- a/src/node/gov/api_version.h +++ b/src/node/gov/api_version.h @@ -9,7 +9,7 @@ namespace ccf::gov::endpoints { - enum class ApiVersion + enum class ApiVersion : uint8_t { preview_v1, MIN = preview_v1, @@ -21,7 +21,7 @@ namespace ccf::gov::endpoints {ApiVersion::preview_v1, "2023-06-01-preview"}, {ApiVersion::v1, "2024-07-01"}}; - std::optional get_api_version( + inline std::optional get_api_version( ccf::endpoints::CommandEndpointContext& ctx, ApiVersion min_accepted, // Optional out-parameter indicating why API version wasn't found @@ -47,7 +47,7 @@ namespace ccf::gov::endpoints } } - const auto param_name = "api-version"; + const auto* const param_name = "api-version"; const auto parsed_query = http::parse_query(ctx.rpc_ctx->get_request_query()); const auto qit = parsed_query.find(param_name); @@ -68,7 +68,7 @@ namespace ccf::gov::endpoints return std::nullopt; } - const auto it = std::find_if( + const auto* const it = std::find_if( std::begin(api_version_strings), std::end(api_version_strings), [&qit](const auto& p) { return p.second == qit->second; }); @@ -100,7 +100,7 @@ namespace ccf::gov::endpoints template auto api_version_adapter(Fn&& f, ApiVersion min_accepted = ApiVersion::MIN) { - return [f, min_accepted](auto& ctx) { + return [f = std::forward(f), min_accepted](auto& ctx) { const auto api_version = get_api_version(ctx, min_accepted); if (api_version.has_value()) { diff --git a/src/node/gov/handlers/acks.h b/src/node/gov/handlers/acks.h index 1d91a5948d79..a4ed1ce81242 100644 --- a/src/node/gov/handlers/acks.h +++ b/src/node/gov/handlers/acks.h @@ -10,9 +10,9 @@ namespace ccf::gov::endpoints { - void init_ack_handlers( + inline void init_ack_handlers( ccf::BaseEndpointRegistry& registry, - NetworkState& network, + NetworkState& /*network*/, ShareManager& share_manager) { auto get_state_digest = [&](auto& ctx, ApiVersion api_version) { diff --git a/src/node/gov/handlers/helpers.h b/src/node/gov/handlers/helpers.h index 3cbabc9f876f..ef07f8e25535 100644 --- a/src/node/gov/handlers/helpers.h +++ b/src/node/gov/handlers/helpers.h @@ -8,12 +8,12 @@ namespace ccf::gov::endpoints::detail { - AuthnPolicies member_sig_only_policies(const std::string& gov_msg_type) + inline AuthnPolicies member_sig_only_policies(const std::string& gov_msg_type) { return {std::make_shared(gov_msg_type)}; } - AuthnPolicies active_member_sig_only_policies(const std::string& gov_msg_type) + inline AuthnPolicies active_member_sig_only_policies(const std::string& gov_msg_type) { return {std::make_shared(gov_msg_type)}; } @@ -60,7 +60,7 @@ namespace ccf::gov::endpoints::detail } // Extract memberId from path parameter, confirm it is a plausible ID - bool try_parse_member_id( + inline bool try_parse_member_id( const std::shared_ptr& rpc_ctx, ccf::MemberId& member_id) { // Extract member ID from path parameter @@ -96,7 +96,7 @@ namespace ccf::gov::endpoints::detail // Like try_parse_member_id, but also confirm that the parsed member ID // matches the COSE signer - bool try_parse_signed_member_id( + inline bool try_parse_signed_member_id( const ccf::MemberCOSESign1AuthnIdentity& cose_ident, const std::shared_ptr& rpc_ctx, ccf::MemberId& member_id) @@ -120,7 +120,7 @@ namespace ccf::gov::endpoints::detail } // Extract userId from path parameter, confirm it is a plausible ID - bool try_parse_user_id( + inline bool try_parse_user_id( const std::shared_ptr& rpc_ctx, ccf::UserId& user_id) { // Extract user ID from path parameter @@ -154,7 +154,7 @@ namespace ccf::gov::endpoints::detail } // Extract proposalId from path parameter, confirm it is a plausible ID - bool try_parse_proposal_id( + inline bool try_parse_proposal_id( const std::shared_ptr& rpc_ctx, ccf::ProposalId& proposal_id) { @@ -194,7 +194,7 @@ namespace ccf::gov::endpoints::detail // Like try_parse_proposal_id, but also confirm that the parsed proposal ID // matches a signed COSE header - bool try_parse_signed_proposal_id( + inline bool try_parse_signed_proposal_id( const ccf::MemberCOSESign1AuthnIdentity& cose_ident, const std::shared_ptr& rpc_ctx, ccf::ProposalId& proposal_id) @@ -222,7 +222,7 @@ namespace ccf::gov::endpoints::detail } // Extract nodeId from path parameter, confirm it is a plausible ID - bool try_parse_node_id( + inline bool try_parse_node_id( const std::shared_ptr& rpc_ctx, ccf::NodeId& node_id) { // Extract node ID from path parameter diff --git a/src/node/gov/handlers/proposals.h b/src/node/gov/handlers/proposals.h index ab0e2f922afb..36eb4fa61aa4 100644 --- a/src/node/gov/handlers/proposals.h +++ b/src/node/gov/handlers/proposals.h @@ -17,7 +17,7 @@ namespace ccf::gov::endpoints { struct ProposalSubmissionResult { - enum class Status + enum class Status : uint8_t { Acceptable, DuplicateInWindow, @@ -26,25 +26,30 @@ namespace ccf::gov::endpoints // May be empty, a colliding proposal ID, or a min_created_at value, // depending on status - std::string info = ""; + std::string info; }; - ProposalSubmissionResult validate_proposal_submission_time( + inline ProposalSubmissionResult validate_proposal_submission_time( ccf::kv::Tx& tx, const std::string& created_at, const std::vector& request_digest, const ccf::ProposalId& proposal_id) { - auto cose_recent_proposals = + auto* cose_recent_proposals = tx.rw(ccf::Tables::COSE_RECENT_PROPOSALS); auto key = fmt::format("{}:{}", created_at, ds::to_hex(request_digest)); if (cose_recent_proposals->has(key)) { - auto colliding_proposal_id = cose_recent_proposals->get(key).value(); - return { - ProposalSubmissionResult::Status::DuplicateInWindow, - colliding_proposal_id}; + auto colliding_proposal_id = cose_recent_proposals->get(key); + if (colliding_proposal_id.has_value()) + { + return { + ProposalSubmissionResult::Status::DuplicateInWindow, + *colliding_proposal_id}; + } + throw std::logic_error( + fmt::format("Failed to get value for existing key in {}", ccf::Tables::COSE_RECENT_PROPOSALS)); } std::vector replay_keys; @@ -71,7 +76,7 @@ namespace ccf::gov::endpoints } size_t window_size = ccf::default_recent_cose_proposals_window_size; - auto config_handle = + auto* config_handle = tx.ro(ccf::Tables::CONFIGURATION); auto config = config_handle->get(); if ( @@ -90,25 +95,25 @@ namespace ccf::gov::endpoints cose_recent_proposals->remove(replay_keys[i]); } } - return {ProposalSubmissionResult::Status::Acceptable}; + return {ProposalSubmissionResult::Status::Acceptable, {} /* reason */}; } - void record_cose_governance_history( + inline void record_cose_governance_history( ccf::kv::Tx& tx, const MemberId& caller_id, const std::span& cose_sign1) { - auto cose_governance_history = + auto* cose_governance_history = tx.wo(ccf::Tables::COSE_GOV_HISTORY); cose_governance_history->put( caller_id, {cose_sign1.begin(), cose_sign1.end()}); } - void remove_all_other_non_open_proposals( + inline void remove_all_other_non_open_proposals( ccf::kv::Tx& tx, const ProposalId& proposal_id) { - auto p = tx.rw(jsgov::Tables::PROPOSALS); - auto pi = + auto* p = tx.rw(jsgov::Tables::PROPOSALS); + auto* pi = tx.rw(jsgov::Tables::PROPOSALS_INFO); std::vector to_be_removed; pi->foreach( @@ -129,7 +134,7 @@ namespace ccf::gov::endpoints // Evaluate JS functions on this proposal. Result is presented in modified // proposal_info argument, which is written back to the KV by this function - void resolve_proposal( + inline void resolve_proposal( ccf::AbstractNodeContext& context, ccf::NetworkState& network, ccf::kv::Tx& tx, @@ -144,9 +149,9 @@ namespace ccf::gov::endpoints ccf::jsgov::VoteFailures vote_failures = {}; const std::string_view proposal{ - (const char*)proposal_bytes.data(), proposal_bytes.size()}; + reinterpret_cast(proposal_bytes.data()), proposal_bytes.size()}; - auto proposal_info_handle = tx.template rw( + auto* proposal_info_handle = tx.template rw( jsgov::Tables::PROPOSALS_INFO); // Evaluate ballots @@ -341,7 +346,7 @@ namespace ccf::gov::endpoints } } - nlohmann::json convert_proposal_to_api_format( + inline nlohmann::json convert_proposal_to_api_format( const ProposalId& proposal_id, const ccf::jsgov::ProposalInfo& summary) { auto response_body = nlohmann::json::object(); @@ -383,7 +388,7 @@ namespace ccf::gov::endpoints } } - void init_proposals_handlers( + inline void init_proposals_handlers( ccf::BaseEndpointRegistry& registry, NetworkState& network, ccf::AbstractNodeContext& node_context) @@ -569,9 +574,6 @@ namespace ccf::gov::endpoints const auto created_at_str = fmt::format( "{:0>10}", cose_ident.protected_header.gov_msg_created_at); - ccf::ProposalId colliding_proposal_id; - std::string min_created_at; - const auto subtime_result = detail::validate_proposal_submission_time( ctx.tx, created_at_str, request_digest, proposal_id); @@ -907,7 +909,7 @@ namespace ccf::gov::endpoints } // Look up proposal info and check expected state - auto proposal_info_handle = + auto* proposal_info_handle = ctx.tx.template rw( jsgov::Tables::PROPOSALS_INFO); auto proposal_info = proposal_info_handle->get(proposal_id); @@ -937,7 +939,7 @@ namespace ccf::gov::endpoints } // Look up proposal contents - auto proposals_handle = ctx.tx.template ro( + auto* proposals_handle = ctx.tx.template ro( ccf::jsgov::Tables::PROPOSALS); const auto proposal = proposals_handle->get(proposal_id); if (!proposal.has_value()) @@ -994,18 +996,16 @@ namespace ccf::gov::endpoints ctx.rpc_ctx->set_response_json(response_body, HTTP_STATUS_OK); return; } - else - { - detail::set_gov_error( - ctx.rpc_ctx, - HTTP_STATUS_BAD_REQUEST, - ccf::errors::VoteAlreadyExists, - fmt::format( - "Different ballot already submitted by {} for {}.", - member_id, - proposal_id)); - return; - } + + detail::set_gov_error( + ctx.rpc_ctx, + HTTP_STATUS_BAD_REQUEST, + ccf::errors::VoteAlreadyExists, + fmt::format( + "Different ballot already submitted by {} for {}.", + member_id, + proposal_id)); + return; } // Store newly provided ballot diff --git a/src/node/gov/handlers/recovery.h b/src/node/gov/handlers/recovery.h index c1d82aed3ff5..eb633c3a15d6 100644 --- a/src/node/gov/handlers/recovery.h +++ b/src/node/gov/handlers/recovery.h @@ -9,7 +9,7 @@ namespace ccf::gov::endpoints { - void init_recovery_handlers( + inline void init_recovery_handlers( ccf::BaseEndpointRegistry& registry, ShareManager& share_manager, ccf::AbstractNodeContext& node_context) diff --git a/src/node/gov/handlers/service_state.h b/src/node/gov/handlers/service_state.h index 118656e080a2..7e3c8ea0174f 100644 --- a/src/node/gov/handlers/service_state.h +++ b/src/node/gov/handlers/service_state.h @@ -7,7 +7,7 @@ namespace ccf::gov::endpoints { - nlohmann::json produce_member_description( + inline nlohmann::json produce_member_description( const ccf::MemberId& member_id, const ccf::MemberDetails& member_details, ccf::MemberCerts::ReadOnlyHandle* member_certs_handle, @@ -51,7 +51,7 @@ namespace ccf::gov::endpoints return member; } - nlohmann::json produce_user_description( + inline nlohmann::json produce_user_description( const ccf::UserId& user_id, const ccf::crypto::Pem& user_cert, ccf::UserInfo::ReadOnlyHandle* user_info_handle) @@ -69,7 +69,7 @@ namespace ccf::gov::endpoints return user; } - nlohmann::json produce_node_description( + inline nlohmann::json produce_node_description( const ccf::NodeId& node_id, const ccf::NodeInfo& node_info, ccf::NodeEndorsedCertificates::ReadOnlyHandle* node_endorsed_certs_handle) @@ -161,7 +161,7 @@ namespace ccf::gov::endpoints return node; } - void init_service_state_handlers(ccf::BaseEndpointRegistry& registry) + inline void init_service_state_handlers(ccf::BaseEndpointRegistry& registry) { auto get_constitution = [&](auto& ctx, ApiVersion api_version) { switch (api_version) @@ -245,7 +245,7 @@ namespace ccf::gov::endpoints { ccf::SeqNo seqno = service_info->previous_service_identity_version.value(); - ccf::View view; + ccf::View view = 0; // Note: deliberately ignoring errors. Prefer to return single // invalid field than convert entire response to error. registry.get_view_for_seqno_v1(seqno, view); diff --git a/src/node/gov/handlers/transactions.h b/src/node/gov/handlers/transactions.h index 786b97cfb78c..27446182b108 100644 --- a/src/node/gov/handlers/transactions.h +++ b/src/node/gov/handlers/transactions.h @@ -10,7 +10,7 @@ namespace ccf::gov::endpoints { - void init_transactions_handlers(ccf::BaseEndpointRegistry& registry) + inline void init_transactions_handlers(ccf::BaseEndpointRegistry& registry) { auto get_transaction_status = [&](auto& ctx, ApiVersion api_version) { switch (api_version) @@ -20,7 +20,8 @@ namespace ccf::gov::endpoints default: { // Extract transaction ID from path parameter - std::string tx_id_str, error; + std::string tx_id_str; + std::string error; if (!ccf::endpoints::get_path_param( ctx.rpc_ctx->get_request_path_params(), "transactionId", @@ -51,7 +52,7 @@ namespace ccf::gov::endpoints } // Lookup status - ccf::TxStatus status; + ccf::TxStatus status = ccf::TxStatus::Unknown; const auto result = registry.get_status_for_txid_v1(tx_id->view, tx_id->seqno, status); if (result != ccf::ApiResult::OK) @@ -94,8 +95,8 @@ namespace ccf::gov::endpoints default: { // Lookup committed - ccf::View view; - ccf::SeqNo seqno; + ccf::View view = 0; + ccf::SeqNo seqno = 0; auto result = registry.get_last_committed_txid_v1(view, seqno); if (result != ccf::ApiResult::OK) { @@ -110,7 +111,7 @@ namespace ccf::gov::endpoints } // Lookup status - ccf::TxStatus status; + ccf::TxStatus status = ccf::TxStatus::Unknown; result = registry.get_status_for_txid_v1(view, seqno, status); if (result != ccf::ApiResult::OK) { From 07c7418a5eb21b3bfa05ae6e5e9969fb9533191b Mon Sep 17 00:00:00 2001 From: Amaury Chamayou Date: Fri, 5 Dec 2025 14:38:03 +0000 Subject: [PATCH 06/18] more tidy --- .clang-tidy | 2 +- src/node/gov/handlers/helpers.h | 3 +- src/node/gov/handlers/proposals.h | 290 ++++++++++---------- src/node/rpc/call_types.h | 22 +- src/node/rpc/claims.h | 29 +- src/node/rpc/cosesigconfig_subsystem.h | 3 +- src/node/rpc/custom_protocol_subsystem.h | 17 +- src/node/rpc/file_serving_handlers.h | 13 +- src/node/rpc/forwarder.h | 24 +- src/node/rpc/frontend.h | 75 +++-- src/node/rpc/gov_effects_interface.h | 2 +- src/node/rpc/jwt_management.h | 69 +++-- src/node/rpc/network_identity_subsystem.h | 2 +- src/node/rpc/no_create_tx_claims_digest.cpp | 2 +- src/node/rpc/node_call_types.h | 27 +- src/node/rpc/node_frontend.h | 270 +++++++++--------- src/node/rpc/node_interface.h | 18 +- src/node/rpc/node_operation.h | 12 +- src/node/rpc/node_operation_interface.h | 14 +- 19 files changed, 441 insertions(+), 453 deletions(-) diff --git a/.clang-tidy b/.clang-tidy index bb121c427321..5682e37ce011 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -59,5 +59,5 @@ Checks: > -readability-magic-numbers, WarningsAsErrors: '*' -HeaderFilterRegex: '(include\/ccf\/|src\/(udp|tcp|tls|tasks|snapshots|service|quic|pal|apps|clients|common|consensus|ds|enclave|endpoints|host|indexing|http|node\/gov)\/).*' +HeaderFilterRegex: '(include\/ccf\/|src\/(udp|tcp|tls|tasks|snapshots|service|quic|pal|apps|clients|common|consensus|ds|enclave|endpoints|host|indexing|http|node\/gov|node\/rpc)\/).*' FormatStyle: 'file' \ No newline at end of file diff --git a/src/node/gov/handlers/helpers.h b/src/node/gov/handlers/helpers.h index ef07f8e25535..aed08215f964 100644 --- a/src/node/gov/handlers/helpers.h +++ b/src/node/gov/handlers/helpers.h @@ -13,7 +13,8 @@ namespace ccf::gov::endpoints::detail return {std::make_shared(gov_msg_type)}; } - inline AuthnPolicies active_member_sig_only_policies(const std::string& gov_msg_type) + inline AuthnPolicies active_member_sig_only_policies( + const std::string& gov_msg_type) { return {std::make_shared(gov_msg_type)}; } diff --git a/src/node/gov/handlers/proposals.h b/src/node/gov/handlers/proposals.h index 36eb4fa61aa4..6dbe904238c8 100644 --- a/src/node/gov/handlers/proposals.h +++ b/src/node/gov/handlers/proposals.h @@ -48,8 +48,9 @@ namespace ccf::gov::endpoints ProposalSubmissionResult::Status::DuplicateInWindow, *colliding_proposal_id}; } - throw std::logic_error( - fmt::format("Failed to get value for existing key in {}", ccf::Tables::COSE_RECENT_PROPOSALS)); + throw std::logic_error(fmt::format( + "Failed to get value for existing key in {}", + ccf::Tables::COSE_RECENT_PROPOSALS)); } std::vector replay_keys; @@ -149,7 +150,8 @@ namespace ccf::gov::endpoints ccf::jsgov::VoteFailures vote_failures = {}; const std::string_view proposal{ - reinterpret_cast(proposal_bytes.data()), proposal_bytes.size()}; + reinterpret_cast(proposal_bytes.data()), + proposal_bytes.size()}; auto* proposal_info_handle = tx.template rw( jsgov::Tables::PROPOSALS_INFO); @@ -883,169 +885,169 @@ namespace ccf::gov::endpoints .install(); //// implementation of TSP interface Ballots - auto submit_ballot = - [&](ccf::endpoints::EndpointContext& ctx, ApiVersion api_version) { - switch (api_version) + auto submit_ballot = [&]( + ccf::endpoints::EndpointContext& ctx, + ApiVersion api_version) { + switch (api_version) + { + case ApiVersion::preview_v1: + case ApiVersion::v1: + default: { - case ApiVersion::preview_v1: - case ApiVersion::v1: - default: - { - const auto& cose_ident = - ctx.template get_caller(); + const auto& cose_ident = + ctx.template get_caller(); - ccf::ProposalId proposal_id; - if (!detail::try_parse_signed_proposal_id( - cose_ident, ctx.rpc_ctx, proposal_id)) - { - return; - } + ccf::ProposalId proposal_id; + if (!detail::try_parse_signed_proposal_id( + cose_ident, ctx.rpc_ctx, proposal_id)) + { + return; + } - ccf::MemberId member_id; - if (!detail::try_parse_signed_member_id( - cose_ident, ctx.rpc_ctx, member_id)) - { - return; - } + ccf::MemberId member_id; + if (!detail::try_parse_signed_member_id( + cose_ident, ctx.rpc_ctx, member_id)) + { + return; + } - // Look up proposal info and check expected state - auto* proposal_info_handle = - ctx.tx.template rw( - jsgov::Tables::PROPOSALS_INFO); - auto proposal_info = proposal_info_handle->get(proposal_id); - if (!proposal_info.has_value()) - { - detail::set_gov_error( - ctx.rpc_ctx, - HTTP_STATUS_NOT_FOUND, - ccf::errors::ProposalNotFound, - fmt::format("Could not find proposal {}.", proposal_id)); - return; - } + // Look up proposal info and check expected state + auto* proposal_info_handle = + ctx.tx.template rw( + jsgov::Tables::PROPOSALS_INFO); + auto proposal_info = proposal_info_handle->get(proposal_id); + if (!proposal_info.has_value()) + { + detail::set_gov_error( + ctx.rpc_ctx, + HTTP_STATUS_NOT_FOUND, + ccf::errors::ProposalNotFound, + fmt::format("Could not find proposal {}.", proposal_id)); + return; + } - if (proposal_info->state != ccf::ProposalState::OPEN) - { - detail::set_gov_error( - ctx.rpc_ctx, - HTTP_STATUS_BAD_REQUEST, - ccf::errors::ProposalNotOpen, - fmt::format( - "Proposal {} is currently in state {} - only {} proposals " - "can receive votes", - proposal_id, - proposal_info->state, - ProposalState::OPEN)); - return; - } + if (proposal_info->state != ccf::ProposalState::OPEN) + { + detail::set_gov_error( + ctx.rpc_ctx, + HTTP_STATUS_BAD_REQUEST, + ccf::errors::ProposalNotOpen, + fmt::format( + "Proposal {} is currently in state {} - only {} proposals " + "can receive votes", + proposal_id, + proposal_info->state, + ProposalState::OPEN)); + return; + } - // Look up proposal contents - auto* proposals_handle = ctx.tx.template ro( - ccf::jsgov::Tables::PROPOSALS); - const auto proposal = proposals_handle->get(proposal_id); - if (!proposal.has_value()) - { - detail::set_gov_error( - ctx.rpc_ctx, - HTTP_STATUS_NOT_FOUND, - ccf::errors::ProposalNotFound, - fmt::format("Could not find proposal {}.", proposal_id)); - return; - } + // Look up proposal contents + auto* proposals_handle = ctx.tx.template ro( + ccf::jsgov::Tables::PROPOSALS); + const auto proposal = proposals_handle->get(proposal_id); + if (!proposal.has_value()) + { + detail::set_gov_error( + ctx.rpc_ctx, + HTTP_STATUS_NOT_FOUND, + ccf::errors::ProposalNotFound, + fmt::format("Could not find proposal {}.", proposal_id)); + return; + } - // Parse and validate incoming ballot - const auto params = nlohmann::json::parse(cose_ident.content); - const auto ballot_it = params.find("ballot"); - if (ballot_it == params.end() || !ballot_it.value().is_string()) - { - detail::set_gov_error( - ctx.rpc_ctx, - HTTP_STATUS_BAD_REQUEST, - ccf::errors::InvalidInput, - "Signed request body is not a JSON object containing required " - "string field \"ballot\""); - return; - } + // Parse and validate incoming ballot + const auto params = nlohmann::json::parse(cose_ident.content); + const auto ballot_it = params.find("ballot"); + if (ballot_it == params.end() || !ballot_it.value().is_string()) + { + detail::set_gov_error( + ctx.rpc_ctx, + HTTP_STATUS_BAD_REQUEST, + ccf::errors::InvalidInput, + "Signed request body is not a JSON object containing required " + "string field \"ballot\""); + return; + } - // Access constitution to evaluate ballots - const auto constitution = - ctx.tx.template ro(ccf::Tables::CONSTITUTION) - ->get(); - if (!constitution.has_value()) - { - detail::set_gov_error( - ctx.rpc_ctx, - HTTP_STATUS_INTERNAL_SERVER_ERROR, - ccf::errors::InternalError, - "No constitution is set - ballots cannot be evaluated"); - return; - } + // Access constitution to evaluate ballots + const auto constitution = + ctx.tx.template ro(ccf::Tables::CONSTITUTION) + ->get(); + if (!constitution.has_value()) + { + detail::set_gov_error( + ctx.rpc_ctx, + HTTP_STATUS_INTERNAL_SERVER_ERROR, + ccf::errors::InternalError, + "No constitution is set - ballots cannot be evaluated"); + return; + } - const auto ballot = ballot_it.value().get(); + const auto ballot = ballot_it.value().get(); - const auto info_ballot_it = proposal_info->ballots.find(member_id); - if (info_ballot_it != proposal_info->ballots.end()) + const auto info_ballot_it = proposal_info->ballots.find(member_id); + if (info_ballot_it != proposal_info->ballots.end()) + { + // If ballot matches previously submitted, aim for idempotent + // matching response + if (info_ballot_it->second == ballot) { - // If ballot matches previously submitted, aim for idempotent - // matching response - if (info_ballot_it->second == ballot) - { - const auto response_body = - detail::convert_proposal_to_api_format( - proposal_id, proposal_info.value()); - - ctx.rpc_ctx->set_response_json(response_body, HTTP_STATUS_OK); - return; - } + const auto response_body = detail::convert_proposal_to_api_format( + proposal_id, proposal_info.value()); - detail::set_gov_error( - ctx.rpc_ctx, - HTTP_STATUS_BAD_REQUEST, - ccf::errors::VoteAlreadyExists, - fmt::format( - "Different ballot already submitted by {} for {}.", - member_id, - proposal_id)); + ctx.rpc_ctx->set_response_json(response_body, HTTP_STATUS_OK); return; } - // Store newly provided ballot - proposal_info->ballots.insert_or_assign( - info_ballot_it, member_id, ballot_it.value().get()); - - detail::record_cose_governance_history( - ctx.tx, cose_ident.member_id, cose_ident.envelope); + detail::set_gov_error( + ctx.rpc_ctx, + HTTP_STATUS_BAD_REQUEST, + ccf::errors::VoteAlreadyExists, + fmt::format( + "Different ballot already submitted by {} for {}.", + member_id, + proposal_id)); + return; + } - detail::resolve_proposal( - node_context, - network, - ctx.tx, - proposal_id, - proposal.value(), - proposal_info.value(), - constitution.value()); + // Store newly provided ballot + proposal_info->ballots.insert_or_assign( + info_ballot_it, member_id, ballot_it.value().get()); - if (proposal_info->state == ProposalState::FAILED) - { - // If the proposal failed to apply, we want to discard the tx and - // not apply its side-effects to the KV state, because it may have - // failed mid-execution (eg - thrown an exception), in which case - // we do not want to apply partial writes - detail::set_gov_error( - ctx.rpc_ctx, - HTTP_STATUS_INTERNAL_SERVER_ERROR, - ccf::errors::InternalError, - fmt::format("{}", proposal_info->failure)); - return; - } + detail::record_cose_governance_history( + ctx.tx, cose_ident.member_id, cose_ident.envelope); - const auto response_body = detail::convert_proposal_to_api_format( - proposal_id, proposal_info.value()); + detail::resolve_proposal( + node_context, + network, + ctx.tx, + proposal_id, + proposal.value(), + proposal_info.value(), + constitution.value()); - ctx.rpc_ctx->set_response_json(response_body, HTTP_STATUS_OK); + if (proposal_info->state == ProposalState::FAILED) + { + // If the proposal failed to apply, we want to discard the tx and + // not apply its side-effects to the KV state, because it may have + // failed mid-execution (eg - thrown an exception), in which case + // we do not want to apply partial writes + detail::set_gov_error( + ctx.rpc_ctx, + HTTP_STATUS_INTERNAL_SERVER_ERROR, + ccf::errors::InternalError, + fmt::format("{}", proposal_info->failure)); return; } + + const auto response_body = detail::convert_proposal_to_api_format( + proposal_id, proposal_info.value()); + + ctx.rpc_ctx->set_response_json(response_body, HTTP_STATUS_OK); + return; } - }; + } + }; registry .make_endpoint( "/members/proposals/{proposalId}/ballots/{memberId}:submit", diff --git a/src/node/rpc/call_types.h b/src/node/rpc/call_types.h index 87de70bf9cb6..cff3a82ed6c4 100644 --- a/src/node/rpc/call_types.h +++ b/src/node/rpc/call_types.h @@ -33,7 +33,7 @@ namespace ccf struct Out { ccf::TxID transaction_id; - TxStatus status; + TxStatus status{}; }; }; @@ -42,12 +42,12 @@ namespace ccf struct Version { std::string digest; - ccf::CodeStatus status; + ccf::CodeStatus status{}; }; struct Out { - std::vector versions = {}; + std::vector versions; }; }; @@ -61,7 +61,7 @@ namespace ccf struct Out { - std::vector host_data = {}; + std::vector host_data; }; }; @@ -69,11 +69,11 @@ namespace ccf { struct Out { - ServiceStatus service_status; + ServiceStatus service_status{}; ccf::crypto::Pem service_certificate; std::optional current_view; std::optional primary_id; - size_t recovery_count; + size_t recovery_count{}; nlohmann::json service_data; std::optional current_service_create_txid; }; @@ -84,11 +84,11 @@ namespace ccf struct NodeInfo { NodeId node_id; - NodeStatus status; - bool primary; + NodeStatus status{}; + bool primary{}; ccf::NodeInfoNetwork::RpcInterfaces rpc_interfaces; nlohmann::json node_data; - ccf::SeqNo last_written; + ccf::SeqNo last_written{}; }; using Out = NodeInfo; @@ -98,7 +98,7 @@ namespace ccf { struct Out { - std::vector nodes = {}; + std::vector nodes; }; }; @@ -111,7 +111,7 @@ namespace ccf { struct In { - std::vector receipt = {}; + std::vector receipt; }; struct Out diff --git a/src/node/rpc/claims.h b/src/node/rpc/claims.h index 76a30a1d144e..8a3cec033277 100644 --- a/src/node/rpc/claims.h +++ b/src/node/rpc/claims.h @@ -9,7 +9,7 @@ namespace ccf { static ClaimsDigest no_claims() { - return ClaimsDigest(); + return {}; } static ccf::crypto::Sha256Hash entry_leaf( @@ -23,27 +23,18 @@ namespace ccf { if (claims_digest.empty()) { - return ccf::crypto::Sha256Hash( - write_set_digest, commit_evidence_digest.value()); - } - else - { - return ccf::crypto::Sha256Hash( - write_set_digest, - commit_evidence_digest.value(), - claims_digest.value()); + return {write_set_digest, commit_evidence_digest.value()}; } + return { + write_set_digest, + commit_evidence_digest.value(), + claims_digest.value()}; } - else + + if (claims_digest.empty()) { - if (claims_digest.empty()) - { - return ccf::crypto::Sha256Hash(write_set_digest); - } - else - { - return ccf::crypto::Sha256Hash(write_set_digest, claims_digest.value()); - } + return {write_set_digest}; } + return {write_set_digest, claims_digest.value()}; } } \ No newline at end of file diff --git a/src/node/rpc/cosesigconfig_subsystem.h b/src/node/rpc/cosesigconfig_subsystem.h index 153c7a36be2b..57c1bdec2b2f 100644 --- a/src/node/rpc/cosesigconfig_subsystem.h +++ b/src/node/rpc/cosesigconfig_subsystem.h @@ -17,7 +17,8 @@ namespace ccf node_state(node_state_) {} - virtual const ccf::COSESignaturesConfig& get_cose_signatures_config() const + [[nodiscard]] const ccf::COSESignaturesConfig& get_cose_signatures_config() + const override { return node_state.get_cose_signatures_config(); } diff --git a/src/node/rpc/custom_protocol_subsystem.h b/src/node/rpc/custom_protocol_subsystem.h index a2a4c928b466..ef93a25d1d5c 100644 --- a/src/node/rpc/custom_protocol_subsystem.h +++ b/src/node/rpc/custom_protocol_subsystem.h @@ -25,19 +25,19 @@ namespace ccf node_state(node_state_) {} - virtual void install( + void install( const std::string& protocol_name, CreateSessionFn create_session_f) override { session_creation_functions[protocol_name] = create_session_f; } - virtual void uninstall(const std::string& protocol_name) override + void uninstall(const std::string& protocol_name) override { session_creation_functions.erase(protocol_name); } - virtual std::shared_ptr create_session( + std::shared_ptr create_session( const std::string& protocol_name, ccf::tls::ConnID conn_id, const std::unique_ptr&& ctx) override @@ -47,15 +47,12 @@ namespace ccf { return it->second(conn_id, std::move(ctx)); } - else - { - throw std::logic_error(fmt::format( - "Session creation function for protocol '{}' has not been installed", - protocol_name)); - } + throw std::logic_error(fmt::format( + "Session creation function for protocol '{}' has not been installed", + protocol_name)); } - virtual std::shared_ptr get_essentials() override + std::shared_ptr get_essentials() override { std::shared_ptr r = std::make_shared(); r->writer = node_state.get_writer_factory().create_writer_to_outside(); diff --git a/src/node/rpc/file_serving_handlers.h b/src/node/rpc/file_serving_handlers.h index befe19169e9a..a853ee1d7c2e 100644 --- a/src/node/rpc/file_serving_handlers.h +++ b/src/node/rpc/file_serving_handlers.h @@ -18,7 +18,7 @@ namespace ccf::node ccf::kv::ReadOnlyTx& ro_tx, const ccf::NodeId& target_node) { - auto nodes = ro_tx.ro(ccf::Tables::NODES); + auto* nodes = ro_tx.ro(ccf::Tables::NODES); auto node_info = nodes->get(target_node); if (!node_info.has_value()) @@ -85,7 +85,7 @@ namespace ccf::node if (snapshot_since.has_value()) { - if (error_reason != "") + if (!error_reason.empty()) { ctx.rpc_ctx->set_error( HTTP_STATUS_BAD_REQUEST, @@ -252,7 +252,7 @@ namespace ccf::node LOG_DEBUG_FMT("Found snapshot: {}", snapshot_path.string()); - f.seekg(0, f.end); + f.seekg(0, std::ifstream::end); const auto total_size = (size_t)f.tellg(); ctx.rpc_ctx->set_response_header("accept-ranges", "bytes"); @@ -286,7 +286,7 @@ namespace ccf::node return; } - if (ranges.find(",") != std::string::npos) + if (ranges.find(',') != std::string::npos) { ctx.rpc_ctx->set_error( HTTP_STATUS_BAD_REQUEST, @@ -392,7 +392,7 @@ namespace ccf::node if (!s_range_end.empty()) { // Negative range, like "-Y" - size_t offset; + size_t offset = 0; const auto [p, ec] = std::from_chars(s_range_end.begin(), s_range_end.end(), offset); if (ec != std::errc()) @@ -433,7 +433,8 @@ namespace ccf::node // Read requested range into buffer std::vector contents(range_size); f.seekg(range_start); - f.read((char*)contents.data(), contents.size()); + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) + f.read(reinterpret_cast(contents.data()), contents.size()); f.close(); // Build successful response diff --git a/src/node/rpc/forwarder.h b/src/node/rpc/forwarder.h index b804e95b6261..bc3ed2374037 100644 --- a/src/node/rpc/forwarder.h +++ b/src/node/rpc/forwarder.h @@ -18,7 +18,7 @@ namespace ccf class ForwardedRpcHandler { public: - virtual ~ForwardedRpcHandler() {} + virtual ~ForwardedRpcHandler() = default; virtual void process_forwarded( std::shared_ptr fwd_ctx) = 0; @@ -68,9 +68,9 @@ namespace ccf std::weak_ptr rpcresponder, std::shared_ptr n2n_channels, std::weak_ptr rpc_map_) : - rpcresponder(rpcresponder), - n2n_channels(n2n_channels), - rpc_map(rpc_map_) + rpcresponder(std::move(rpcresponder)), + n2n_channels(std::move(n2n_channels)), + rpc_map(std::move(rpc_map_)) {} void initialize(const NodeId& self_) @@ -87,7 +87,6 @@ namespace ccf auto session_ctx = rpc_ctx->get_session_context(); IsCallerCertForwarded include_caller = false; - const auto method = rpc_ctx->get_method(); const auto& raw_request = rpc_ctx->get_serialised_request(); auto client_session_id = session_ctx->client_session_id; size_t size = sizeof(client_session_id) + sizeof(IsCallerCertForwarded) + @@ -99,7 +98,7 @@ namespace ccf } std::vector plain(size); - auto data_ = plain.data(); + auto* data_ = plain.data(); auto size_ = plain.size(); serialized::write(data_, size_, client_session_id); serialized::write(data_, size_, include_caller); @@ -110,13 +109,14 @@ namespace ccf } serialized::write(data_, size_, raw_request.data(), raw_request.size()); - ForwardedCommandId command_id; + ForwardedCommandId command_id = 0; { std::lock_guard guard(timeout_tasks_lock); command_id = next_command_id++; - auto task = ccf::tasks::make_basic_task([=, this]() { - this->send_timeout_error_response(to, client_session_id, timeout); - }); + auto task = + ccf::tasks::make_basic_task([this, to, client_session_id, timeout]() { + this->send_timeout_error_response(to, client_session_id, timeout); + }); timeout_tasks[command_id] = task; ccf::tasks::add_delayed_task(task, timeout); } @@ -203,7 +203,7 @@ namespace ccf const std::vector& data) { std::vector plain(sizeof(client_session_id) + data.size()); - auto data_ = plain.data(); + auto* data_ = plain.data(); auto size_ = plain.size(); serialized::write(data_, size_, client_session_id); serialized::write(data_, size_, data.data(), data.size()); @@ -217,7 +217,7 @@ namespace ccf struct ForwardedResponseResult { - size_t client_session_id; + size_t client_session_id{}; std::vector response_body; bool should_terminate_session = false; }; diff --git a/src/node/rpc/frontend.h b/src/node/rpc/frontend.h index a5bdf80bcdcf..9b41847d3aa8 100644 --- a/src/node/rpc/frontend.h +++ b/src/node/rpc/frontend.h @@ -41,9 +41,9 @@ namespace ccf ccf::pal::Mutex open_lock; bool is_open_ = false; - ccf::kv::Consensus* consensus; + ccf::kv::Consensus* consensus{nullptr}; std::shared_ptr cmd_forwarder; - ccf::kv::TxHistory* history; + ccf::kv::TxHistory* history{nullptr}; size_t sig_tx_interval = 5000; std::chrono::milliseconds sig_ms_interval = std::chrono::milliseconds(1000); @@ -54,7 +54,7 @@ namespace ccf void update_consensus() { - auto c = tables.get_consensus().get(); + auto* c = tables.get_consensus().get(); if (consensus != c) { @@ -124,7 +124,7 @@ namespace ccf const endpoints::EndpointDefinitionPtr& endpoint) { auto interface_id = ctx->get_session_context()->interface_id; - if (consensus && interface_id) + if ((consensus != nullptr) && interface_id) { if (!node_configuration_subsystem) { @@ -137,7 +137,7 @@ namespace ccf } } - auto& ncs = node_configuration_subsystem->get(); + const auto& ncs = node_configuration_subsystem->get(); const auto& required_features = endpoint->required_operator_features; if (!required_features.empty()) @@ -196,7 +196,9 @@ namespace ccf else { auto icfg = ncs.node_config.network.rpc_interfaces.at(*interface_id); - if (icfg.endorsement->authority == Authority::UNSECURED) + if ( + icfg.endorsement.has_value() && + icfg.endorsement->authority == Authority::UNSECURED) { // Unsecured interfaces are opt-in only. LOG_FAIL_FMT( @@ -267,7 +269,8 @@ namespace ccf return std::nullopt; } - const auto node_it = target_node_its[rand() % target_node_its.size()]; + const auto node_it = + target_node_its[random() % target_node_its.size()]; if (node_it != nodes.end()) { const auto& interfaces = node_it->second.rpc_interfaces; @@ -427,13 +430,15 @@ namespace ccf // First request on this session - assign the active term session_ctx->active_view = current_view; } - else if (current_view != session_ctx->active_view.value()) + // NOLINTNEXTLINE(bugprone-unchecked-optional-access) + else if (current_view != *session_ctx->active_view) { auto msg = fmt::format( "Potential loss of session consistency on session {}. Started " "in view {}, now in view {}. Closing session.", session_ctx->client_session_id, - session_ctx->active_view.value(), + *session_ctx // NOLINT(bugprone-unchecked-optional-access) + ->active_view, current_view); LOG_INFO_FMT("{}", msg); @@ -470,14 +475,11 @@ namespace ccf { break; } - else - { - // Collate error details - error_details.emplace_back(ODataAuthErrorDetails{ - policy->get_security_scheme_name(), - ccf::errors::InvalidAuthenticationInfo, - auth_error_reason}); - } + // Collate error details + error_details.emplace_back(ODataAuthErrorDetails{ + policy->get_security_scheme_name(), + ccf::errors::InvalidAuthenticationInfo, + auth_error_reason}); } if (identity == nullptr) @@ -488,21 +490,22 @@ namespace ccf // Return collated error details for the auth policies // declared in the request std::vector json_details; + json_details.reserve(error_details.size()); for (auto& details : error_details) { - json_details.push_back(details); + json_details.emplace_back(details); } ctx->set_error( HTTP_STATUS_UNAUTHORIZED, ccf::errors::InvalidAuthenticationInfo, "Invalid authentication credentials.", - std::move(json_details)); + json_details); } return identity; } - std::chrono::milliseconds get_forwarding_timeout( + [[nodiscard]] std::chrono::milliseconds get_forwarding_timeout( std::shared_ptr ctx) const { auto r = std::chrono::milliseconds(3'000); @@ -510,12 +513,13 @@ namespace ccf auto interface_id = ctx->get_session_context()->interface_id; if (interface_id.has_value()) { - auto& ncs = node_configuration_subsystem->get(); + const auto& ncs = node_configuration_subsystem->get(); auto rit = ncs.node_config.network.rpc_interfaces.find(*interface_id); if (rit != ncs.node_config.network.rpc_interfaces.end()) { if (rit->second.forwarding_timeout_ms.has_value()) { + // NOLINTNEXTLINE(bugprone-unchecked-optional-access) r = std::chrono::milliseconds(*rit->second.forwarding_timeout_ms); } } @@ -526,8 +530,8 @@ namespace ccf void forward( std::shared_ptr ctx, - ccf::kv::ReadOnlyTx& tx, - const endpoints::EndpointDefinitionPtr& endpoint) + ccf::kv::ReadOnlyTx& /*tx*/, + const endpoints::EndpointDefinitionPtr& /*endpoint*/) { // HTTP/2 does not support forwarding if (ctx->get_http_version() == HttpVersion::HTTP2) @@ -540,7 +544,7 @@ namespace ccf return; } - if (!cmd_forwarder || !consensus) + if (!cmd_forwarder || (consensus == nullptr)) { ctx->set_error( HTTP_STATUS_INTERNAL_SERVER_ERROR, @@ -602,8 +606,6 @@ namespace ccf // Ensure future requests on this session are forwarded for session // consistency ctx->get_session_context()->is_forwarding = true; - - return; } void process_command(std::shared_ptr ctx) @@ -708,14 +710,15 @@ namespace ccf if (ctx->get_session_context()->interface_id.has_value()) { redirections = get_redirections_config( - ctx->get_session_context()->interface_id.value()); + // NOLINTNEXTLINE(bugprone-unchecked-optional-access) + *ctx->get_session_context()->interface_id); } // If a redirections config was specified, then redirections are used // and no forwarding is done if (redirections.has_value()) { - if (check_redirect(*tx_p, ctx, endpoint, redirections.value())) + if (check_redirect(*tx_p, ctx, endpoint, *redirections)) { return; } @@ -769,10 +772,7 @@ namespace ccf { return; } - else - { - args.caller = std::move(identity); - } + args.caller = std::move(identity); } endpoints.execute_endpoint(endpoint, args); @@ -793,7 +793,8 @@ namespace ccf { return; } - else if (args.owned_tx == nullptr) + + if (args.owned_tx == nullptr) { LOG_FAIL_FMT( "Bad endpoint: During execution of {} {}, returned a non-pending " @@ -945,8 +946,6 @@ namespace ccf static constexpr size_t retry_after_seconds = 3; ctx->set_response_header(http::headers::RETRY_AFTER, retry_after_seconds); - - return; } public: @@ -956,9 +955,7 @@ namespace ccf ccf::AbstractNodeContext& node_context_) : tables(tables_), endpoints(handlers_), - node_context(node_context_), - consensus(nullptr), - history(nullptr) + node_context(node_context_) {} void set_sig_intervals( @@ -998,7 +995,7 @@ namespace ccf if (endpoints.request_needs_root(ctx)) { update_history(); - if (history) + if (history != nullptr) { // Warning: Retrieving the current TxID and root from the history // should only ever be used for the proposal creation endpoint and diff --git a/src/node/rpc/gov_effects_interface.h b/src/node/rpc/gov_effects_interface.h index c9afdc1c14ab..e33aa3ca24a7 100644 --- a/src/node/rpc/gov_effects_interface.h +++ b/src/node/rpc/gov_effects_interface.h @@ -11,7 +11,7 @@ namespace ccf class AbstractGovernanceEffects : public ccf::AbstractNodeSubSystem { public: - virtual ~AbstractGovernanceEffects() = default; + ~AbstractGovernanceEffects() override = default; static char const* get_subsystem_name() { diff --git a/src/node/rpc/jwt_management.h b/src/node/rpc/jwt_management.h index 8ea040b76c63..228e4d70f58a 100644 --- a/src/node/rpc/jwt_management.h +++ b/src/node/rpc/jwt_management.h @@ -13,11 +13,14 @@ #include #include -namespace +namespace ccf::jwt_management_detail { - std::vector try_parse_raw_rsa(const ccf::crypto::JsonWebKeyData& jwk) + inline std::vector try_parse_raw_rsa( + const ccf::crypto::JsonWebKeyData& jwk) { - if (!jwk.e || jwk.e->empty() || !jwk.n || jwk.n->empty()) + if ( + !jwk.kid.has_value() || !jwk.e.has_value() || jwk.e->empty() || + !jwk.n.has_value() || jwk.n->empty()) { return {}; } @@ -25,9 +28,9 @@ namespace std::vector der; ccf::crypto::JsonWebKeyRSAPublic data; data.kty = ccf::crypto::JsonWebKeyType::RSA; - data.kid = jwk.kid.value(); - data.n = jwk.n.value(); - data.e = jwk.e.value(); + data.kid = *jwk.kid; + data.n = *jwk.n; + data.e = *jwk.e; try { const auto pubkey = ccf::crypto::make_rsa_public_key(data); @@ -40,19 +43,22 @@ namespace } } - std::vector try_parse_raw_ec(const ccf::crypto::JsonWebKeyData& jwk) + inline std::vector try_parse_raw_ec( + const ccf::crypto::JsonWebKeyData& jwk) { - if (!jwk.x || jwk.x->empty() || !jwk.y || jwk.y->empty() || !jwk.crv) + if ( + !jwk.kid.has_value() || !jwk.x.has_value() || jwk.x->empty() || + !jwk.y.has_value() || jwk.y->empty() || !jwk.crv.has_value()) { return {}; } ccf::crypto::JsonWebKeyECPublic data; data.kty = ccf::crypto::JsonWebKeyType::EC; - data.kid = jwk.kid.value(); - data.crv = jwk.crv.value(); - data.x = jwk.x.value(); - data.y = jwk.y.value(); + data.kid = *jwk.kid; + data.crv = *jwk.crv; + data.x = *jwk.x; + data.y = *jwk.y; try { const auto pubkey = ccf::crypto::make_ec_public_key(data); @@ -65,15 +71,16 @@ namespace } } - std::vector try_parse_x5c(const ccf::crypto::JsonWebKeyData& jwk) + inline std::vector try_parse_x5c( + const ccf::crypto::JsonWebKeyData& jwk) { - if (!jwk.x5c || jwk.x5c->empty()) + if (!jwk.kid.has_value() || !jwk.x5c.has_value() || jwk.x5c->empty()) { return {}; } - const auto& kid = jwk.kid.value(); - auto& der_base64 = jwk.x5c.value()[0]; + const auto& kid = *jwk.kid; + const auto& der_base64 = (*jwk.x5c)[0]; ccf::Cert der; try { @@ -96,9 +103,14 @@ namespace } } - std::vector try_parse_jwk(const ccf::crypto::JsonWebKeyData& jwk) + inline std::vector try_parse_jwk( + const ccf::crypto::JsonWebKeyData& jwk) { - const auto& kid = jwk.kid.value(); + if (!jwk.kid.has_value()) + { + throw std::logic_error("Missing kid for JWT signing key"); + } + const auto& kid = *jwk.kid; auto key = try_parse_raw_rsa(jwk); if (!key.empty()) { @@ -156,7 +168,7 @@ namespace ccf static void remove_jwt_public_signing_keys( ccf::kv::Tx& tx, std::string issuer) { - auto keys = tx.rw( + auto* keys = tx.rw( Tables::JWT_PUBLIC_SIGNING_KEYS_METADATA); keys->foreach([&issuer, &keys](const auto& k, const auto& v) { @@ -186,10 +198,10 @@ namespace ccf ccf::kv::Tx& tx, const std::string& log_prefix, std::string issuer, - const JwtIssuerMetadata& issuer_metadata, + const JwtIssuerMetadata& /*issuer_metadata*/, const JsonWebKeySet& jwks) { - auto keys = tx.rw( + auto* keys = tx.rw( Tables::JWT_PUBLIC_SIGNING_KEYS_METADATA); // add keys if (jwks.keys.empty()) @@ -202,15 +214,15 @@ namespace ccf try { - for (auto& jwk : jwks.keys) + for (const auto& jwk : jwks.keys) { if (!jwk.kid.has_value()) { throw std::logic_error("Missing kid for JWT signing key"); } - const auto& kid = jwk.kid.value(); - auto key_der = try_parse_jwk(jwk); + const auto& kid = *jwk.kid; + auto key_der = jwt_management_detail::try_parse_jwk(jwk); if (jwk.issuer) { @@ -267,10 +279,11 @@ namespace ccf value.constraint = it->second; } - if (existing_kids.count(kid)) + if (existing_kids.contains(kid)) { const auto& keys_for_kid = keys->get(kid); if ( + keys_for_kid.has_value() && find_if( keys_for_kid->begin(), keys_for_kid->end(), @@ -317,11 +330,15 @@ namespace ccf } } - for (auto& kid : existing_kids) + for (const auto& kid : existing_kids) { if (!new_keys.contains(kid)) { auto updated = keys->get(kid); + if (!updated.has_value()) + { + continue; + } updated->erase( std::remove_if( updated->begin(), diff --git a/src/node/rpc/network_identity_subsystem.h b/src/node/rpc/network_identity_subsystem.h index 618e97c4ed34..5e6101a5bcd3 100644 --- a/src/node/rpc/network_identity_subsystem.h +++ b/src/node/rpc/network_identity_subsystem.h @@ -22,7 +22,7 @@ namespace ccf network_identity(network_identity_) {} - virtual const std::unique_ptr& get() override + const std::unique_ptr& get() override { return network_identity; } diff --git a/src/node/rpc/no_create_tx_claims_digest.cpp b/src/node/rpc/no_create_tx_claims_digest.cpp index 0910336b0312..c5adca27eea3 100644 --- a/src/node/rpc/no_create_tx_claims_digest.cpp +++ b/src/node/rpc/no_create_tx_claims_digest.cpp @@ -8,7 +8,7 @@ namespace ccf { std::optional __attribute__((weak)) - get_create_tx_claims_digest(ccf::kv::ReadOnlyTx& tx) + get_create_tx_claims_digest(ccf::kv::ReadOnlyTx& /*tx*/) { return std::nullopt; } diff --git a/src/node/rpc/node_call_types.h b/src/node/rpc/node_call_types.h index bff46d634577..7a26af1b34ee 100644 --- a/src/node/rpc/node_call_types.h +++ b/src/node/rpc/node_call_types.h @@ -28,15 +28,15 @@ namespace ccf struct Out { ccf::NodeId node_id; - ccf::NodeStartupState state; - ccf::kv::Version last_signed_seqno; - ccf::kv::Version startup_seqno; + ccf::NodeStartupState state{}; + ccf::kv::Version last_signed_seqno{}; + ccf::kv::Version startup_seqno{}; // Only on recovery std::optional recovery_target_seqno; std::optional last_recovered_seqno; - bool stop_notice; + bool stop_notice{}; }; }; @@ -48,7 +48,7 @@ namespace ccf { std::string ccf_version; std::string quickjs_version; - bool unsafe; + bool unsafe{}; }; }; @@ -92,7 +92,7 @@ namespace ccf struct Out { - NodeStatus node_status; + NodeStatus node_status{}; // Deprecated in 2.x std::optional node_id = std::nullopt; @@ -109,24 +109,23 @@ namespace ccf std::optional cose_signatures_config = std::nullopt; - NetworkInfo() {} + NetworkInfo() = default; NetworkInfo( bool public_only, ccf::kv::Version last_recovered_signed_idx, - const LedgerSecretsMap& ledger_secrets, + LedgerSecretsMap ledger_secrets, const NetworkIdentity& identity, ServiceStatus service_status, - const std::optional& endorsed_certificate, - const std::optional& - cose_signatures_config_) : + std::optional endorsed_certificate, + std::optional cose_signatures_config_) : public_only(public_only), last_recovered_signed_idx(last_recovered_signed_idx), - ledger_secrets(ledger_secrets), + ledger_secrets(std::move(ledger_secrets)), identity(identity), service_status(service_status), - endorsed_certificate(endorsed_certificate), - cose_signatures_config(cose_signatures_config_) + endorsed_certificate(std::move(endorsed_certificate)), + cose_signatures_config(std::move(cose_signatures_config_)) {} bool operator==(const NetworkInfo& other) const diff --git a/src/node/rpc/node_frontend.h b/src/node/rpc/node_frontend.h index fcd72768a6a9..b8a4acfcb9a5 100644 --- a/src/node/rpc/node_frontend.h +++ b/src/node/rpc/node_frontend.h @@ -21,7 +21,7 @@ #include "node/network_state.h" #include "node/rpc/file_serving_handlers.h" #include "node/rpc/jwt_management.h" -#include "node/rpc/no_create_tx_claims_digest.cpp" +#include "node/rpc/no_create_tx_claims_digest.cpp" // NOLINT(bugprone-suspicious-include) #include "node/rpc/serialization.h" #include "node/session_metrics.h" #include "node_interface.h" @@ -32,12 +32,12 @@ namespace ccf { struct Quote { - NodeId node_id = {}; + NodeId node_id; std::vector raw; std::vector endorsements; - QuoteFormat format; + QuoteFormat format = QuoteFormat::oe_sgx_v1; - std::string measurement = {}; // < Hex-encoded + std::string measurement; // < Hex-encoded std::optional> uvm_endorsements = std::nullopt; // SNP only @@ -88,11 +88,11 @@ namespace ccf struct JavaScriptMetrics { - uint64_t bytecode_size; - bool bytecode_used; - uint64_t max_heap_size; - uint64_t max_stack_size; - uint64_t max_execution_time; + uint64_t bytecode_size = 0; + bool bytecode_used = false; + uint64_t max_heap_size = 0; + uint64_t max_stack_size = 0; + uint64_t max_execution_time = 0; uint64_t max_cached_interpreters = 10; }; @@ -169,7 +169,7 @@ namespace ccf public: // The node frontend is exempt from backpressure rules to enable an operator // to access a node that is not making progress. - bool apply_uncommitted_tx_backpressure() const override + [[nodiscard]] bool apply_uncommitted_tx_backpressure() const override { return false; } @@ -225,8 +225,8 @@ namespace ccf { // Check that a node exists by looking up its public key in the nodes // table. - auto nodes = tx.ro(network.nodes); - auto endorsed_node_certificates = + auto* nodes = tx.ro(network.nodes); + auto* endorsed_node_certificates = tx.ro(network.node_endorsed_certificates); LOG_DEBUG_FMT( @@ -256,7 +256,7 @@ namespace ccf std::optional check_conflicting_node_network( ccf::kv::Tx& tx, const NodeInfoNetwork& node_info_network) { - auto nodes = tx.rw(network.nodes); + auto* nodes = tx.rw(network.nodes); std::optional duplicate_node_id = std::nullopt; nodes->foreach([&node_info_network, &duplicate_node_id]( @@ -287,8 +287,8 @@ namespace ccf NodeStatus node_status, ServiceStatus service_status) { - auto nodes = tx.rw(network.nodes); - auto node_endorsed_certificates = + auto* nodes = tx.rw(network.nodes); + auto* node_endorsed_certificates = tx.rw(network.node_endorsed_certificates); auto conflicting_node_id = @@ -386,7 +386,7 @@ namespace ccf node_operation.is_part_of_public_network(), node_operation.get_last_recovered_signed_idx(), this->network.ledger_secrets->get(tx), - *this->network.identity.get(), + *this->network.identity, service_status, endorsed_certificate, node_operation.get_cose_signatures_config()}; @@ -498,7 +498,7 @@ namespace ccf node_operation.get_last_recovered_signed_idx(), this->network.ledger_secrets->get( args.tx, existing_node_info->ledger_secret_seqno), - *this->network.identity.get(), + *this->network.identity, active_service->status, existing_node_info->endorsed_certificate, node_operation.get_cose_signatures_config()); @@ -566,65 +566,62 @@ namespace ccf node_operation.get_last_recovered_signed_idx(), this->network.ledger_secrets->get( args.tx, existing_node_info->ledger_secret_seqno), - *this->network.identity.get(), + *this->network.identity, active_service->status, existing_node_info->endorsed_certificate, node_operation.get_cose_signatures_config()); return make_success(rep); } - else if (node_status == NodeStatus::PENDING) + + if (node_status == NodeStatus::PENDING) { // Only return node status and ID return make_success(rep); } - else - { - return make_error( - HTTP_STATUS_BAD_REQUEST, - ccf::errors::InvalidNodeState, - fmt::format( - "Joining node is not in expected state ({}).", node_status)); - } + + return make_error( + HTTP_STATUS_BAD_REQUEST, + ccf::errors::InvalidNodeState, + fmt::format( + "Joining node is not in expected state ({}).", node_status)); } - else + + if (consensus != nullptr && !this->node_operation.can_replicate()) { - if (consensus != nullptr && !this->node_operation.can_replicate()) + auto primary_id = consensus->primary(); + if (primary_id.has_value()) { - auto primary_id = consensus->primary(); - if (primary_id.has_value()) + const auto address = node::get_redirect_address_for_node( + args, args.tx, primary_id.value()); + if (!address.has_value()) { - const auto address = node::get_redirect_address_for_node( - args, args.tx, primary_id.value()); - if (!address.has_value()) - { - return already_populated_response(); - } - - args.rpc_ctx->set_response_header( - http::headers::LOCATION, - fmt::format("https://{}/node/join", address.value())); - - return make_error( - HTTP_STATUS_PERMANENT_REDIRECT, - ccf::errors::NodeCannotHandleRequest, - "Node is not primary; cannot handle write"); + return already_populated_response(); } + args.rpc_ctx->set_response_header( + http::headers::LOCATION, + fmt::format("https://{}/node/join", address.value())); + return make_error( - HTTP_STATUS_INTERNAL_SERVER_ERROR, - ccf::errors::InternalError, - "Primary unknown"); + HTTP_STATUS_PERMANENT_REDIRECT, + ccf::errors::NodeCannotHandleRequest, + "Node is not primary; cannot handle write"); } - // If the node does not exist, add it to the KV in state pending - return add_node( - args.tx, - args.rpc_ctx->get_session_context()->caller_cert, - in, - NodeStatus::PENDING, - active_service->status); + return make_error( + HTTP_STATUS_INTERNAL_SERVER_ERROR, + ccf::errors::InternalError, + "Primary unknown"); } + + // If the node does not exist, add it to the KV in state pending + return add_node( + args.tx, + args.rpc_ctx->get_session_context()->caller_cert, + in, + NodeStatus::PENDING, + active_service->status); }; make_endpoint("/join", HTTP_POST, json_adapter(accept), no_auth_required) .set_forwarding_required(endpoints::ForwardingRequired::Never) @@ -739,20 +736,19 @@ namespace ccf return make_success(q); } - else if (result == ApiResult::NotFound) + + if (result == ApiResult::NotFound) { return make_error( HTTP_STATUS_NOT_FOUND, ccf::errors::ResourceNotFound, "Could not find node quote."); } - else - { - return make_error( - HTTP_STATUS_INTERNAL_SERVER_ERROR, - ccf::errors::InternalError, - fmt::format("Error code: {}", ccf::api_result_to_str(result))); - } + + return make_error( + HTTP_STATUS_INTERNAL_SERVER_ERROR, + ccf::errors::InternalError, + fmt::format("Error code: {}", ccf::api_result_to_str(result))); }; make_read_only_endpoint( "/quotes/self", @@ -816,8 +812,8 @@ namespace ccf auto get_attestations = [get_quotes](auto& args, nlohmann::json&& params) { - const auto res = get_quotes(args, std::move(params)); - const auto body = std::get_if(&res); + auto res = get_quotes(args, std::move(params)); + const auto* body = std::get_if(&res); if (body != nullptr) { auto result = nlohmann::json::object(); @@ -882,13 +878,11 @@ namespace ccf out.previous_service_identity = psi.value(); return make_success(out); } - else - { - return make_error( - HTTP_STATUS_NOT_FOUND, - ccf::errors::ResourceNotFound, - "This service is not a recovery of a previous service."); - } + + return make_error( + HTTP_STATUS_NOT_FOUND, + ccf::errors::ResourceNotFound, + "This service is not a recovery of a previous service."); }; make_read_only_endpoint( "/service/previous_identity", @@ -998,7 +992,7 @@ namespace ccf auto nodes = args.tx.ro(this->network.nodes); nodes->foreach( - [&out, nodes](const NodeId& node_id, const NodeInfo& ni) { + [&out, nodes](const NodeId& node_id, const NodeInfo& /*ni*/) { // Only nodes whose retire_committed status is committed can be // safely removed, because any primary elected from here on would // consider them retired, and would consequently not need their @@ -1098,10 +1092,11 @@ namespace ccf .set_auto_schema() .install(); - auto get_self_signed_certificate = [this](auto& args, nlohmann::json&&) { - return SelfSignedNodeCertificateInfo{ - this->node_operation.get_self_signed_node_certificate()}; - }; + auto get_self_signed_certificate = + [this](auto& /*args*/, nlohmann::json&&) { + return SelfSignedNodeCertificateInfo{ + this->node_operation.get_self_signed_node_certificate()}; + }; make_command_endpoint( "/self_signed_certificate", HTTP_GET, @@ -1189,28 +1184,26 @@ namespace ccf ni.node_data, nodes->get_version_of_previous_write(node_id).value_or(0)}); } - else + + // If the node isn't in its KV yet, fall back to configuration + auto node_configuration_subsystem = + this->context.get_subsystem(); + if (!node_configuration_subsystem) { - // If the node isn't in its KV yet, fall back to configuration - auto node_configuration_subsystem = - this->context.get_subsystem(); - if (!node_configuration_subsystem) - { - return make_error( - HTTP_STATUS_INTERNAL_SERVER_ERROR, - ccf::errors::InternalError, - "NodeConfigurationSubsystem is not available"); - } - const auto& node_startup_config = - node_configuration_subsystem->get().node_config; - return make_success(GetNode::Out{ - node_id, - ccf::NodeStatus::PENDING, - is_primary, - node_startup_config.network.rpc_interfaces, - node_startup_config.node_data, - 0}); + return make_error( + HTTP_STATUS_INTERNAL_SERVER_ERROR, + ccf::errors::InternalError, + "NodeConfigurationSubsystem is not available"); } + const auto& node_startup_config = + node_configuration_subsystem->get().node_config; + return make_success(GetNode::Out{ + node_id, + ccf::NodeStatus::PENDING, + is_primary, + node_startup_config.network.rpc_interfaces, + node_startup_config.node_data, + 0}); }; make_read_only_endpoint( "/network/nodes/self", @@ -1253,13 +1246,11 @@ namespace ccf nodes->get_version_of_previous_write(primary_id.value()) .value_or(0)}); } - else - { - return make_error( - HTTP_STATUS_NOT_FOUND, - ccf::errors::ResourceNotFound, - "No configured consensus"); - } + + return make_error( + HTTP_STATUS_NOT_FOUND, + ccf::errors::ResourceNotFound, + "No configured consensus"); }; make_read_only_endpoint( "/network/nodes/primary", @@ -1319,14 +1310,11 @@ namespace ccf args.rpc_ctx->set_response_status(HTTP_STATUS_OK); return; } - else - { - args.rpc_ctx->set_error( - HTTP_STATUS_NOT_FOUND, - ccf::errors::ResourceNotFound, - "Node is not primary"); - return; - } + + args.rpc_ctx->set_error( + HTTP_STATUS_NOT_FOUND, + ccf::errors::ResourceNotFound, + "Node is not primary"); }; make_read_only_endpoint( "/primary", HTTP_GET, get_primary, no_auth_required) @@ -1339,20 +1327,17 @@ namespace ccf args.rpc_ctx->set_response_status(HTTP_STATUS_OK); return; } - else - { - args.rpc_ctx->set_error( - HTTP_STATUS_NOT_FOUND, - ccf::errors::ResourceNotFound, - "Node is not backup"); - return; - } + + args.rpc_ctx->set_error( + HTTP_STATUS_NOT_FOUND, + ccf::errors::ResourceNotFound, + "Node is not backup"); }; make_read_only_endpoint("/backup", HTTP_GET, get_backup, no_auth_required) .set_forwarding_required(endpoints::ForwardingRequired::Never) .install(); - auto consensus_config = [this](auto& args, nlohmann::json&&) { + auto consensus_config = [this](auto& /*args*/, nlohmann::json&&) { // Query node for configurations, separate current from pending if (consensus != nullptr) { @@ -1367,13 +1352,11 @@ namespace ccf } return make_success(cc); } - else - { - return make_error( - HTTP_STATUS_NOT_FOUND, - ccf::errors::ResourceNotFound, - "No configured consensus"); - } + + return make_error( + HTTP_STATUS_NOT_FOUND, + ccf::errors::ResourceNotFound, + "No configured consensus"); }; make_command_endpoint( @@ -1385,18 +1368,16 @@ namespace ccf .set_auto_schema() .install(); - auto consensus_state = [this](auto& args, nlohmann::json&&) { + auto consensus_state = [this](auto& /*args*/, nlohmann::json&&) { if (consensus != nullptr) { return make_success(ConsensusConfigDetails{consensus->get_details()}); } - else - { - return make_error( - HTTP_STATUS_NOT_FOUND, - ccf::errors::ResourceNotFound, - "No configured consensus"); - } + + return make_error( + HTTP_STATUS_NOT_FOUND, + ccf::errors::ResourceNotFound, + "No configured consensus"); }; make_command_endpoint( @@ -1543,7 +1524,7 @@ namespace ccf else { // On recovery, force a new ledger chunk - auto tx_ = static_cast(&ctx.tx); + auto* tx_ = static_cast(&ctx.tx); if (tx_ == nullptr) { throw std::logic_error("Could not cast tx to CommittableTx"); @@ -1727,9 +1708,10 @@ namespace ccf .set_openapi_hidden(true) .install(); - auto get_jwt_metrics = [this](auto& args, const nlohmann::json& params) { - return make_success(jwt_refresh_metrics); - }; + auto get_jwt_metrics = + [this](auto& /*args*/, const nlohmann::json& /*params*/) { + return make_success(jwt_refresh_metrics); + }; make_read_only_endpoint( "/jwt_keys/refresh/metrics", HTTP_GET, @@ -1739,7 +1721,7 @@ namespace ccf .install(); auto service_config_handler = - [this](auto& args, const nlohmann::json& params) { + [this](auto& args, const nlohmann::json& /*params*/) { return make_success(args.tx.ro(network.config)->get()); }; make_endpoint( @@ -1752,8 +1734,8 @@ namespace ccf .install(); auto list_indexing_strategies = [this]( - auto& args, - const nlohmann::json& params) { + auto& /*args*/, + const nlohmann::json& /*params*/) { return make_success(this->context.get_indexing_strategies().describe()); }; diff --git a/src/node/rpc/node_interface.h b/src/node/rpc/node_interface.h index 9b7bd23b8bc4..380b37e43875 100644 --- a/src/node/rpc/node_interface.h +++ b/src/node/rpc/node_interface.h @@ -21,7 +21,7 @@ namespace ccf class AbstractNodeState { public: - virtual ~AbstractNodeState() {} + virtual ~AbstractNodeState() = default; virtual void transition_service_to_open( ccf::kv::Tx& tx, @@ -30,14 +30,14 @@ namespace ccf virtual void trigger_recovery_shares_refresh(ccf::kv::Tx& tx) = 0; virtual void trigger_ledger_chunk(ccf::kv::Tx& tx) = 0; virtual void trigger_snapshot(ccf::kv::Tx& tx) = 0; - virtual bool is_in_initialised_state() const = 0; - virtual bool is_part_of_public_network() const = 0; - virtual bool is_primary() const = 0; + [[nodiscard]] virtual bool is_in_initialised_state() const = 0; + [[nodiscard]] virtual bool is_part_of_public_network() const = 0; + [[nodiscard]] virtual bool is_primary() const = 0; virtual bool can_replicate() = 0; virtual std::optional get_primary() = 0; - virtual bool is_reading_public_ledger() const = 0; - virtual bool is_reading_private_ledger() const = 0; - virtual bool is_part_of_network() const = 0; + [[nodiscard]] virtual bool is_reading_public_ledger() const = 0; + [[nodiscard]] virtual bool is_reading_private_ledger() const = 0; + [[nodiscard]] virtual bool is_part_of_network() const = 0; virtual ccf::kv::Version get_last_recovered_signed_idx() = 0; virtual void initiate_private_recovery( ccf::kv::Tx& tx, @@ -54,13 +54,13 @@ namespace ccf virtual size_t get_jwt_attempts() = 0; virtual ccf::crypto::Pem get_self_signed_certificate() = 0; virtual const ccf::COSESignaturesConfig& get_cose_signatures_config() = 0; - virtual const ccf::StartupConfig& get_node_config() const = 0; + [[nodiscard]] virtual const ccf::StartupConfig& get_node_config() const = 0; virtual ccf::crypto::Pem get_network_cert() = 0; virtual void stop_notice() = 0; virtual bool has_received_stop_notice() = 0; virtual bool is_member_frontend_open() = 0; virtual bool is_user_frontend_open() = 0; - virtual bool is_accessible_to_members() const = 0; + [[nodiscard]] virtual bool is_accessible_to_members() const = 0; virtual void make_http_request( const ::http::URL& url, diff --git a/src/node/rpc/node_operation.h b/src/node/rpc/node_operation.h index f04ee07c2080..927b40a765bf 100644 --- a/src/node/rpc/node_operation.h +++ b/src/node/rpc/node_operation.h @@ -20,27 +20,27 @@ namespace ccf return impl.state(); } - bool is_in_initialised_state() const override + [[nodiscard]] bool is_in_initialised_state() const override { return impl.is_in_initialised_state(); } - bool is_part_of_public_network() const override + [[nodiscard]] bool is_part_of_public_network() const override { return impl.is_part_of_public_network(); } - bool is_part_of_network() const override + [[nodiscard]] bool is_part_of_network() const override { return impl.is_part_of_network(); } - bool is_reading_public_ledger() const override + [[nodiscard]] bool is_reading_public_ledger() const override { return impl.is_reading_public_ledger(); } - bool is_reading_private_ledger() const override + [[nodiscard]] bool is_reading_private_ledger() const override { return impl.is_reading_private_ledger(); } @@ -55,7 +55,7 @@ namespace ccf return impl.is_member_frontend_open(); } - bool is_accessible_to_members() const override + [[nodiscard]] bool is_accessible_to_members() const override { return impl.is_accessible_to_members(); } diff --git a/src/node/rpc/node_operation_interface.h b/src/node/rpc/node_operation_interface.h index c9d76cecf736..583b795c40c1 100644 --- a/src/node/rpc/node_operation_interface.h +++ b/src/node/rpc/node_operation_interface.h @@ -22,7 +22,7 @@ namespace ccf class AbstractNodeOperation : public ccf::AbstractNodeSubSystem { public: - virtual ~AbstractNodeOperation() = default; + ~AbstractNodeOperation() override = default; static char const* get_subsystem_name() { @@ -31,15 +31,15 @@ namespace ccf virtual ExtendedState state() = 0; - virtual bool is_in_initialised_state() const = 0; - virtual bool is_part_of_public_network() const = 0; - virtual bool is_part_of_network() const = 0; - virtual bool is_reading_public_ledger() const = 0; - virtual bool is_reading_private_ledger() const = 0; + [[nodiscard]] virtual bool is_in_initialised_state() const = 0; + [[nodiscard]] virtual bool is_part_of_public_network() const = 0; + [[nodiscard]] virtual bool is_part_of_network() const = 0; + [[nodiscard]] virtual bool is_reading_public_ledger() const = 0; + [[nodiscard]] virtual bool is_reading_private_ledger() const = 0; virtual bool is_user_frontend_open() = 0; virtual bool is_member_frontend_open() = 0; - virtual bool is_accessible_to_members() const = 0; + [[nodiscard]] virtual bool is_accessible_to_members() const = 0; virtual bool can_replicate() = 0; virtual std::optional get_primary() = 0; From 15b6c2ca3e90cc413aef9ba3e8dd5d210bf26423 Mon Sep 17 00:00:00 2001 From: Amaury Chamayou Date: Fri, 5 Dec 2025 15:28:03 +0000 Subject: [PATCH 07/18] all of node? --- .clang-tidy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.clang-tidy b/.clang-tidy index 5682e37ce011..caadbeaf0a0e 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -59,5 +59,5 @@ Checks: > -readability-magic-numbers, WarningsAsErrors: '*' -HeaderFilterRegex: '(include\/ccf\/|src\/(udp|tcp|tls|tasks|snapshots|service|quic|pal|apps|clients|common|consensus|ds|enclave|endpoints|host|indexing|http|node\/gov|node\/rpc)\/).*' +HeaderFilterRegex: '(include\/ccf\/|src\/(udp|tcp|tls|tasks|snapshots|service|quic|pal|apps|clients|common|consensus|ds|enclave|endpoints|host|indexing|http|node).*' FormatStyle: 'file' \ No newline at end of file From f74594900915d132fb69c33bd4faeffe595acc91 Mon Sep 17 00:00:00 2001 From: Amaury Chamayou Date: Mon, 8 Dec 2025 14:57:05 +0000 Subject: [PATCH 08/18] draft --- .clang-tidy | 2 +- src/js/extensions/ccf/kv_helpers.h | 61 ++--- src/js/modules/chained_module_loader.h | 2 +- src/js/modules/kv_bytecode_module_loader.h | 2 +- src/js/modules/kv_module_loader.h | 4 +- src/js/permissions_checks.h | 22 +- src/kv/apply_changes.h | 30 +-- src/kv/committable_tx.h | 151 +++++++------ src/kv/compacted_version_conflict.h | 4 +- src/kv/deserialise.h | 18 +- src/kv/generic_serialise_wrapper.h | 20 +- src/kv/kv_types.h | 74 +++--- src/kv/ledger_chunker.h | 10 +- src/kv/raw_serialise.h | 31 +-- src/kv/serialised_entry_format.h | 2 +- src/kv/snapshot.h | 2 +- src/kv/store.h | 77 +++---- src/kv/tx_pimpl.h | 2 +- src/kv/untyped_change_set.h | 22 +- src/kv/untyped_map.h | 124 ++++++----- src/kv/version_v.h | 2 +- src/node/channels.h | 125 +++++------ src/node/cose_common.h | 23 +- src/node/encryptor.h | 2 +- src/node/historical_queries.h | 146 ++++++------ src/node/history.h | 148 ++++++------ src/node/http_node_client.h | 7 +- src/node/jwt_key_auto_refresh.h | 16 +- src/node/ledger_secret.h | 4 +- src/node/ledger_secrets.h | 4 +- src/node/local_sealing.h | 6 +- src/node/node_client.h | 6 +- src/node/node_configuration_subsystem.h | 4 +- src/node/node_signature_verify.h | 15 +- src/node/node_state.h | 247 +++++++++++---------- src/node/node_to_node.h | 2 +- src/node/node_to_node_channel_manager.h | 42 ++-- src/node/node_types.h | 22 +- src/node/quote_endorsements_client.h | 19 +- src/node/rpc_context_impl.h | 25 ++- src/node/secret_broadcast.h | 6 +- src/node/session_metrics.h | 4 +- src/node/share_manager.h | 86 +++---- src/node/snapshot_serdes.h | 4 +- src/node/snapshotter.h | 30 +-- src/node/tx_receipt_impl.h | 20 +- 46 files changed, 877 insertions(+), 798 deletions(-) diff --git a/.clang-tidy b/.clang-tidy index caadbeaf0a0e..287e69afafda 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -59,5 +59,5 @@ Checks: > -readability-magic-numbers, WarningsAsErrors: '*' -HeaderFilterRegex: '(include\/ccf\/|src\/(udp|tcp|tls|tasks|snapshots|service|quic|pal|apps|clients|common|consensus|ds|enclave|endpoints|host|indexing|http|node).*' +HeaderFilterRegex: '(include\/ccf|src)\/.*' FormatStyle: 'file' \ No newline at end of file diff --git a/src/js/extensions/ccf/kv_helpers.h b/src/js/extensions/ccf/kv_helpers.h index 5f2d4f1dcf30..0423134d3427 100644 --- a/src/js/extensions/ccf/kv_helpers.h +++ b/src/js/extensions/ccf/kv_helpers.h @@ -19,7 +19,8 @@ namespace ccf::js::extensions::kvhelpers static JSValue C_FUNC_NAME( \ JSContext* ctx, JSValueConst this_val, int, JSValueConst*) \ { \ - js::core::Context& jsctx = *(js::core::Context*)JS_GetContextOpaque(ctx); \ + js::core::Context& jsctx = \ + *static_cast(JS_GetContextOpaque(ctx)); \ const auto table_name = \ jsctx.to_str(JS_GetPropertyStr(jsctx, this_val, "_map_name")) \ .value_or(""); \ @@ -66,7 +67,8 @@ namespace ccf::js::extensions::kvhelpers static JSValue js_kv_map_has( JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv) { - js::core::Context& jsctx = *(js::core::Context*)JS_GetContextOpaque(ctx); + js::core::Context& jsctx = + *static_cast(JS_GetContextOpaque(ctx)); if (argc != 1) { @@ -74,7 +76,7 @@ namespace ccf::js::extensions::kvhelpers ctx, "Passed %d arguments, but expected 1", argc); } - size_t key_size; + size_t key_size = 0; uint8_t* key = JS_GetArrayBuffer(ctx, &key_size, argv[0]); if (!key) @@ -82,7 +84,7 @@ namespace ccf::js::extensions::kvhelpers return JS_ThrowTypeError(ctx, "Argument must be an ArrayBuffer"); } - auto handle = GetReadOnlyHandle(jsctx, this_val); + auto* handle = GetReadOnlyHandle(jsctx, this_val); JS_CHECK_HANDLE(handle); auto has = handle->has({key, key + key_size}); @@ -94,7 +96,8 @@ namespace ccf::js::extensions::kvhelpers static JSValue js_kv_map_get( JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv) { - js::core::Context& jsctx = *(js::core::Context*)JS_GetContextOpaque(ctx); + js::core::Context& jsctx = + *static_cast(JS_GetContextOpaque(ctx)); if (argc != 1) { @@ -102,7 +105,7 @@ namespace ccf::js::extensions::kvhelpers ctx, "Passed %d arguments, but expected 1", argc); } - size_t key_size; + size_t key_size = 0; uint8_t* key = JS_GetArrayBuffer(ctx, &key_size, argv[0]); if (!key) @@ -110,7 +113,7 @@ namespace ccf::js::extensions::kvhelpers return JS_ThrowTypeError(ctx, "Argument must be an ArrayBuffer"); } - auto handle = GetReadOnlyHandle(jsctx, this_val); + auto* handle = GetReadOnlyHandle(jsctx, this_val); JS_CHECK_HANDLE(handle); auto val = handle->get({key, key + key_size}); @@ -131,7 +134,8 @@ namespace ccf::js::extensions::kvhelpers static JSValue js_kv_get_version_of_previous_write( JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv) { - js::core::Context& jsctx = *(js::core::Context*)JS_GetContextOpaque(ctx); + js::core::Context& jsctx = + *static_cast(JS_GetContextOpaque(ctx)); if (argc != 1) { @@ -139,7 +143,7 @@ namespace ccf::js::extensions::kvhelpers ctx, "Passed %d arguments, but expected 1", argc); } - size_t key_size; + size_t key_size = 0; uint8_t* key = JS_GetArrayBuffer(ctx, &key_size, argv[0]); if (!key) @@ -147,7 +151,7 @@ namespace ccf::js::extensions::kvhelpers return JS_ThrowTypeError(ctx, "Argument must be an ArrayBuffer"); } - auto handle = GetReadOnlyHandle(jsctx, this_val); + auto* handle = GetReadOnlyHandle(jsctx, this_val); JS_CHECK_HANDLE(handle); auto val = handle->get_version_of_previous_write({key, key + key_size}); @@ -162,11 +166,12 @@ namespace ccf::js::extensions::kvhelpers template static JSValue js_kv_map_size_getter( - JSContext* ctx, JSValueConst this_val, int argc, JSValueConst*) + JSContext* ctx, JSValueConst this_val, int /*argc*/, JSValueConst*) { - js::core::Context& jsctx = *(js::core::Context*)JS_GetContextOpaque(ctx); + js::core::Context& jsctx = + *static_cast(JS_GetContextOpaque(ctx)); - auto handle = GetReadOnlyHandle(jsctx, this_val); + auto* handle = GetReadOnlyHandle(jsctx, this_val); JS_CHECK_HANDLE(handle); const uint64_t size = handle->size(); @@ -183,7 +188,8 @@ namespace ccf::js::extensions::kvhelpers static JSValue js_kv_map_delete( JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv) { - js::core::Context& jsctx = *(js::core::Context*)JS_GetContextOpaque(ctx); + js::core::Context& jsctx = + *static_cast(JS_GetContextOpaque(ctx)); if (argc != 1) { @@ -191,7 +197,7 @@ namespace ccf::js::extensions::kvhelpers ctx, "Passed %d arguments, but expected 1", argc); } - size_t key_size; + size_t key_size = 0; uint8_t* key = JS_GetArrayBuffer(ctx, &key_size, argv[0]); if (!key) @@ -199,7 +205,7 @@ namespace ccf::js::extensions::kvhelpers return JS_ThrowTypeError(ctx, "Argument must be an ArrayBuffer"); } - auto handle = GetWriteHandle(jsctx, this_val); + auto* handle = GetWriteHandle(jsctx, this_val); JS_CHECK_HANDLE(handle); handle->remove({key, key + key_size}); @@ -211,7 +217,8 @@ namespace ccf::js::extensions::kvhelpers static JSValue js_kv_map_set( JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv) { - js::core::Context& jsctx = *(js::core::Context*)JS_GetContextOpaque(ctx); + js::core::Context& jsctx = + *static_cast(JS_GetContextOpaque(ctx)); if (argc != 2) { @@ -219,10 +226,10 @@ namespace ccf::js::extensions::kvhelpers ctx, "Passed %d arguments, but expected 2", argc); } - size_t key_size; + size_t key_size = 0; uint8_t* key = JS_GetArrayBuffer(ctx, &key_size, argv[0]); - size_t val_size; + size_t val_size = 0; uint8_t* val = JS_GetArrayBuffer(ctx, &val_size, argv[1]); if (!key || !val) @@ -230,7 +237,7 @@ namespace ccf::js::extensions::kvhelpers return JS_ThrowTypeError(ctx, "Arguments must be ArrayBuffers"); } - auto handle = GetWriteHandle(jsctx, this_val); + auto* handle = GetWriteHandle(jsctx, this_val); JS_CHECK_HANDLE(handle); handle->put({key, key + key_size}, {val, val + val_size}); @@ -240,9 +247,10 @@ namespace ccf::js::extensions::kvhelpers template static JSValue js_kv_map_clear( - JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv) + JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* /*argv*/) { - js::core::Context& jsctx = *(js::core::Context*)JS_GetContextOpaque(ctx); + js::core::Context& jsctx = + *static_cast(JS_GetContextOpaque(ctx)); if (argc != 0) { @@ -250,7 +258,7 @@ namespace ccf::js::extensions::kvhelpers ctx, "Passed %d arguments, but expected 0", argc); } - auto handle = GetWriteHandle(jsctx, this_val); + auto* handle = GetWriteHandle(jsctx, this_val); JS_CHECK_HANDLE(handle); handle->clear(); @@ -262,11 +270,14 @@ namespace ccf::js::extensions::kvhelpers static JSValue js_kv_map_foreach( JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv) { - js::core::Context& jsctx = *(js::core::Context*)JS_GetContextOpaque(ctx); + js::core::Context& jsctx = + *static_cast(JS_GetContextOpaque(ctx)); if (argc != 1) + { return JS_ThrowTypeError( ctx, "Passed %d arguments, but expected 1", argc); + } js::core::JSWrappedValue func(ctx, argv[0]); js::core::JSWrappedValue obj(ctx, this_val); @@ -276,7 +287,7 @@ namespace ccf::js::extensions::kvhelpers return JS_ThrowTypeError(ctx, "Argument must be a function"); } - auto handle = GetReadOnlyHandle(jsctx, this_val); + auto* handle = GetReadOnlyHandle(jsctx, this_val); JS_CHECK_HANDLE(handle); bool failed = false; diff --git a/src/js/modules/chained_module_loader.h b/src/js/modules/chained_module_loader.h index 23faa0551a70..335315001123 100644 --- a/src/js/modules/chained_module_loader.h +++ b/src/js/modules/chained_module_loader.h @@ -14,7 +14,7 @@ namespace ccf::js::modules public: ChainedModuleLoader(ModuleLoaders&& ml) : sub_loaders(std::move(ml)) {} - virtual std::optional get_module( + std::optional get_module( std::string_view module_name, js::core::Context& ctx) override { for (auto& sub_loader : sub_loaders) diff --git a/src/js/modules/kv_bytecode_module_loader.h b/src/js/modules/kv_bytecode_module_loader.h index ff5491ec1984..89c984898738 100644 --- a/src/js/modules/kv_bytecode_module_loader.h +++ b/src/js/modules/kv_bytecode_module_loader.h @@ -42,7 +42,7 @@ namespace ccf::js::modules } } - virtual std::optional get_module( + std::optional get_module( std::string_view module_name, js::core::Context& ctx) override { if (!version_ok) diff --git a/src/js/modules/kv_module_loader.h b/src/js/modules/kv_module_loader.h index 3670886ad87f..06a59cddc7f1 100644 --- a/src/js/modules/kv_module_loader.h +++ b/src/js/modules/kv_module_loader.h @@ -20,7 +20,7 @@ namespace ccf::js::modules public: KvModuleLoader(ccf::Modules::ReadOnlyHandle* mh) : modules_handle(mh) {} - virtual std::optional get_module( + std::optional get_module( std::string_view module_name, js::core::Context& ctx) override { std::string module_name_kv(module_name); @@ -38,7 +38,7 @@ namespace ccf::js::modules return std::nullopt; } - auto module_name_quickjs = module_name_kv.c_str() + 1; + const auto* module_name_quickjs = module_name_kv.c_str() + 1; const char* buf = module_str->c_str(); size_t buf_len = module_str->size(); auto parsed_module = ctx.eval( diff --git a/src/js/permissions_checks.h b/src/js/permissions_checks.h index 375e650ddc9c..84e1610ae365 100644 --- a/src/js/permissions_checks.h +++ b/src/js/permissions_checks.h @@ -33,16 +33,15 @@ namespace ccf::js { return KVAccessPermissions::READ_WRITE; } - else if ( + + if ( execution_context == TxAccess::APP_RO && namespace_of_table == ccf::kv::AccessCategory::APPLICATION) { return KVAccessPermissions::READ_ONLY; } - else - { - return KVAccessPermissions::ILLEGAL; - } + + return KVAccessPermissions::ILLEGAL; } case (ccf::kv::SecurityDomain::PUBLIC): @@ -60,10 +59,8 @@ namespace ccf::js { return KVAccessPermissions::READ_WRITE; } - else - { - return KVAccessPermissions::READ_ONLY; - } + + return KVAccessPermissions::READ_ONLY; } case ccf::kv::AccessCategory::APPLICATION: @@ -106,7 +103,7 @@ namespace ccf::js (permission == KVAccessPermissions::WRITE_ONLY ? "write-only" : "inaccessible"); - char const* exec_context = "unknown"; + char const* exec_context = nullptr; switch (access) { case (TxAccess::APP_RW): @@ -129,6 +126,11 @@ namespace ccf::js exec_context = "read-write governance"; break; } + default: + { + exec_context = "unknown"; + break; + } } static constexpr char const* access_permissions_explanation_url = diff --git a/src/kv/apply_changes.h b/src/kv/apply_changes.h index f92583742714..dc64c5dd3dc1 100644 --- a/src/kv/apply_changes.h +++ b/src/kv/apply_changes.h @@ -46,10 +46,10 @@ namespace ccf::kv views[map_name] = mc.map->create_committer(mc.changeset.get()); } - for (auto it = changes.begin(); it != changes.end(); ++it) + for (auto& [map_name, mc] : changes) { - has_writes |= it->second.changeset->has_writes(); - it->second.map->lock(); + has_writes |= mc.changeset->has_writes(); + mc.map->lock(); } bool ok = true; @@ -59,7 +59,7 @@ namespace ccf::kv // expected_rollback_count is only set on signature transactions // which always contain some writes, and on which all the maps // point to the same store. - auto store = changes.begin()->second.map->get_store(); + auto* store = changes.begin()->second.map->get_store(); if (store != nullptr) { // Note that this is done when holding the lock on at least some maps @@ -75,9 +75,9 @@ namespace ccf::kv if (ok && has_writes) { - for (auto it = views.begin(); it != views.end(); ++it) + for (auto& [view_name, view_ptr] : views) { - if (!it->second->prepare()) + if (!view_ptr->prepare()) { ok = false; break; @@ -93,11 +93,11 @@ namespace ccf::kv // versions. This is fine - none can create maps (ie - change their // conflict set with this operation) while we hold the store lock. Assume // that the caller is currently holding store->lock() - auto store = map_ptr->get_store(); + auto* store = map_ptr->get_store(); // This is to avoid recursively locking version_lock by calling // current_version() in the commit_reserved case. - ccf::kv::Version current_v; + ccf::kv::Version current_v = 0; if (new_maps_conflict_version.has_value()) { current_v = *new_maps_conflict_version; @@ -117,7 +117,7 @@ namespace ccf::kv if (ok && has_writes) { // Get the version number to be used for this commit. - ccf::kv::Version version_last_new_map; + ccf::kv::Version version_last_new_map = 0; std::tie(version, version_last_new_map) = version_resolver_fn(!new_maps.empty()); @@ -132,15 +132,15 @@ namespace ccf::kv } } - for (auto it = views.begin(); it != views.end(); ++it) + for (auto& [view_name, view_ptr] : views) { - it->second->commit(version, track_deletes_on_missing_keys); + view_ptr->commit(version, track_deletes_on_missing_keys); } // Collect ConsensusHooks - for (auto it = views.begin(); it != views.end(); ++it) + for (auto& [view_name, view_ptr] : views) { - auto hook_ptr = it->second->post_commit(); + auto hook_ptr = view_ptr->post_commit(); if (hook_ptr != nullptr) { hooks.push_back(std::move(hook_ptr)); @@ -148,9 +148,9 @@ namespace ccf::kv } } - for (auto it = changes.begin(); it != changes.end(); ++it) + for (auto& [map_name, mc] : changes) { - it->second.map->unlock(); + mc.map->unlock(); } if (!ok) diff --git a/src/kv/committable_tx.h b/src/kv/committable_tx.h index b0f188337701..586eb09accf6 100644 --- a/src/kv/committable_tx.h +++ b/src/kv/committable_tx.h @@ -43,13 +43,19 @@ namespace ccf::kv bool include_reads = false) { if (!committed) + { throw std::logic_error("Transaction not yet committed"); + } if (!success) + { throw std::logic_error("Transaction aborted"); + } if (claims_digest_.empty()) + { throw std::logic_error("Missing claims"); + } // If no transactions made changes, return a zero length vector. const bool any_changes = @@ -136,7 +142,9 @@ namespace ccf::kv const std::string& commit_evidence)> write_set_observer = nullptr) { if (committed) + { throw std::logic_error("Transaction already committed"); + } if (all_changes.empty()) { @@ -184,75 +192,72 @@ namespace ccf::kv LOG_TRACE_FMT("Could not commit transaction due to conflict"); return CommitResult::FAIL_CONFLICT; } - else - { - committed = true; - version = c.value(); - if (tx_flag_enabled(TxFlag::LEDGER_CHUNK_AT_NEXT_SIGNATURE)) - { - auto chunker = pimpl->store->get_chunker(); - if (chunker) - { - chunker->force_end_of_chunk(version); - } - } + committed = true; + version = c.value(); - if (tx_flag_enabled(TxFlag::SNAPSHOT_AT_NEXT_SIGNATURE)) + if (tx_flag_enabled(TxFlag::LEDGER_CHUNK_AT_NEXT_SIGNATURE)) + { + auto chunker = pimpl->store->get_chunker(); + if (chunker) { - pimpl->store->set_flag( - AbstractStore::StoreFlag::SNAPSHOT_AT_NEXT_SIGNATURE); - unset_tx_flag(TxFlag::SNAPSHOT_AT_NEXT_SIGNATURE); + chunker->force_end_of_chunk(version); } + } + + if (tx_flag_enabled(TxFlag::SNAPSHOT_AT_NEXT_SIGNATURE)) + { + pimpl->store->set_flag( + AbstractStore::StoreFlag::SNAPSHOT_AT_NEXT_SIGNATURE); + unset_tx_flag(TxFlag::SNAPSHOT_AT_NEXT_SIGNATURE); + } + + if (version == NoVersion) + { + // Read-only transaction + return CommitResult::SUCCESS; + } + + // From here, we have received a unique commit version and made + // modifications to our local kv. If we fail in any way, we cannot + // recover. + try + { + ccf::crypto::Sha256Hash commit_evidence_digest; + std::string commit_evidence; + auto data = serialise(commit_evidence_digest, commit_evidence, claims); - if (version == NoVersion) + if (data.empty()) { - // Read-only transaction return CommitResult::SUCCESS; } - // From here, we have received a unique commit version and made - // modifications to our local kv. If we fail in any way, we cannot - // recover. - try + if (write_set_observer != nullptr) { - ccf::crypto::Sha256Hash commit_evidence_digest; - std::string commit_evidence; - auto data = - serialise(commit_evidence_digest, commit_evidence, claims); - - if (data.empty()) - { - return CommitResult::SUCCESS; - } - - if (write_set_observer != nullptr) - { - write_set_observer(data, commit_evidence); - } + write_set_observer(data, commit_evidence); + } - auto claims_ = claims; + auto claims_ = claims; - return pimpl->store->commit( - {pimpl->commit_view, version}, - std::make_unique( - std::move(data), - std::move(claims_), - std::move(commit_evidence_digest), - std::move(hooks)), - false); - } - catch (const std::exception& e) - { - committed = false; + return pimpl->store->commit( + {pimpl->commit_view, version}, + std::make_unique( + std::move(data), + std::move(claims_), + std::move(commit_evidence_digest), + std::move(hooks)), + false); + } + catch (const std::exception& e) + { + committed = false; - LOG_FAIL_FMT("Error during serialisation"); - LOG_DEBUG_FMT("Error during serialisation: {}", e.what()); + LOG_FAIL_FMT("Error during serialisation"); + LOG_DEBUG_FMT("Error during serialisation: {}", e.what()); - // Discard original exception type, throw as now fatal - // KvSerialiserException - throw KvSerialiserException(e.what()); - } + // Discard original exception type, throw as now fatal + // KvSerialiserException + throw KvSerialiserException(e.what()); } } @@ -263,13 +268,17 @@ namespace ccf::kv * * @return Commit version */ - Version commit_version() + [[nodiscard]] Version commit_version() const { if (!committed) + { throw std::logic_error("Transaction not yet committed"); + } if (!success) + { throw std::logic_error("Transaction aborted"); + } return version; } @@ -281,13 +290,17 @@ namespace ccf::kv * * @return Commit term */ - Version commit_term() + [[nodiscard]] Version commit_term() const { if (!committed) + { throw std::logic_error("Transaction not yet committed"); + } if (!success) + { throw std::logic_error("Transaction aborted"); + } return pimpl->commit_view; } @@ -296,7 +309,7 @@ namespace ccf::kv * * @return Committed version, or `ccf::kv::NoVersion` otherwise */ - Version get_version() + [[nodiscard]] Version get_version() const { return version; } @@ -319,13 +332,11 @@ namespace ccf::kv if (version == NoVersion) { // Read-only transaction - return pimpl->read_txid.value(); - } - else - { - // Write transaction - return TxID(pimpl->commit_view, version); + return pimpl->read_txid; } + + // Write transaction + return TxID(pimpl->commit_view, version); } void set_read_txid(const TxID& tx_id, Term commit_view_) @@ -353,7 +364,7 @@ namespace ccf::kv flags &= ~static_cast(flag); } - virtual bool tx_flag_enabled(TxFlag f) const + [[nodiscard]] virtual bool tx_flag_enabled(TxFlag f) const { return (flags & static_cast(f)) != 0; } @@ -377,22 +388,26 @@ namespace ccf::kv Term read_term, const TxID& reserved_tx_id, Version rollback_count_) : - CommittableTx(_store) + CommittableTx(_store), + rollback_count(rollback_count_) { version = reserved_tx_id.seqno; pimpl->commit_view = reserved_tx_id.view; pimpl->read_txid = TxID(read_term, reserved_tx_id.seqno - 1); - rollback_count = rollback_count_; } // Used by frontend to commit reserved transactions PendingTxInfo commit_reserved() { if (committed) + { throw std::logic_error("Transaction already committed"); + } if (all_changes.empty()) + { throw std::logic_error("Reserved transaction cannot be empty"); + } std::vector hooks; bool track_deletes_on_missing_keys = false; @@ -407,7 +422,9 @@ namespace ccf::kv success = c.has_value(); if (!success) + { throw std::logic_error("Failed to commit reserved transaction"); + } ccf::crypto::Sha256Hash commit_evidence_digest; std::string commit_evidence; diff --git a/src/kv/compacted_version_conflict.h b/src/kv/compacted_version_conflict.h index 9c0605621819..093861539398 100644 --- a/src/kv/compacted_version_conflict.h +++ b/src/kv/compacted_version_conflict.h @@ -12,9 +12,9 @@ namespace ccf::kv std::string msg; public: - CompactedVersionConflict(const std::string& s) : msg(s) {} + CompactedVersionConflict(std::string s) : msg(std::move(s)) {} - char const* what() const + [[nodiscard]] char const* what() const { return msg.c_str(); } diff --git a/src/kv/deserialise.h b/src/kv/deserialise.h index c7e6d75662ca..dffff3e4c000 100644 --- a/src/kv/deserialise.h +++ b/src/kv/deserialise.h @@ -18,6 +18,8 @@ namespace ccf::kv class ExecutionWrapperStore { public: + virtual ~ExecutionWrapperStore() = default; + virtual bool fill_maps( const std::vector& data, bool public_only, @@ -47,14 +49,14 @@ namespace ccf::kv std::shared_ptr chunker; const std::vector data; bool public_only; - ccf::kv::Version version; - Term term; - EntryFlags entry_flags; + ccf::kv::Version version{0}; + Term term{0}; + EntryFlags entry_flags{0}; OrderedChanges changes; MapCollection new_maps; ccf::kv::ConsensusHookPtrs hooks; ccf::ClaimsDigest claims_digest; - std::optional commit_evidence_digest = {}; + std::optional commit_evidence_digest; const std::optional expected_txid; @@ -67,8 +69,8 @@ namespace ccf::kv bool public_only_, const std::optional& expected_txid_) : store(store_), - history(history_), - chunker(chunker_), + history(std::move(history_)), + chunker(std::move(chunker_)), data(data_), public_only(public_only_), expected_txid(expected_txid_) @@ -183,12 +185,12 @@ namespace ccf::kv { chunker->append_entry_size(data.size()); - if (entry_flags & ccf::kv::EntryFlags::FORCE_LEDGER_CHUNK_BEFORE) + if ((entry_flags & ccf::kv::EntryFlags::FORCE_LEDGER_CHUNK_BEFORE) != 0) { chunker->produced_chunk_at(version - 1); } - if (entry_flags & ccf::kv::EntryFlags::FORCE_LEDGER_CHUNK_AFTER) + if ((entry_flags & ccf::kv::EntryFlags::FORCE_LEDGER_CHUNK_AFTER) != 0) { chunker->produced_chunk_at(version); } diff --git a/src/kv/generic_serialise_wrapper.h b/src/kv/generic_serialise_wrapper.h index a31f7f9492ac..6f6651db7474 100644 --- a/src/kv/generic_serialise_wrapper.h +++ b/src/kv/generic_serialise_wrapper.h @@ -29,7 +29,7 @@ namespace ccf::kv std::shared_ptr crypto_util; // must only be set by set_current_domain, since it affects current_writer - SecurityDomain current_domain; + SecurityDomain current_domain{SecurityDomain::PUBLIC}; // If true, consider historical ledger secrets when encrypting entries bool historical_hint; @@ -71,7 +71,7 @@ namespace ccf::kv tx_id(tx_id_), entry_type(entry_type_), header_flags(header_flags_), - crypto_util(e), + crypto_util(std::move(e)), historical_hint(historical_hint_) { set_current_domain(SecurityDomain::PUBLIC); @@ -177,7 +177,7 @@ namespace ccf::kv size_ += sizeof(SerialisedEntryHeader); std::vector entry(size_); - auto data_ = entry.data(); + auto* data_ = entry.data(); serialized::write(data_, size_, entry_header); @@ -221,7 +221,7 @@ namespace ccf::kv size_, serialised_public_domain.data(), serialised_public_domain.size()); - if (encrypted_private_domain.size() > 0) + if (!encrypted_private_domain.empty()) { serialized::write( data_, @@ -242,13 +242,13 @@ namespace ccf::kv R private_reader; R* current_reader; std::vector decrypted_buffer; - EntryType entry_type; + EntryType entry_type{EntryType::WriteSet}; // Present systematically in regular transactions, but absent from snapshots ccf::ClaimsDigest claims_digest = ccf::no_claims(); // Present systematically in regular transactions, but absent from snapshots std::optional commit_evidence_digest = std::nullopt; - Version version; + Version version{0}; std::shared_ptr crypto_util; std::optional domain_restriction; @@ -282,7 +282,7 @@ namespace ccf::kv GenericDeserialiseWrapper( std::shared_ptr e, std::optional domain_restriction = std::nullopt) : - crypto_util(e), + crypto_util(std::move(e)), domain_restriction(domain_restriction) {} @@ -304,7 +304,7 @@ namespace ccf::kv bool historical_hint = false) { current_reader = &public_reader; - auto data_ = data; + const auto* data_ = data; auto size_ = size; const auto tx_header = @@ -320,7 +320,7 @@ namespace ccf::kv size_)); } - auto gcm_hdr_data = data_; + const auto* gcm_hdr_data = data_; switch (tx_header.version) { @@ -348,7 +348,7 @@ namespace ccf::kv serialized::skip(data_, size_, crypto_util->get_header_length()); auto public_domain_length = serialized::read(data_, size_); - auto data_public = data_; + const auto* data_public = data_; public_reader.init(data_public, public_domain_length); read_public_header(); diff --git a/src/kv/kv_types.h b/src/kv/kv_types.h index e3a661665369..6a4f0860f666 100644 --- a/src/kv/kv_types.h +++ b/src/kv/kv_types.h @@ -54,9 +54,9 @@ namespace ccf::kv NodeInfo() = default; - NodeInfo(const std::string& hostname_, const std::string& port_) : - hostname(hostname_), - port(port_) + NodeInfo(std::string hostname_, std::string port_) : + hostname(std::move(hostname_)), + port(std::move(port_)) {} bool operator==(const NodeInfo& other) const @@ -67,9 +67,9 @@ namespace ccf::kv using Nodes = std::map; - ccf::SeqNo idx; + ccf::SeqNo idx = 0; Nodes nodes; - ReconfigurationId rid; + ReconfigurationId rid = 0; }; inline void to_json(nlohmann::json& j, const Configuration::NodeInfo& ni) @@ -85,13 +85,13 @@ namespace ccf::kv ni.port = p; } - inline std::string schema_name(const Configuration::NodeInfo*) + inline std::string schema_name(const Configuration::NodeInfo* /*unused*/) { return "Configuration__NodeInfo"; } inline void fill_json_schema( - nlohmann::json& schema, const Configuration::NodeInfo*) + nlohmann::json& schema, const Configuration::NodeInfo* /*unused*/) { schema["type"] = "object"; schema["required"] = nlohmann::json::array(); @@ -101,7 +101,7 @@ namespace ccf::kv schema["properties"]["address"]["$ref"] = "#/components/schemas/string"; } - enum class LeadershipState + enum class LeadershipState : uint8_t { None, Leader, @@ -118,7 +118,7 @@ namespace ccf::kv {LeadershipState::PreVoteCandidate, "PreVoteCandidate"}, {LeadershipState::Candidate, "Candidate"}}); - enum class MembershipState + enum class MembershipState : uint8_t { Active, Retired @@ -129,7 +129,7 @@ namespace ccf::kv {{MembershipState::Active, "Active"}, {MembershipState::Retired, "Retired"}}); - enum class RetirementPhase + enum class RetirementPhase : uint8_t { Ordered = 1, Signed = 2, @@ -155,9 +155,9 @@ namespace ccf::kv size_t last_received_ms; }; - std::vector configs = {}; - std::unordered_map acks = {}; - MembershipState membership_state; + std::vector configs; + std::unordered_map acks; + MembershipState membership_state{}; std::optional leadership_state = std::nullopt; std::optional retirement_phase = std::nullopt; std::optional> learners = @@ -190,10 +190,12 @@ namespace ccf::kv class ConfigurableConsensus { public: + virtual ~ConfigurableConsensus() = default; virtual void add_configuration( ccf::SeqNo seqno, const Configuration::Nodes& conf) = 0; virtual Configuration::Nodes get_latest_configuration() = 0; - virtual Configuration::Nodes get_latest_configuration_unsafe() const = 0; + [[nodiscard]] virtual Configuration::Nodes get_latest_configuration_unsafe() + const = 0; virtual ConsensusDetails get_details() = 0; }; @@ -203,21 +205,21 @@ namespace ccf::kv bool, std::shared_ptr>>; - enum CommitResult + enum CommitResult : uint8_t { SUCCESS = 1, FAIL_CONFLICT = 2, FAIL_NO_REPLICATE = 3 }; - enum SecurityDomain + enum SecurityDomain : uint8_t { PUBLIC, // Public domain indicates the version and always appears first PRIVATE, SECURITY_DOMAIN_MAX }; - enum AccessCategory + enum AccessCategory : uint8_t { INTERNAL, GOVERNANCE, @@ -296,7 +298,7 @@ namespace ccf::kv return {security_domain, access_category}; } - enum ApplyResult + enum ApplyResult : uint8_t { PASS = 1, PASS_SIGNATURE = 2, @@ -315,9 +317,9 @@ namespace ccf::kv std::string msg; public: - KvSerialiserException(const std::string& msg_) : msg(msg_) {} + KvSerialiserException(std::string msg_) : msg(std::move(msg_)) {} - virtual const char* what() const throw() + [[nodiscard]] const char* what() const noexcept override { return msg.c_str(); } @@ -326,7 +328,7 @@ namespace ccf::kv class TxHistory { public: - virtual ~TxHistory() {} + virtual ~TxHistory() = default; virtual bool verify_root_signatures(ccf::kv::Version version) = 0; virtual void try_emit_signature() = 0; virtual void emit_signature() = 0; @@ -361,7 +363,7 @@ namespace ccf::kv class Consensus : public ConfigurableConsensus { public: - virtual ~Consensus() {} + ~Consensus() override = default; virtual NodeId id() = 0; virtual bool is_primary() = 0; @@ -370,7 +372,7 @@ namespace ccf::kv virtual bool can_replicate() = 0; virtual bool is_at_max_capacity() = 0; - enum class SignatureDisposition + enum class SignatureDisposition : uint8_t { CANT_REPLICATE, CAN_SIGN, @@ -399,13 +401,13 @@ namespace ccf::kv virtual void recv_message( const NodeId& from, const uint8_t* data, size_t size) = 0; - virtual void periodic(std::chrono::milliseconds) {} + virtual void periodic(std::chrono::milliseconds /*elapsed*/) {} virtual void periodic_end() {} virtual void enable_all_domains() {} virtual void set_retired_committed( - ccf::SeqNo, const std::vector& node_ids) + ccf::SeqNo /*seqno*/, const std::vector& node_ids) {} }; @@ -460,19 +462,19 @@ namespace ccf::kv PendingTxInfo call() override { - return PendingTxInfo( + return { CommitResult::SUCCESS, std::move(data), std::move(claims_digest), std::move(commit_evidence_digest), - std::move(hooks)); + std::move(hooks)}; } }; class AbstractTxEncryptor { public: - virtual ~AbstractTxEncryptor() {} + virtual ~AbstractTxEncryptor() = default; virtual bool encrypt( const std::vector& plain, @@ -517,7 +519,7 @@ namespace ccf::kv public: virtual ~AbstractChangeSet() = default; - virtual bool has_writes() const = 0; + [[nodiscard]] virtual bool has_writes() const = 0; }; class AbstractCommitter @@ -541,11 +543,11 @@ namespace ccf::kv public: virtual ~Snapshot() = default; virtual void serialise(KvStoreSerialiser& s) = 0; - virtual SecurityDomain get_security_domain() const = 0; + [[nodiscard]] virtual SecurityDomain get_security_domain() const = 0; }; using GetName::GetName; - virtual ~AbstractMap() {} + ~AbstractMap() override = default; virtual std::unique_ptr create_committer( AbstractChangeSet* changes) = 0; @@ -609,12 +611,12 @@ namespace ccf::kv { public: virtual ~AbstractSnapshot() = default; - virtual Version get_version() const = 0; + [[nodiscard]] virtual Version get_version() const = 0; virtual std::vector serialise( const std::shared_ptr& encryptor) = 0; }; - virtual ~AbstractStore() {} + virtual ~AbstractStore() = default; virtual void lock_map_set() = 0; virtual void unlock_map_set() = 0; @@ -681,7 +683,7 @@ namespace ccf::kv virtual bool flag_enabled(StoreFlag f) = 0; virtual void set_flag_unsafe(StoreFlag f) = 0; virtual void unset_flag_unsafe(StoreFlag f) = 0; - virtual bool flag_enabled_unsafe(StoreFlag f) const = 0; + [[nodiscard]] virtual bool flag_enabled_unsafe(StoreFlag f) const = 0; }; template @@ -689,7 +691,7 @@ namespace ccf::kv { public: ScopedStoreMapsLock() = delete; - ScopedStoreMapsLock(StorePointer _store) : store(_store) + ScopedStoreMapsLock(StorePointer _store) : store(std::move(_store)) { store->lock_maps(); } @@ -720,7 +722,7 @@ struct formatter const -> decltype(ctx.out()) { std::set node_ids; - for (auto& [nid, _] : nodes) + for (const auto& [nid, _] : nodes) { node_ids.insert(nid); } diff --git a/src/kv/ledger_chunker.h b/src/kv/ledger_chunker.h index 0b4dedf654c6..1bdaa4d0e8df 100644 --- a/src/kv/ledger_chunker.h +++ b/src/kv/ledger_chunker.h @@ -21,12 +21,12 @@ namespace ccf::kv const size_t chunk_threshold; Version current_tx_version; - std::map transaction_sizes = {}; - std::set chunk_ends = {}; - std::set forced_chunk_versions = {}; + std::map transaction_sizes; + std::set chunk_ends; + std::set forced_chunk_versions; std::mutex chunker_lock; - size_t get_unchunked_size(Version up_to) const + [[nodiscard]] size_t get_unchunked_size(Version up_to) const { auto begin = transaction_sizes.cbegin(); auto end = transaction_sizes.upper_bound(up_to); @@ -114,7 +114,7 @@ namespace ccf::kv void compacted_to(Version v) override { std::lock_guard l(chunker_lock); - Version compactable_v; + Version compactable_v = 0; auto compactable_it = chunk_ends.lower_bound(v); if (compactable_it != chunk_ends.begin()) diff --git a/src/kv/raw_serialise.h b/src/kv/raw_serialise.h index c5406b772859..ef1b1104a2a6 100644 --- a/src/kv/raw_serialise.h +++ b/src/kv/raw_serialise.h @@ -26,7 +26,7 @@ namespace ccf::kv size_t size_before = buf.size(); buf.resize(buf.size() + sizeof(T)); - auto data_ = buf.data() + size_before; + auto* data_ = buf.data() + size_before; auto size_ = buf.size() - size_before; serialized::write(data_, size_, t); } @@ -39,7 +39,7 @@ namespace ccf::kv buf.resize(buf.size() + entry_size_bytes); - auto data_ = buf.data() + size_before; + auto* data_ = buf.data() + size_before; auto size_ = buf.size() - size_before; serialized::write( data_, @@ -55,7 +55,7 @@ namespace ccf::kv size_t size_before = buf.size(); buf.resize(buf.size() + array_size); - auto data_ = buf.data() + size_before; + auto* data_ = buf.data() + size_before; auto size_ = buf.size() - size_before; serialized::write( data_, @@ -69,7 +69,7 @@ namespace ccf::kv size_t size_before = buf.size(); buf.resize(buf.size() + sizeof(size_t) + str.size()); - auto data_ = buf.data() + size_before; + auto* data_ = buf.data() + size_before; auto size_ = buf.size() - size_before; serialized::write(data_, size_, str); } @@ -128,7 +128,7 @@ namespace ccf::kv { public: const uint8_t* data_ptr; - size_t data_offset; + size_t data_offset{0}; size_t data_size; /** Reads the next entry, advancing data_offset @@ -137,7 +137,7 @@ namespace ccf::kv T read_entry() { auto remainder = data_size - data_offset; - auto data = data_ptr + data_offset; + const auto* data = data_ptr + data_offset; const auto entry = serialized::read(data, remainder); const auto bytes_read = data_size - data_offset - remainder; data_offset += bytes_read; @@ -163,14 +163,13 @@ namespace ccf::kv return entry_size; } - public: RawReader(const RawReader& other) = delete; RawReader& operator=(const RawReader& other) = delete; - RawReader(const uint8_t* data_in_ptr = nullptr, size_t data_in_size = 0) - { - init(data_in_ptr, data_in_size); - } + RawReader(const uint8_t* data_in_ptr = nullptr, size_t data_in_size = 0) : + data_ptr(data_in_ptr), + data_size(data_in_size) + {} void init(const uint8_t* data_in_ptr, size_t data_in_size) { @@ -200,8 +199,8 @@ namespace ccf::kv } else if constexpr (ccf::nonstd::is_std_array::value) { - T ret; - auto data_ = reinterpret_cast(ret.data()); + T ret{}; + auto* data_ = reinterpret_cast(ret.data()); constexpr size_t size = ret.size() * sizeof(typename T::value_type); auto size_ = size; serialized::write(data_, size_, data_ptr + data_offset, size); @@ -211,10 +210,12 @@ namespace ccf::kv } else if constexpr (std::is_same_v) { - uint8_t entry_type = read_entry(); + auto entry_type = read_entry(); if (entry_type > static_cast(ccf::kv::EntryType::MAX)) + { throw std::logic_error( fmt::format("Invalid EntryType: {}", entry_type)); + } return ccf::kv::EntryType(entry_type); } @@ -237,7 +238,7 @@ namespace ccf::kv } } - bool is_eos() + [[nodiscard]] bool is_eos() const { return data_offset >= data_size; } diff --git a/src/kv/serialised_entry_format.h b/src/kv/serialised_entry_format.h index 4e8cb0fb4793..46e0650fd9cf 100644 --- a/src/kv/serialised_entry_format.h +++ b/src/kv/serialised_entry_format.h @@ -25,7 +25,7 @@ namespace ccf::kv static constexpr auto BITS_FOR_SIZE = (sizeof(uint64_t) - sizeof(uint8_t) - sizeof(SerialisedEntryFlags)) * CHAR_BIT; - uint64_t size : BITS_FOR_SIZE; + uint64_t size : BITS_FOR_SIZE = 0; void set_size(uint64_t size_) { diff --git a/src/kv/snapshot.h b/src/kv/snapshot.h index af306e77e387..ebe7f759de26 100644 --- a/src/kv/snapshot.h +++ b/src/kv/snapshot.h @@ -34,7 +34,7 @@ namespace ccf::kv view_history = std::move(view_history_); } - Version get_version() const override + [[nodiscard]] Version get_version() const override { return version; } diff --git a/src/kv/store.h b/src/kv/store.h index f95609fa970b..df1af6510122 100644 --- a/src/kv/store.h +++ b/src/kv/store.h @@ -144,10 +144,7 @@ namespace ccf::kv bool has_map_internal(const std::string& name) { auto search = maps.find(name); - if (search != maps.end()) - return true; - - return false; + return search != maps.end(); } Version next_version_unsafe() @@ -406,8 +403,8 @@ namespace ccf::kv public_only ? ccf::kv::SecurityDomain::PUBLIC : std::optional()); - ccf::kv::Term term; - ccf::kv::EntryFlags entry_flags; + ccf::kv::Term term = 0; + ccf::kv::EntryFlags entry_flags = {}; auto v_ = d.init(data, size, term, entry_flags, is_historical); if (!v_.has_value()) { @@ -433,7 +430,7 @@ namespace ccf::kv hash_at_snapshot = d.deserialise_raw(); } - if (view_history) + if (view_history != nullptr) { view_history_ = d.deserialise_view_history(); } @@ -530,7 +527,7 @@ namespace ccf::kv } } - if (view_history) + if (view_history != nullptr) { *view_history = std::move(view_history_); } @@ -749,9 +746,11 @@ namespace ccf::kv commit_evidence_digest = std::move(d.consume_commit_evidence_digest()); if (commit_evidence_digest.has_value()) + { LOG_TRACE_FMT( "Deserialised commit evidence digest {}", commit_evidence_digest.value()); + } // Throw away any local commits that have not propagated via the // consensus. @@ -826,12 +825,7 @@ namespace ccf::kv const std::optional& expected_txid = std::nullopt) override { auto exec = std::make_unique( - this, - get_history(), - get_chunker(), - std::move(data), - public_only, - expected_txid); + this, get_history(), get_chunker(), data, public_only, expected_txid); return exec; } @@ -839,29 +833,38 @@ namespace ccf::kv { // Only used for debugging, not thread safe. if (version != that.version) + { return false; + } if (maps.size() != that.maps.size()) + { return false; + } - for (auto it = maps.begin(); it != maps.end(); ++it) - { - auto search = that.maps.find(it->first); + return std::ranges::all_of(maps, [&that](const auto& entry) { + const auto& [map_name, map_pair] = entry; + auto search = that.maps.find(map_name); if (search == that.maps.end()) + { return false; + } - auto& [this_v, this_map] = it->second; - auto& [that_v, that_map] = search->second; + const auto& [this_v, this_map] = map_pair; + const auto& [that_v, that_map] = search->second; if (this_v != that_v) + { return false; + } if (*this_map != *that_map) + { return false; - } - - return true; + } + return true; + }); } Version current_version() override @@ -975,7 +978,7 @@ namespace ccf::kv } // Release version lock - if (contiguous_pending_txs.size() == 0) + if (contiguous_pending_txs.empty()) { return CommitResult::SUCCESS; } @@ -1041,11 +1044,9 @@ namespace ccf::kv } return CommitResult::SUCCESS; } - else - { - LOG_DEBUG_FMT("Failed to replicate"); - return CommitResult::FAIL_NO_REPLICATE; - } + + LOG_DEBUG_FMT("Failed to replicate"); + return CommitResult::FAIL_NO_REPLICATE; } bool should_create_ledger_chunk(Version version) override @@ -1266,7 +1267,7 @@ namespace ccf::kv ReadOnlyTx create_read_only_tx() override { - return ReadOnlyTx(this); + return {this}; } std::unique_ptr create_read_only_tx_ptr() override @@ -1276,12 +1277,12 @@ namespace ccf::kv TxDiff create_tx_diff() override { - return TxDiff(this); + return {this}; } CommittableTx create_tx() { - return CommittableTx(this); + return {this}; } std::unique_ptr create_tx_ptr() @@ -1292,38 +1293,38 @@ namespace ccf::kv ReservedTx create_reserved_tx(const TxID& tx_id) { std::lock_guard vguard(version_lock); - return ReservedTx(this, term_of_last_version, tx_id, rollback_count); + return {this, term_of_last_version, tx_id, rollback_count}; } - virtual void set_flag(StoreFlag f) override + void set_flag(StoreFlag f) override { std::lock_guard vguard(version_lock); set_flag_unsafe(f); } - virtual void unset_flag(StoreFlag f) override + void unset_flag(StoreFlag f) override { std::lock_guard vguard(version_lock); unset_flag_unsafe(f); } - virtual bool flag_enabled(StoreFlag f) override + bool flag_enabled(StoreFlag f) override { std::lock_guard vguard(version_lock); return flag_enabled_unsafe(f); } - virtual void set_flag_unsafe(StoreFlag f) override + void set_flag_unsafe(StoreFlag f) override { this->flags |= static_cast(f); } - virtual void unset_flag_unsafe(StoreFlag f) override + void unset_flag_unsafe(StoreFlag f) override { this->flags &= ~static_cast(f); } - virtual bool flag_enabled_unsafe(StoreFlag f) const override + [[nodiscard]] bool flag_enabled_unsafe(StoreFlag f) const override { return (flags & static_cast(f)) != 0; } diff --git a/src/kv/tx_pimpl.h b/src/kv/tx_pimpl.h index db9ee90373e9..1f14e91297e4 100644 --- a/src/kv/tx_pimpl.h +++ b/src/kv/tx_pimpl.h @@ -8,7 +8,7 @@ namespace ccf::kv { struct BaseTx::PrivateImpl { - AbstractStore* store; + AbstractStore* store = nullptr; // NB: This exists only to maintain the old API, where this Tx stores // MapHandles and returns raw pointers to them. It could be removed entirely diff --git a/src/kv/untyped_change_set.h b/src/kv/untyped_change_set.h index 6385ec84b2a3..123635995f93 100644 --- a/src/kv/untyped_change_set.h +++ b/src/kv/untyped_change_set.h @@ -42,17 +42,17 @@ namespace ccf::kv::untyped struct ChangeSet : public AbstractChangeSet { protected: - ChangeSet() {} + ChangeSet() = default; public: const size_t rollback_counter = {}; - const ccf::kv::untyped::State state = {}; - const ccf::kv::untyped::State committed = {}; + const ccf::kv::untyped::State state; + const ccf::kv::untyped::State committed; const Version start_version = {}; Version read_version = NoVersion; - ccf::kv::untyped::Read reads = {}; - ccf::kv::untyped::Write writes = {}; + ccf::kv::untyped::Read reads; + ccf::kv::untyped::Write writes; ChangeSet( size_t rollbacks, @@ -64,12 +64,12 @@ namespace ccf::kv::untyped state(current_state), committed(committed_state), start_version(current_version), - writes(changed_writes) + writes(std::move(changed_writes)) {} ChangeSet(ChangeSet&) = delete; - bool has_writes() const override + [[nodiscard]] bool has_writes() const override { return !writes.empty(); } @@ -92,7 +92,7 @@ namespace ccf::kv::untyped SnapshotChangeSet(SnapshotChangeSet&) = delete; - bool has_writes() const override + [[nodiscard]] bool has_writes() const override { return true; } @@ -136,8 +136,8 @@ namespace map const uint8_t*& data, size_t& size) { ccf::kv::untyped::VersionV ret; - uint64_t data_size = serialized::read(data, size); - ccf::kv::Version version = serialized::read(data, size); + auto data_size = serialized::read(data, size); + auto version = serialized::read(data, size); ret.version = version; data_size -= sizeof(ccf::kv::Version); ret.value.append(data, data + data_size); @@ -171,7 +171,7 @@ namespace map inline ccf::kv::untyped::SerialisedEntry deserialize< ccf::kv::untyped::SerialisedEntry>(const uint8_t*& data, size_t& size) { - uint64_t data_size = serialized::read(data, size); + auto data_size = serialized::read(data, size); ccf::kv::untyped::SerialisedEntry ret; ret.append(data, data + data_size); serialized::skip(data, size, data_size); diff --git a/src/kv/untyped_map.h b/src/kv/untyped_map.h index dc5488628ea3..c542bf4eb372 100644 --- a/src/kv/untyped_map.h +++ b/src/kv/untyped_map.h @@ -21,13 +21,13 @@ namespace ccf::kv::untyped struct LocalCommit { LocalCommit() = default; - LocalCommit(Version v, State&& s, const Write& w) : + LocalCommit(Version v, State&& s, Write w) : version(v), state(std::move(s)), - writes(w) + writes(std::move(w)) {} - Version version; + Version version{0}; State state; Write writes; LocalCommit* next = nullptr; @@ -38,7 +38,7 @@ namespace ccf::kv::untyped struct Roll { std::unique_ptr commits; - size_t rollback_counter; + size_t rollback_counter{0}; LocalCommits empty_commits; @@ -54,6 +54,7 @@ namespace ccf::kv::untyped LocalCommit* c = empty_commits.pop(); if (c == nullptr) { + // NOLINTNEXTLINE(cppcoreguidelines-owning-memory) c = new LocalCommit(std::forward(args)...); } else @@ -150,10 +151,13 @@ namespace ccf::kv::untyped // If the parent map has rolled back since this transaction began, this // transaction must fail. if (change_set.rollback_counter != map_roll.rollback_counter) + { return false; + } // If we have iterated over the map, check for a global version match. - auto current = map_roll.commits->get_tail(); + // Check each key in our read set. + auto* current = map_roll.commits->get_tail(); if ( (change_set.read_version != NoVersion) && (change_set.read_version != current->version)) @@ -163,13 +167,12 @@ namespace ccf::kv::untyped } // Check each key in our read set. - for (auto it = change_set.reads.begin(); it != change_set.reads.end(); - ++it) + for (const auto& [key, value] : change_set.reads) { // Get the value from the current state. - auto search = current->state.get(it->first); + auto search = current->state.get(key); - if (std::get<0>(it->second) == NoVersion) + if (std::get<0>(value) == NoVersion) { // If we depend on the key not existing, it must be absent. if (search.has_value()) @@ -185,7 +188,7 @@ namespace ccf::kv::untyped // conflicts then ensure that the read versions also match. if ( !search.has_value() || - std::get<0>(it->second) != search.value().version) + std::get<0>(value) != search.value().version) { LOG_DEBUG_FMT("Read depends on invalid version of entry"); return false; @@ -211,23 +214,23 @@ namespace ccf::kv::untyped commit_version = v; committed_writes = true; - for (auto it = change_set.writes.begin(); it != change_set.writes.end(); - ++it) + for (const auto& [key, maybe_value] : change_set.writes) { - if (it->second.has_value()) + if (maybe_value.has_value()) { // Write the new value with the global version. changes = true; - state = state.put(it->first, VersionV{v, v, it->second.value()}); + // NOLINTNEXTLINE(bugprone-unchecked-optional-access) + state = state.put(key, VersionV{v, v, maybe_value.value()}); } else { // Delete the key if it exists - auto search = state.get(it->first); + auto search = state.get(key); if (search.has_value()) { changes = true; - state = state.remove(it->first); + state = state.remove(key); } else if (track_deletes_on_missing_keys) { @@ -270,11 +273,11 @@ namespace ccf::kv::untyped public: Snapshot( - const std::string& name_, + std::string name_, SecurityDomain security_domain_, ccf::kv::Version version_, std::unique_ptr&& map_snapshot_) : - name(name_), + name(std::move(name_)), security_domain(security_domain_), version(version_), map_snapshot(std::move(map_snapshot_)) @@ -291,7 +294,7 @@ namespace ccf::kv::untyped s.serialise_raw(ret); } - SecurityDomain get_security_domain() const override + [[nodiscard]] SecurityDomain get_security_domain() const override { return security_domain; } @@ -317,9 +320,9 @@ namespace ccf::kv::untyped Map(const Map& that) = delete; - virtual AbstractMap* clone(AbstractStore* other) override + AbstractMap* clone(AbstractStore* other) override { - return (AbstractMap*)new Map(other, name, security_domain); + return static_cast(new Map(other, name, security_domain)); } void serialise_changes( @@ -327,7 +330,7 @@ namespace ccf::kv::untyped KvStoreSerialiser& s, bool include_reads) override { - const auto non_abstract = + const auto* const non_abstract = dynamic_cast(changes); if (non_abstract == nullptr) { @@ -344,10 +347,9 @@ namespace ccf::kv::untyped s.serialise_entry_version(change_set.read_version); s.serialise_count_header(change_set.reads.size()); - for (auto it = change_set.reads.begin(); it != change_set.reads.end(); - ++it) + for (const auto& [key, value] : change_set.reads) { - s.serialise_read(it->first, std::get<0>(it->second)); + s.serialise_read(key, std::get<0>(value)); } } else @@ -358,10 +360,9 @@ namespace ccf::kv::untyped uint64_t write_ctr = 0; uint64_t remove_ctr = 0; - for (auto it = change_set.writes.begin(); it != change_set.writes.end(); - ++it) + for (const auto& [key, maybe_value] : change_set.writes) { - if (it->second.has_value()) + if (maybe_value.has_value()) { ++write_ctr; } @@ -372,22 +373,21 @@ namespace ccf::kv::untyped } s.serialise_count_header(write_ctr); - for (auto it = change_set.writes.begin(); it != change_set.writes.end(); - ++it) + for (const auto& [key, maybe_value] : change_set.writes) { - if (it->second.has_value()) + if (maybe_value.has_value()) { - s.serialise_write(it->first, it->second.value()); + // NOLINTNEXTLINE(bugprone-unchecked-optional-access) + s.serialise_write(key, maybe_value.value()); } } s.serialise_count_header(remove_ctr); - for (auto it = change_set.writes.begin(); it != change_set.writes.end(); - ++it) + for (const auto& [key, maybe_value] : change_set.writes) { - if (!it->second.has_value()) + if (!maybe_value.has_value()) { - s.serialise_remove(it->first); + s.serialise_remove(key); } } } @@ -426,7 +426,7 @@ namespace ccf::kv::untyped map.roll.reset_commits(); map.roll.rollback_counter++; - auto r = map.roll.commits->get_head(); + auto* r = map.roll.commits->get_head(); r->state = change_set.state; r->version = change_set.version; @@ -444,7 +444,7 @@ namespace ccf::kv::untyped ConsensusHookPtr post_commit() override { - auto r = map.roll.commits->get_head(); + auto* r = map.roll.commits->get_head(); return map.trigger_map_hook(change_set.version, r->writes); } }; @@ -479,7 +479,7 @@ namespace ccf::kv::untyped auto& change_set = *change_set_ptr; - uint64_t ctr; + uint64_t ctr = 0; auto rv = d.deserialise_entry_version(); if (rv != NoVersion) @@ -515,13 +515,14 @@ namespace ccf::kv::untyped std::unique_ptr create_committer( AbstractChangeSet* changes) override { - auto non_abstract = dynamic_cast(changes); + auto* non_abstract = dynamic_cast(changes); if (non_abstract == nullptr) { throw std::logic_error("Type confusion error"); } - auto snapshot_change_set = dynamic_cast(non_abstract); + auto* snapshot_change_set = + dynamic_cast(non_abstract); if (snapshot_change_set != nullptr) { return std::make_unique( @@ -570,7 +571,7 @@ namespace ccf::kv::untyped * * @return Security domain of the map (affects serialisation) */ - virtual SecurityDomain get_security_domain() override + SecurityDomain get_security_domain() override { return security_domain; } @@ -578,13 +579,17 @@ namespace ccf::kv::untyped bool operator==(const Map& that) const { if (name != that.name) + { return false; + } - auto state1 = roll.commits->get_tail(); - auto state2 = that.roll.commits->get_tail(); + auto* state1 = roll.commits->get_tail(); + auto* state2 = that.roll.commits->get_tail(); if (state1->version != state2->version) + { return false; + } size_t count = 0; state2->state.foreach([&count](const K&, const VersionV&) { @@ -604,7 +609,7 @@ namespace ccf::kv::untyped { return false; } - else if (found.value != v.value) + if (found.value != v.value) { return false; } @@ -619,7 +624,9 @@ namespace ccf::kv::untyped }); if (i != count) + { ok = false; + } return ok; } @@ -636,9 +643,9 @@ namespace ccf::kv::untyped // This takes a snapshot of the state of the map at the last entry // committed at or before this version. The Map expects to be locked while // taking the snapshot. - auto r = roll.commits->get_head(); + auto* r = roll.commits->get_head(); - for (auto current = roll.commits->get_tail(); current != nullptr; + for (auto* current = roll.commits->get_tail(); current != nullptr; current = current->prev) { if (current->version <= v) @@ -660,7 +667,7 @@ namespace ccf::kv::untyped // compaction. while (roll.commits->get_head() != roll.commits->get_tail()) { - auto r = roll.commits->get_head(); + auto* r = roll.commits->get_head(); // Globally committed but not discardable. if (r->version == v) @@ -682,14 +689,16 @@ namespace ccf::kv::untyped // Stop if the next state may be rolled back or is the only state. // This ensures there is always a state present. if (r->next->version > v) + { return; + } - auto c = roll.commits->pop(); + auto* c = roll.commits->pop(); roll.empty_commits.insert(c); } // There is only one roll. We may need to call the commit hook. - auto r = roll.commits->get_head(); + auto* r = roll.commits->get_head(); if (global_hook && !r->writes.empty()) { @@ -722,20 +731,24 @@ namespace ccf::kv::untyped while (roll.commits->get_head() != roll.commits->get_tail()) { - auto r = roll.commits->get_tail(); + auto* r = roll.commits->get_tail(); // The initial empty state has v = 0, so will not be discarded if it // is present. if (r->version <= v) + { break; + } advance = true; - auto c = roll.commits->pop_tail(); + auto* c = roll.commits->pop_tail(); roll.empty_commits.insert(c); } if (advance) + { roll.rollback_counter++; + } } void clear() override @@ -756,12 +769,15 @@ namespace ccf::kv::untyped sl.unlock(); } + // NOLINTNEXTLINE(bugprone-exception-escape) void swap(AbstractMap* map_) override { - Map* map = dynamic_cast(map_); + auto* map = dynamic_cast(map_); if (map == nullptr) + { throw std::logic_error( "Attempted to swap maps with incompatible types"); + } std::swap(roll, map->roll); } @@ -774,7 +790,7 @@ namespace ccf::kv::untyped ChangeSetPtr changes = nullptr; // Find the last entry committed at or before this version. - for (auto current = roll.commits->get_tail(); current != nullptr; + for (auto* current = roll.commits->get_tail(); current != nullptr; current = current->prev) { if (current->version <= version) diff --git a/src/kv/version_v.h b/src/kv/version_v.h index 576cbe19b808..03308b48021d 100644 --- a/src/kv/version_v.h +++ b/src/kv/version_v.h @@ -21,7 +21,7 @@ namespace ccf::kv VersionV(Version ver, Version read_ver, V val) : version(ver), read_version(read_ver), - value(val) + value(std::move(val)) {} }; } \ No newline at end of file diff --git a/src/node/channels.h b/src/node/channels.h index c1aaa0b4b00d..1464b949b7d6 100644 --- a/src/node/channels.h +++ b/src/node/channels.h @@ -37,7 +37,7 @@ namespace ccf { - enum ChannelStatus + enum ChannelStatus : uint8_t { INACTIVE = 0, INITIATED, @@ -105,7 +105,7 @@ namespace ccf WireNonce(uint64_t nonce_) : nonce(nonce_) {} - uint64_t get_val() const + [[nodiscard]] uint64_t get_val() const { return *reinterpret_cast(this); } @@ -114,33 +114,30 @@ namespace ccf sizeof(WireNonce) == sizeof(MsgNonce), "WireNonce is the wrong size"); // Static helper functions for serialization/deserialization - namespace + inline WireNonce get_wire_nonce(const GcmHdr& header) { - static inline WireNonce get_wire_nonce(const GcmHdr& header) - { - return *reinterpret_cast(header.iv.data()); - } + return *reinterpret_cast(header.iv.data()); + } - template - static inline void append_value(std::vector& target, const T& t) - { - const auto size_before = target.size(); - auto size = sizeof(t); - target.resize(size_before + size); - auto data = target.data() + size_before; - serialized::write(data, size, t); - } + template + inline void append_value(std::vector& target, const T& t) + { + const auto size_before = target.size(); + auto size = sizeof(t); + target.resize(size_before + size); + auto* data = target.data() + size_before; + serialized::write(data, size, t); + } - static inline void append_buffer( - std::vector& target, std::span src) - { - const auto size_before = target.size(); - auto size = src.size() + sizeof(src.size()); - target.resize(size_before + size); - auto data = target.data() + size_before; - serialized::write(data, size, src.size()); - serialized::write(data, size, src.data(), src.size()); - } + inline void append_buffer( + std::vector& target, std::span src) + { + const auto size_before = target.size(); + auto size = src.size() + sizeof(src.size()); + target.resize(size_before + size); + auto* data = target.data() + size_before; + serialized::write(data, size, src.size()); + serialized::write(data, size, src.data(), src.size()); } // Key exchange states are: @@ -445,7 +442,7 @@ namespace ccf "recv_key_exchange_init({} bytes, {})", size, they_have_priority); // Parse fields from incoming message - size_t peer_version = serialized::read(data, size); + auto peer_version = serialized::read(data, size); if (peer_version != protocol_version) { CHANNEL_RECV_FAIL( @@ -515,17 +512,15 @@ namespace ccf CHANNEL_RECV_TRACE("Ignoring lower priority key init"); return true; } - else + + // Whatever else we _were_ doing, we've received a valid init from them + // - reset to use it + if (status.check(ESTABLISHED)) { - // Whatever else we _were_ doing, we've received a valid init from them - // - reset to use it - if (status.check(ESTABLISHED)) - { - kex_ctx.reset(); - } - peer_cert = cert; - peer_cv = verifier; + kex_ctx.reset(); } + peer_cert = cert; + peer_cv = verifier; CHANNEL_RECV_TRACE( "recv_key_exchange_init: version={} ks={} sig={} pc={} salt={}", @@ -563,7 +558,7 @@ namespace ccf } // Parse fields from incoming message - size_t peer_version = serialized::read(data, size); + auto peer_version = serialized::read(data, size); if (peer_version != protocol_version) { CHANNEL_RECV_FAIL( @@ -710,13 +705,11 @@ namespace ccf "Buffer header wants {} bytes, but only {} remain", sz, size); return {}; } - else - { - data += sz; - size -= sz; - } - return std::span(data_start, sz); + data += sz; + size -= sz; + + return {data_start, sz}; } bool verify_peer_certificate( @@ -745,10 +738,8 @@ namespace ccf return true; } - else - { - return false; - } + + return false; } bool verify_peer_signature( @@ -760,12 +751,7 @@ namespace ccf "Verifying peer signature with peer certificate serial {}", verifier ? verifier->serial_number() : "no peer_cv!"); - if (!verifier || !verifier->verify(msg, sig)) - { - return false; - } - - return true; + return verifier && verifier->verify(msg, sig); } void update_send_key() @@ -906,14 +892,12 @@ namespace ccf outgoing_forwarding_queue_size); return true; } - else - { - CHANNEL_SEND_FAIL( - "Unable to queue outgoing forwarding message - already queued " - "maximum {} messages", - outgoing_forwarding_queue_size); - return false; - } + + CHANNEL_SEND_FAIL( + "Unable to queue outgoing forwarding message - already queued " + "maximum {} messages", + outgoing_forwarding_queue_size); + return false; } default: @@ -937,7 +921,8 @@ namespace ccf nonce); GcmHdr gcm_hdr; - gcm_hdr.set_iv((const uint8_t*)&wire_nonce, sizeof(wire_nonce)); + gcm_hdr.set_iv( + reinterpret_cast(&wire_nonce), sizeof(wire_nonce)); std::vector cipher; assert(send_key); @@ -973,16 +958,16 @@ namespace ccf const ccf::crypto::Pem& service_cert_, ccf::crypto::ECKeyPairPtr node_kp_, const ccf::crypto::Pem& node_cert_, - const NodeId& self_, - const NodeId& peer_id_, + NodeId self_, + NodeId peer_id_, size_t message_limit_) : - self(self_), + self(std::move(self_)), service_cert(service_cert_), - node_kp(node_kp_), + node_kp(std::move(node_kp_)), node_cert(node_cert_), to_host(writer_factory.create_writer_to_outside()), - peer_id(peer_id_), - status(fmt::format("Channel to {}", peer_id_), INACTIVE), + peer_id(std::move(peer_id_)), + status(fmt::format("Channel to {}", peer_id), INACTIVE), message_limit(message_limit_) { auto e = ccf::crypto::get_entropy(); @@ -1069,9 +1054,9 @@ namespace ccf size_t size_ = size; GcmHdr hdr; - serialized::skip(data_, size_, (size_ - hdr.serialised_size())); + serialized::skip(data_, size_, (size_ - GcmHdr::serialised_size())); hdr.deserialise(data_, size_); - size -= hdr.serialised_size(); + size -= GcmHdr::serialised_size(); if (!verify(hdr, std::span(data, size))) { diff --git a/src/node/cose_common.h b/src/node/cose_common.h index 225dd748dc81..8371958e1483 100644 --- a/src/node/cose_common.h +++ b/src/node/cose_common.h @@ -27,12 +27,12 @@ namespace ccf::cose static std::string qcbor_buf_to_string(const UsefulBufC& buf) { - return std::string(reinterpret_cast(buf.ptr), buf.len); + return {reinterpret_cast(buf.ptr), buf.len}; } static std::vector qcbor_buf_to_byte_vector(const UsefulBufC& buf) { - auto ptr = static_cast(buf.ptr); + const auto* ptr = static_cast(buf.ptr); return {ptr, ptr + buf.len}; } @@ -70,7 +70,7 @@ namespace ccf::cose static std::pair extract_iss_sub_from_sig(const std::vector& cose_sign1) { - QCBORError qcbor_result; + QCBORError qcbor_result = QCBOR_SUCCESS; QCBORDecodeContext ctx; UsefulBufC buf{cose_sign1.data(), cose_sign1.size()}; QCBORDecode_Init(&ctx, buf, QCBOR_DECODE_MODE_NORMAL); @@ -88,10 +88,11 @@ namespace ccf::cose throw COSEDecodeError("COSE_Sign1 is not tagged"); } - QCBORDecode_EnterBstrWrapped(&ctx, QCBOR_TAG_REQUIREMENT_NOT_A_TAG, NULL); - QCBORDecode_EnterMap(&ctx, NULL); + QCBORDecode_EnterBstrWrapped( + &ctx, QCBOR_TAG_REQUIREMENT_NOT_A_TAG, nullptr); + QCBORDecode_EnterMap(&ctx, nullptr); - enum + enum : std::uint8_t { CWT_CLAIMS_INDEX, END_INDEX, @@ -126,7 +127,7 @@ namespace ccf::cose fmt::format("Failed to decode CWT claims: {}", decode_error)); } - enum + enum : std::uint8_t { CWT_ISS_INDEX, CWT_SUB_INDEX, @@ -160,10 +161,8 @@ namespace ccf::cose auto subject = tstring_to_string(cwt_items[CWT_SUB_INDEX]); return {issuer, subject}; } - else - { - throw COSEDecodeError( - "Missing issuer and subject values in CWT Claims in COSE_Sign1"); - } + + throw COSEDecodeError( + "Missing issuer and subject values in CWT Claims in COSE_Sign1"); } } \ No newline at end of file diff --git a/src/node/encryptor.h b/src/node/encryptor.h index dfb50c901291..b452f97f4722 100644 --- a/src/node/encryptor.h +++ b/src/node/encryptor.h @@ -35,7 +35,7 @@ namespace ccf static_cast(term); } - uint64_t get_term() const + [[nodiscard]] uint64_t get_term() const { return *reinterpret_cast(iv.data() + IV_DELIMITER); } diff --git a/src/node/historical_queries.h b/src/node/historical_queries.h index cf7c4d8d97f7..70e477ed7f1c 100644 --- a/src/node/historical_queries.h +++ b/src/node/historical_queries.h @@ -69,7 +69,7 @@ namespace ccf::historical const ccf::kv::StorePtr& sig_store) { auto tx = sig_store->create_read_only_tx(); - auto signatures = tx.ro(ccf::Tables::SIGNATURES); + auto* signatures = tx.ro(ccf::Tables::SIGNATURES); return signatures->get(); } @@ -77,7 +77,7 @@ namespace ccf::historical const ccf::kv::StorePtr& sig_store) { auto tx = sig_store->create_read_only_tx(); - auto signatures = tx.ro(ccf::Tables::COSE_SIGNATURES); + auto* signatures = tx.ro(ccf::Tables::COSE_SIGNATURES); return signatures->get(); } @@ -85,7 +85,7 @@ namespace ccf::historical const ccf::kv::StorePtr& sig_store) { auto tx = sig_store->create_read_only_tx(); - auto tree = + auto* tree = tx.ro(ccf::Tables::SERIALISED_MERKLE_TREE); return tree->get(); } @@ -103,7 +103,7 @@ namespace ccf::historical // whether to keep all the writes so that we can build a diff later bool track_deletes_on_missing_keys_v = false; - enum class StoreStage + enum class StoreStage : uint8_t { Fetching, Trusted, @@ -140,8 +140,8 @@ namespace ccf::historical { std::chrono::milliseconds time_until_fetch = {}; StoreStage current_stage = StoreStage::Fetching; - ccf::crypto::Sha256Hash entry_digest = {}; - ccf::ClaimsDigest claims_digest = {}; + ccf::crypto::Sha256Hash entry_digest; + ccf::ClaimsDigest claims_digest; ccf::kv::StorePtr store = nullptr; bool is_signature = false; TxReceiptImplPtr receipt = nullptr; @@ -156,10 +156,8 @@ namespace ccf::historical return e->get_commit_nonce( {transaction_id.view, transaction_id.seqno}, true); } - else - { - throw std::logic_error("Store pointer not set"); - } + + throw std::logic_error("Store pointer not set"); } std::optional get_commit_evidence() @@ -172,10 +170,8 @@ namespace ccf::historical transaction_id.seqno, ds::to_hex(get_commit_nonce())); } - else - { - return std::nullopt; - } + + return std::nullopt; } }; using StoreDetailsPtr = std::shared_ptr; @@ -198,7 +194,7 @@ namespace ccf::historical {} }; - VersionedSecret earliest_secret_ = {}; + VersionedSecret earliest_secret_; StoreDetailsPtr next_secret_fetch_handle = nullptr; struct Request @@ -206,7 +202,7 @@ namespace ccf::historical AllRequestedStores& all_stores; RequestedStores my_stores; - std::chrono::milliseconds time_to_expiry; + std::chrono::milliseconds time_to_expiry{}; bool include_receipts = false; @@ -220,7 +216,7 @@ namespace ccf::historical Request(AllRequestedStores& all_stores_) : all_stores(all_stores_) {} - StoreDetailsPtr get_store_details(ccf::SeqNo seqno) const + [[nodiscard]] StoreDetailsPtr get_store_details(ccf::SeqNo seqno) const { auto it = all_stores.find(seqno); if (it != all_stores.end()) @@ -231,7 +227,7 @@ namespace ccf::historical return nullptr; } - ccf::SeqNo first_requested_seqno() const + [[nodiscard]] ccf::SeqNo first_requested_seqno() const { if (!my_stores.empty()) { @@ -246,7 +242,8 @@ namespace ccf::historical bool should_include_receipts, SeqNo earliest_ledger_secret_seqno) { - std::vector removed{}, added{}; + std::vector removed{}; + std::vector added{}; bool any_diff = false; @@ -400,7 +397,8 @@ namespace ccf::historical supporting_signatures[next_seqno] = details; return; } - else if (details->is_signature) + + if (details->is_signature) { const auto filled_this = fill_receipts_from_signature(details, new_seqno); @@ -418,12 +416,10 @@ namespace ccf::historical return; } - else - { - // This is a normal transaction, and its already fetched. - // Nothing to do, consider the next. - ++next_seqno; - } + + // This is a normal transaction, and its already fetched. + // Nothing to do, consider the next. + ++next_seqno; } } } @@ -437,8 +433,17 @@ namespace ccf::historical // Iterate through earlier indices. If this signature covers them // then create a receipt for them const auto sig = get_signature(sig_details->store); + if (!sig.has_value()) + { + return false; + } const auto cose_sig = get_cose_signature(sig_details->store); - ccf::MerkleTreeHistory tree(get_tree(sig_details->store).value()); + const auto serialised_tree = get_tree(sig_details->store); + if (!serialised_tree.has_value()) + { + return false; + } + ccf::MerkleTreeHistory tree(serialised_tree.value()); // This is either pointing at the sig itself, or the closest larger // seqno we're holding @@ -516,7 +521,7 @@ namespace ccf::historical // To maintain the estimated size consumed by all requests. Gets updated // when ledger entries are fetched, and when requests are dropped. std::unordered_map> store_to_requests; - std::unordered_map raw_store_sizes{}; + std::unordered_map raw_store_sizes; CacheSize soft_store_cache_limit{std::numeric_limits::max()}; CacheSize soft_store_cache_limit_raw = @@ -727,7 +732,9 @@ namespace ccf::historical details->entry_digest = entry_digest; if (!claims_digest.empty()) + { details->claims_digest = std::move(claims_digest); + } CCF_ASSERT_FMT( details->store == nullptr, @@ -745,10 +752,12 @@ namespace ccf::historical // transaction. const auto sig = get_signature(details->store); const auto cose_sig = get_cose_signature(details->store); - assert(sig.has_value()); - details->transaction_id = {sig->view, sig->seqno}; - details->receipt = std::make_shared( - sig->sig, cose_sig, sig->root.h, nullptr, sig->node, sig->cert); + if (sig.has_value()) + { + details->transaction_id = {sig->view, sig->seqno}; + details->receipt = std::make_shared( + sig->sig, cose_sig, sig->root.h, nullptr, sig->node, sig->cert); + } } auto request_it = requests.begin(); @@ -817,10 +826,10 @@ namespace ccf::historical { // Read encrypted secrets from store auto tx = store->create_read_only_tx(); - auto encrypted_past_ledger_secret_handle = + auto* encrypted_past_ledger_secret_handle = tx.ro( ccf::Tables::ENCRYPTED_PAST_LEDGER_SECRET); - if (!encrypted_past_ledger_secret_handle) + if (encrypted_past_ledger_secret_handle == nullptr) { return false; } @@ -850,7 +859,7 @@ namespace ccf::historical auto recovered_ledger_secret = std::make_shared( ccf::decrypt_previous_ledger_secret_raw( - encrypting_secret, std::move(previous_ledger_secret->encrypted_data)), + encrypting_secret, previous_ledger_secret->encrypted_data), previous_ledger_secret->previous_secret_stored_version); // Add recovered secret to historical secrets @@ -993,9 +1002,10 @@ namespace ccf::historical const std::vector& states) { std::vector stores; - for (size_t i = 0; i < states.size(); i++) + stores.reserve(states.size()); + for (const auto& state : states) { - stores.push_back(states[i]->store); + stores.push_back(state->store); } return stores; } @@ -1004,10 +1014,10 @@ namespace ccf::historical StateCacheImpl( ccf::kv::Store& store, const std::shared_ptr& secrets, - const ringbuffer::WriterPtr& host_writer) : + ringbuffer::WriterPtr host_writer) : source_store(store), source_ledger_secrets(secrets), - to_host(host_writer), + to_host(std::move(host_writer)), historical_ledger_secrets(std::make_shared()), historical_encryptor( std::make_shared(historical_ledger_secrets)) @@ -1170,9 +1180,9 @@ namespace ccf::historical return false; } - ccf::kv::ApplyResult deserialise_result; + ccf::kv::ApplyResult deserialise_result = ccf::kv::ApplyResult::FAIL; ccf::ClaimsDigest claims_digest; - bool has_commit_evidence; + bool has_commit_evidence = false; auto store = deserialise_ledger_entry( seqno, data, @@ -1229,17 +1239,20 @@ namespace ccf::historical auto [valid_from, secret] = earliest_secret_; - if ( - secret->previous_secret_stored_version.has_value() && - secret->previous_secret_stored_version.value() == seqno) + if (secret != nullptr) { - HISTORICAL_LOG( - "Handling past ledger secret. Current earliest is valid from {}, now " - "processing secret stored at {}", - valid_from, - seqno); - handle_encrypted_past_ledger_secret(store, secret); - next_secret_fetch_handle = nullptr; + const auto& prev_version = secret->previous_secret_stored_version; + if (prev_version.has_value() && *prev_version == seqno) + { + HISTORICAL_LOG( + "Handling past ledger secret. Current earliest is valid from {}, " + "now " + "processing secret stored at {}", + valid_from, + seqno); + handle_encrypted_past_ledger_secret(store, secret); + next_secret_fetch_handle = nullptr; + } } HISTORICAL_LOG( @@ -1443,21 +1456,24 @@ namespace ccf::historical details->time_until_fetch = slow_fetch_threshold; const auto seqno = it->first; - if ( - range_to_request.has_value() && - range_to_request->second + 1 == seqno) + if (auto range_val = range_to_request; range_val.has_value()) { - range_to_request->second = seqno; - } - else - { - if (range_to_request.has_value()) + auto range = range_val.value(); + if (range.second + 1 == seqno) + { + range.second = seqno; + range_to_request = range; + } + else { // Submit fetch for previously tracked range - fetch_entries_range( - range_to_request->first, range_to_request->second); + fetch_entries_range(range.first, range.second); + // Track new range + range_to_request = std::make_pair(seqno, seqno); } - + } + else + { // Track new range range_to_request = std::make_pair(seqno, seqno); } @@ -1468,11 +1484,11 @@ namespace ccf::historical } } - if (range_to_request.has_value()) + if (auto range_val = range_to_request; range_val.has_value()) { // Submit fetch for final tracked range - fetch_entries_range( - range_to_request->first, range_to_request->second); + auto range = range_val.value(); + fetch_entries_range(range.first, range.second); } } } diff --git a/src/node/history.h b/src/node/history.h index ef22963b60ee..265c98de33d8 100644 --- a/src/node/history.h +++ b/src/node/history.h @@ -29,7 +29,7 @@ namespace ccf { - enum HashOp + enum HashOp : uint8_t { APPEND, VERIFY, @@ -80,21 +80,21 @@ namespace ccf public: NullTxHistoryPendingTx( - ccf::TxID txid_, ccf::kv::Store& store_, const NodeId& id_) : + ccf::TxID txid_, ccf::kv::Store& store_, NodeId id_) : txid(txid_), store(store_), - id(id_) + id(std::move(id_)) {} ccf::kv::PendingTxInfo call() override { auto sig = store.create_reserved_tx(txid); - auto signatures = + auto* signatures = sig.template wo(ccf::Tables::SIGNATURES); - auto cose_signatures = + auto* cose_signatures = sig.template wo(ccf::Tables::COSE_SIGNATURES); - auto serialised_tree = sig.template wo( + auto* serialised_tree = sig.template wo( ccf::Tables::SERIALISED_MERKLE_TREE); PrimarySignature sig_value(id, txid.seqno); signatures->put(sig_value); @@ -116,25 +116,25 @@ namespace ccf public: NullTxHistory( - ccf::kv::Store& store_, const NodeId& id_, ccf::crypto::ECKeyPair&) : + ccf::kv::Store& store_, NodeId id_, ccf::crypto::ECKeyPair& /*unused*/) : store(store_), - id(id_) + id(std::move(id_)) {} - void append(const std::vector&) override + void append(const std::vector& /*data*/) override { version++; } void append_entry( - const ccf::crypto::Sha256Hash& digest, - std::optional term_of_next_version_ = + const ccf::crypto::Sha256Hash& /*digest*/, + std::optional /*term_of_next_version_*/ = std::nullopt) override { version++; } - bool verify_root_signatures(ccf::kv::Version v) override + bool verify_root_signatures(ccf::kv::Version /*v*/) override { return true; } @@ -152,14 +152,15 @@ namespace ccf term_of_next_version = commit_term_; } - void compact(ccf::kv::Version) override {} + void compact(ccf::kv::Version /*v*/) override {} - bool init_from_snapshot(const std::vector&) override + bool init_from_snapshot( + const std::vector& /*hash_at_snapshot*/) override { return true; } - std::vector get_raw_leaf(uint64_t) override + std::vector get_raw_leaf(uint64_t /*index*/) override { return {}; } @@ -178,9 +179,9 @@ namespace ccf void set_service_signing_identity( std::shared_ptr service_kp_, - const ccf::COSESignaturesConfig& cose_signatures) override + const ccf::COSESignaturesConfig& /*cose_signatures*/) override { - std::ignore = std::move(service_kp_); + std::ignore = service_kp_; } const ccf::COSESignaturesConfig& get_cose_signatures_config() override @@ -202,17 +203,17 @@ namespace ccf term_of_next_version}; } - std::vector get_proof(ccf::kv::Version) override + std::vector get_proof(ccf::kv::Version /*v*/) override { return {}; } - bool verify_proof(const std::vector&) override + bool verify_proof(const std::vector& /*proof*/) override { return true; } - std::vector serialise_tree(size_t) override + std::vector serialise_tree(size_t /*to*/) override { return {}; } @@ -245,7 +246,7 @@ namespace ccf std::shared_ptr path = nullptr; public: - Proof() {} + Proof() = default; Proof(const std::vector& v) { @@ -254,7 +255,7 @@ namespace ccf path = std::make_shared(v, position); } - const HistoryTree::Hash& get_root() const + [[nodiscard]] const HistoryTree::Hash& get_root() const { return root; } @@ -264,11 +265,10 @@ namespace ccf return path; } - Proof(HistoryTree* tree, uint64_t index) - { - root = tree->root(); - path = tree->path(index); - } + Proof(HistoryTree* tree, uint64_t index) : + root(tree->root()), + path(tree->path(index)) + {} Proof(const Proof&) = delete; @@ -278,18 +278,17 @@ namespace ccf { return false; } - else if (tree->max_index() == path->max_index()) + + if (tree->max_index() == path->max_index()) { return tree->root() == root && path->verify(root); } - else - { - auto past_root = tree->past_root(path->max_index()); - return path->verify(*past_root); - } + + auto past_root = tree->past_root(path->max_index()); + return path->verify(*past_root); } - std::vector to_v() const + [[nodiscard]] std::vector to_v() const { std::vector v; root.serialise(v); @@ -315,7 +314,7 @@ namespace ccf ccf::TxID txid_, ccf::kv::Store& store_, ccf::kv::TxHistory& history_, - const NodeId& id_, + NodeId id_, ccf::crypto::ECKeyPair& node_kp_, ccf::crypto::ECKeyPair_OpenSSL& service_kp_, ccf::crypto::Pem& endorsed_cert_, @@ -323,7 +322,7 @@ namespace ccf txid(txid_), store(store_), history(history_), - id(id_), + id(std::move(id_)), node_kp(node_kp_), service_kp(service_kp_), endorsed_cert(endorsed_cert_), @@ -333,11 +332,11 @@ namespace ccf ccf::kv::PendingTxInfo call() override { auto sig = store.create_reserved_tx(txid); - auto signatures = + auto* signatures = sig.template wo(ccf::Tables::SIGNATURES); - auto cose_signatures = + auto* cose_signatures = sig.template wo(ccf::Tables::COSE_SIGNATURES); - auto serialised_tree = sig.template wo( + auto* serialised_tree = sig.template wo( ccf::Tables::SERIALISED_MERKLE_TREE); ccf::crypto::Sha256Hash root = history.get_replicated_state_root(); @@ -360,7 +359,8 @@ namespace ccf const auto& service_key_der = service_kp.public_key_der(); auto kid = ccf::crypto::Sha256Hash(service_key_der).hex_str(); - std::span kid_span{(uint8_t*)kid.data(), kid.size()}; + std::span kid_span{ + reinterpret_cast(kid.data()), kid.size()}; const auto time_since_epoch = std::chrono::duration_cast( @@ -415,31 +415,24 @@ namespace ccf class MerkleTreeHistory { - HistoryTree* tree; + std::unique_ptr tree; public: MerkleTreeHistory(MerkleTreeHistory const&) = delete; - MerkleTreeHistory(const std::vector& serialised) - { - tree = new HistoryTree(serialised); - } + MerkleTreeHistory(const std::vector& serialised) : + tree(std::make_unique(serialised)) + {} - MerkleTreeHistory(ccf::crypto::Sha256Hash first_hash = {}) - { - tree = new HistoryTree(merkle::Hash(first_hash.h)); - } + MerkleTreeHistory(ccf::crypto::Sha256Hash first_hash = {}) : + tree(std::make_unique(merkle::Hash(first_hash.h))) + {} - ~MerkleTreeHistory() - { - delete (tree); - tree = nullptr; - } + ~MerkleTreeHistory() = default; void deserialise(const std::vector& serialised) { - delete (tree); - tree = new HistoryTree(serialised); + tree = std::make_unique(serialised); } void append(const ccf::crypto::Sha256Hash& hash) @@ -447,7 +440,7 @@ namespace ccf tree->insert(merkle::Hash(hash.h)); } - ccf::crypto::Sha256Hash get_root() const + [[nodiscard]] ccf::crypto::Sha256Hash get_root() const { const merkle::Hash& root = tree->root(); ccf::crypto::Sha256Hash result; @@ -455,11 +448,14 @@ namespace ccf return result; } - void operator=(const MerkleTreeHistory& rhs) + MerkleTreeHistory& operator=(const MerkleTreeHistory& rhs) { - delete (tree); - ccf::crypto::Sha256Hash root(rhs.get_root()); - tree = new HistoryTree(merkle::Hash(root.h)); + if (this != &rhs) + { + ccf::crypto::Sha256Hash root(rhs.get_root()); + tree = std::make_unique(merkle::Hash(root.h)); + } + return *this; } void flush(uint64_t index) @@ -491,12 +487,12 @@ namespace ccf index, end_index())); } - return Proof(tree, index); + return {tree.get(), index}; } bool verify(const Proof& r) { - return r.verify(tree); + return r.verify(tree.get()); } std::vector serialise() @@ -551,8 +547,8 @@ namespace ccf T replicated_state_tree; ccf::crypto::ECKeyPair& node_kp; - ccf::crypto::COSEVerifierUniquePtr cose_verifier{}; - std::vector cose_cert_cached{}; + ccf::crypto::COSEVerifierUniquePtr cose_verifier; + std::vector cose_cert_cached; ccf::tasks::Task emit_signature_periodic_task; size_t sig_tx_interval; @@ -560,7 +556,7 @@ namespace ccf ccf::pal::Mutex state_lock; ccf::kv::Term term_of_last_version = 0; - ccf::kv::Term term_of_next_version; + ccf::kv::Term term_of_next_version{}; std::optional endorsed_cert = std::nullopt; @@ -575,13 +571,13 @@ namespace ccf public: HashedTxHistory( ccf::kv::Store& store_, - const NodeId& id_, + NodeId id_, ccf::crypto::ECKeyPair& node_kp_, size_t sig_tx_interval_ = 0, size_t sig_ms_interval_ = 0, bool signature_timer = false) : store(store_), - id(id_), + id(std::move(id_)), node_kp(node_kp_), sig_tx_interval(sig_tx_interval_), sig_ms_interval(sig_ms_interval_) @@ -671,7 +667,7 @@ namespace ccf ccf::tasks::add_periodic_task(emit_signature_periodic_task, delay, delay); } - ~HashedTxHistory() + ~HashedTxHistory() override { if (emit_signature_periodic_task != nullptr) { @@ -691,7 +687,7 @@ namespace ccf // deserialising the tree in the signatures table and then applying the // hash of the transaction at which the snapshot was taken auto tx = store.create_read_only_tx(); - auto tree_h = tx.template ro( + auto* tree_h = tx.template ro( ccf::Tables::SERIALISED_MERKLE_TREE); auto tree = tree_h->get(); if (!tree.has_value()) @@ -740,7 +736,7 @@ namespace ccf { auto tx = store.create_read_only_tx(); - auto signatures = + auto* signatures = tx.template ro(ccf::Tables::SIGNATURES); auto sig = signatures->get(); if (!sig.has_value()) @@ -756,7 +752,7 @@ namespace ccf return false; } - auto cose_signatures = + auto* cose_signatures = tx.template ro(ccf::Tables::COSE_SIGNATURES); auto cose_sig = cose_signatures->get(); @@ -782,7 +778,7 @@ namespace ccf return true; } - auto service = tx.template ro(Tables::SERVICE); + auto* service = tx.template ro(Tables::SERVICE); auto service_info = service->get(); if (!service_info.has_value()) @@ -807,10 +803,8 @@ namespace ccf return replicated_state_tree.serialise( replicated_state_tree.begin_index(), to); } - else - { - return {}; - } + + return {}; } void set_term(ccf::kv::Term t) override diff --git a/src/node/http_node_client.h b/src/node/http_node_client.h index 9e46c0315f9c..6859b91855ba 100644 --- a/src/node/http_node_client.h +++ b/src/node/http_node_client.h @@ -20,9 +20,9 @@ namespace ccf rpc_map, node_sign_kp, self_signed_node_cert_, endorsed_node_cert_) {} - virtual ~HTTPNodeClient() {} + ~HTTPNodeClient() override = default; - virtual bool make_request(::http::Request& request) override + bool make_request(::http::Request& request) override { const auto& node_cert = endorsed_node_cert.has_value() ? endorsed_node_cert.value() : @@ -44,7 +44,8 @@ namespace ccf if (rs != HTTP_STATUS_OK) { auto ser_res = ctx->serialise_response(); - std::string str((char*)ser_res.data(), ser_res.size()); + std::string str( + reinterpret_cast(ser_res.data()), ser_res.size()); LOG_DEBUG_FMT("Request failed: {}", str); } diff --git a/src/node/jwt_key_auto_refresh.h b/src/node/jwt_key_auto_refresh.h index d8d1704574f4..dec0224831ce 100644 --- a/src/node/jwt_key_auto_refresh.h +++ b/src/node/jwt_key_auto_refresh.h @@ -33,15 +33,15 @@ namespace ccf const std::shared_ptr& consensus, const std::shared_ptr& rpcsessions, const std::shared_ptr& rpc_map, - const ccf::crypto::ECKeyPairPtr& node_sign_kp, - const ccf::crypto::Pem& node_cert) : + ccf::crypto::ECKeyPairPtr node_sign_kp, + ccf::crypto::Pem node_cert) : refresh_interval_s(refresh_interval_s), network(network), consensus(consensus), rpcsessions(rpcsessions), rpc_map(rpc_map), - node_sign_kp(node_sign_kp), - node_cert(node_cert), + node_sign_kp(std::move(node_sign_kp)), + node_cert(std::move(node_cert)), attempts(0) {} @@ -278,8 +278,8 @@ namespace ccf void refresh_jwt_keys() { auto tx = network.tables->create_read_only_tx(); - auto jwt_issuers = tx.ro(network.jwt_issuers); - auto ca_cert_bundles = tx.ro(network.ca_cert_bundles); + auto* jwt_issuers = tx.ro(network.jwt_issuers); + auto* ca_cert_bundles = tx.ro(network.ca_cert_bundles); jwt_issuers->foreach([this, &ca_cert_bundles]( const JwtIssuer& issuer, const JwtIssuerMetadata& metadata) { @@ -297,7 +297,7 @@ namespace ccf LOG_DEBUG_FMT( "JWT key auto-refresh: Refreshing keys for issuer '{}'", issuer); - auto& ca_cert_bundle_name = metadata.ca_cert_bundle_name.value(); + const auto& ca_cert_bundle_name = metadata.ca_cert_bundle_name.value(); auto ca_cert_bundle_pem = ca_cert_bundles->get(ca_cert_bundle_name); if (!ca_cert_bundle_pem.has_value()) { @@ -348,7 +348,7 @@ namespace ccf } // Returns a copy of the current attempts - size_t get_attempts() const + [[nodiscard]] size_t get_attempts() const { return attempts.load(); } diff --git a/src/node/ledger_secret.h b/src/node/ledger_secret.h index 8552e55ac430..57449b8be7e0 100644 --- a/src/node/ledger_secret.h +++ b/src/node/ledger_secret.h @@ -31,7 +31,7 @@ namespace ccf ccf::crypto::MDType::SHA256, raw_key, {commit_secret_label_, - commit_secret_label_ + sizeof(commit_secret_label_)}); + commit_secret_label_ + strlen(commit_secret_label_)}); } return commit_secret.value(); } @@ -109,7 +109,7 @@ namespace nlohmann { static void to_json(json& j, const ccf::LedgerSecretPtr& s) { - if (s.get()) + if (s.get() != nullptr) { j = *s; } diff --git a/src/node/ledger_secrets.h b/src/node/ledger_secrets.h index 8d356c1a6d1b..c7f0c13f8dd1 100644 --- a/src/node/ledger_secrets.h +++ b/src/node/ledger_secrets.h @@ -102,7 +102,7 @@ namespace ccf // another tx. To prevent conflicts, accessing the ledger secrets // require access to a tx object, which must take a dependency on the // secrets table. - auto secrets = tx.ro(Tables::ENCRYPTED_LEDGER_SECRETS); + auto* secrets = tx.ro(Tables::ENCRYPTED_LEDGER_SECRETS); secrets->get(); } @@ -225,7 +225,7 @@ namespace ccf fmt::format("No ledger secrets at {}", up_to.has_value())); } - return LedgerSecretsMap(ledger_secrets.begin(), ++search); + return {ledger_secrets.begin(), ++search}; } void restore_historical(LedgerSecretsMap&& restored_ledger_secrets) diff --git a/src/node/local_sealing.h b/src/node/local_sealing.h index 6dd5ecf0e30c..d688b6740f63 100644 --- a/src/node/local_sealing.h +++ b/src/node/local_sealing.h @@ -88,7 +88,7 @@ namespace ccf struct SealedLedgerSecretAAD { ccf::kv::Version version = 0; - ccf::pal::snp::TcbVersionRaw tcb_version = {}; + ccf::pal::snp::TcbVersionRaw tcb_version; }; DECLARE_JSON_TYPE_WITH_OPTIONAL_FIELDS(SealedLedgerSecretAAD); @@ -138,7 +138,7 @@ namespace ccf } inline std::optional unseal_ledger_secret_from_disk( - ccf::kv::Version expected_version, + ccf::kv::Version /*expected_version*/, const files::fs::path& ledger_secret_path) { try @@ -193,7 +193,7 @@ namespace ccf { std::vector> files; std::map files_map; - for (auto f : files::fs::directory_iterator(sealed_secret_dir)) + for (const auto& f : files::fs::directory_iterator(sealed_secret_dir)) { auto filename = f.path().filename(); std::optional ledger_version = diff --git a/src/node/node_client.h b/src/node/node_client.h index f9317e1ab845..cf74b8df37a6 100644 --- a/src/node/node_client.h +++ b/src/node/node_client.h @@ -23,13 +23,13 @@ namespace ccf ccf::crypto::ECKeyPairPtr node_sign_kp_, const ccf::crypto::Pem& self_signed_node_cert_, const std::optional& endorsed_node_cert_) : - rpc_map(rpc_map_), - node_sign_kp(node_sign_kp_), + rpc_map(std::move(rpc_map_)), + node_sign_kp(std::move(node_sign_kp_)), self_signed_node_cert(self_signed_node_cert_), endorsed_node_cert(endorsed_node_cert_) {} - virtual ~NodeClient() {} + virtual ~NodeClient() = default; virtual bool make_request(::http::Request& request) = 0; }; diff --git a/src/node/node_configuration_subsystem.h b/src/node/node_configuration_subsystem.h index 009cb13ccd57..caee601fb880 100644 --- a/src/node/node_configuration_subsystem.h +++ b/src/node/node_configuration_subsystem.h @@ -21,14 +21,14 @@ namespace ccf node_config_state({node_state_.get_node_config(), {}, false}) {} - virtual ~NodeConfigurationSubsystem() = default; + ~NodeConfigurationSubsystem() override = default; static char const* get_subsystem_name() { return "NodeConfiguration"; } - virtual const NodeConfigurationState& get() override + const NodeConfigurationState& get() override { if (!node_config_state.initialized) { diff --git a/src/node/node_signature_verify.h b/src/node/node_signature_verify.h index b3b7bacf59cd..306c0df63475 100644 --- a/src/node/node_signature_verify.h +++ b/src/node/node_signature_verify.h @@ -17,7 +17,7 @@ namespace ccf size_t expected_root_size) { ccf::crypto::Pem node_cert; - auto node_endorsed_certs = tx.template ro( + auto* node_endorsed_certs = tx.template ro( ccf::Tables::NODE_ENDORSED_CERTIFICATES); auto node_endorsed_cert = node_endorsed_certs->get(node_id); if (!node_endorsed_cert.has_value()) @@ -25,7 +25,7 @@ namespace ccf // No endorsed certificate for node. Its (self-signed) certificate // must be stored in the nodes table (1.x ledger only) - auto nodes = tx.template ro(ccf::Tables::NODES); + auto* nodes = tx.template ro(ccf::Tables::NODES); auto node = nodes->get(node_id); if (!node.has_value()) { @@ -35,10 +35,13 @@ namespace ccf return false; } - CCF_ASSERT_FMT( - node->cert.has_value(), - "No certificate recorded in nodes table for {} (1.x ledger)", - node_id); + if (!node->cert.has_value()) + { + LOG_FAIL_FMT( + "No certificate recorded in nodes table for {} (1.x ledger)", + node_id); + return false; + } node_cert = node->cert.value(); } diff --git a/src/node/node_state.h b/src/node/node_state.h index 17c30e598f52..434ae488d41c 100644 --- a/src/node/node_state.h +++ b/src/node/node_state.h @@ -57,6 +57,7 @@ # include "kv/test/null_encryptor.h" #endif +#include #include #include #define FMT_HEADER_ONLY @@ -76,7 +77,7 @@ namespace ccf ccf::crypto::Pem service_cert; }; - void reset_data(std::vector& data) + inline void reset_data(std::vector& data) { data.clear(); data.shrink_to_fit(); @@ -90,10 +91,10 @@ namespace ccf // ::ds::StateMachine sm; pal::Mutex lock; - StartType start_type; + StartType start_type = StartType::Start; ccf::crypto::CurveID curve_id; - std::vector subject_alt_names = {}; + std::vector subject_alt_names; std::shared_ptr node_sign_kp; NodeId self; @@ -117,8 +118,8 @@ namespace ccf ringbuffer::AbstractWriterFactory& writer_factory; ringbuffer::WriterPtr to_host; ccf::consensus::Configuration consensus_config; - size_t sig_tx_interval; - size_t sig_ms_interval; + size_t sig_tx_interval = 0; + size_t sig_ms_interval = 0; NetworkState& network; @@ -140,11 +141,11 @@ namespace ccf // std::shared_ptr recovery_store; - ccf::kv::Version recovery_v; + ccf::kv::Version recovery_v = 0; ccf::crypto::Sha256Hash recovery_root; std::vector view_history; ::consensus::Index last_recovered_signed_idx = 0; - RecoveredEncryptedLedgerSecrets recovered_encrypted_ledger_secrets = {}; + RecoveredEncryptedLedgerSecrets recovered_encrypted_ledger_secrets; ::consensus::Index last_recovered_idx = 0; static const size_t recovery_batch_size = 100; @@ -178,7 +179,7 @@ namespace ccf // Create a new store to verify the snapshot only snapshot_store = make_store(); auto snapshot_history = std::make_shared( - *snapshot_store.get(), + *snapshot_store, self, *node_sign_kp, sig_tx_interval, @@ -223,7 +224,7 @@ namespace ccf writer_factory(writer_factory), to_host(writer_factory.create_writer_to_outside()), network(network), - rpcsessions(rpcsessions), + rpcsessions(std::move(rpcsessions)), share_manager(network.ledger_secrets) {} @@ -437,13 +438,14 @@ namespace ccf // Check that tcbm in endorsement matches reported TCB in our // retrieved attestation - auto* quote = reinterpret_cast( - quote_info.quote.data()); + const auto* quote = + reinterpret_cast( + quote_info.quote.data()); const auto reported_tcb = quote->reported_tcb; // tcbm is a single hex value, like DB18000000000004. To match // that with a TcbVersion, reverse the bytes. - const uint8_t* tcb_begin = + const auto* tcb_begin = reinterpret_cast(&reported_tcb); const std::span tcb_bytes{ tcb_begin, tcb_begin + sizeof(reported_tcb)}; @@ -526,19 +528,19 @@ namespace ccf quote_endorsements_client->fetch_endorsements(); return; } - else // Non-SNP - { - if (!((quote_info.format == QuoteFormat::oe_sgx_v1 && - !quote_info.endorsements.empty()) || - (quote_info.format != QuoteFormat::oe_sgx_v1 && - quote_info.endorsements.empty()))) - { - throw std::runtime_error( - "SGX quote generation should have already fetched endorsements"); - } - launch_node(); + // Non-SNP + if ( + (quote_info.format == QuoteFormat::oe_sgx_v1 && + quote_info.endorsements.empty()) || + (quote_info.format != QuoteFormat::oe_sgx_v1 && + !quote_info.endorsements.empty())) + { + throw std::runtime_error( + "SGX quote generation should have already fetched endorsements"); } + + launch_node(); }; pal::PlatformAttestationReportData report_data = @@ -798,7 +800,7 @@ namespace ccf } auto tx = network.tables->create_read_only_tx(); - auto signatures = tx.ro(network.signatures); + auto* signatures = tx.ro(network.signatures); auto sig = signatures->get(); if (!sig.has_value()) { @@ -947,7 +949,7 @@ namespace ccf [this](ccf::kv::Version, const ccf::kv::untyped::Write&) -> ccf::kv::ConsensusHookPtr { jwt_key_auto_refresh->schedule_once(); - return ccf::kv::ConsensusHookPtr(nullptr); + return {nullptr}; }); } @@ -980,7 +982,7 @@ namespace ccf sm.expect(NodeStartupState::readingPublicLedger); - auto data = entries.data(); + const auto* data = entries.data(); auto size = entries.size(); if (size == 0) @@ -1162,8 +1164,8 @@ namespace ccf history->set_service_signing_identity( network.identity->get_key_pair(), cs_cfg); - auto h = dynamic_cast(history.get()); - if (h) + auto* h = dynamic_cast(history.get()); + if (h != nullptr) { h->set_node_id(self); } @@ -1192,7 +1194,7 @@ namespace ccf return; } - auto data = entries.data(); + const auto* data = entries.data(); auto size = entries.size(); if (size == 0) @@ -1274,7 +1276,7 @@ namespace ccf recovery_v)); } - auto h = + auto* h = dynamic_cast(recovery_store->get_history().get()); if (h->get_replicated_state_root() != recovery_root) { @@ -1283,7 +1285,7 @@ namespace ccf recovery_v)); } - network.tables->swap_private_maps(*recovery_store.get()); + network.tables->swap_private_maps(*recovery_store); recovery_store.reset(); // Raft should deserialise all security domains when network is opened @@ -1304,7 +1306,7 @@ namespace ccf { // Ensure this transition happens at-most-once, by checking that no // other node has already advanced the state - auto service = tx.ro(Tables::SERVICE); + auto* service = tx.ro(Tables::SERVICE); auto active_service = service->get(); if (!active_service.has_value()) @@ -1365,7 +1367,7 @@ namespace ccf // secret are issued. network.tables->set_map_hook( network.encrypted_ledger_secrets.get_name(), - network.encrypted_ledger_secrets.wrap_map_hook( + EncryptedLedgerSecretsInfo::wrap_map_hook( [this]( ccf::kv::Version version, const EncryptedLedgerSecretsInfo::Write& w) @@ -1383,7 +1385,7 @@ namespace ccf network.tables->unset_map_hook( network.encrypted_ledger_secrets.get_name()); - return ccf::kv::ConsensusHookPtr(nullptr); + return {nullptr}; })); } @@ -1419,7 +1421,7 @@ namespace ccf true /* Check transactions in order */, true /* Make use of historical secrets */); auto recovery_history = std::make_shared( - *recovery_store.get(), + *recovery_store, self, *node_sign_kp, sig_tx_interval, @@ -1433,7 +1435,7 @@ namespace ccf // Record real store version and root recovery_v = network.tables->current_version(); - auto h = dynamic_cast(history.get()); + auto* h = dynamic_cast(history.get()); recovery_root = h->get_replicated_state_root(); if (startup_snapshot_info) @@ -1463,7 +1465,7 @@ namespace ccf void trigger_ledger_chunk(ccf::kv::Tx& tx) override { - auto tx_ = static_cast(&tx); + auto* tx_ = dynamic_cast(&tx); if (tx_ == nullptr) { throw std::logic_error("Could not cast tx to CommittableTx"); @@ -1474,7 +1476,7 @@ namespace ccf void trigger_snapshot(ccf::kv::Tx& tx) override { - auto committable_tx = static_cast(&tx); + auto* committable_tx = dynamic_cast(&tx); if (committable_tx == nullptr) { throw std::logic_error("Could not cast tx to CommittableTx"); @@ -1489,7 +1491,7 @@ namespace ccf { std::lock_guard guard(lock); - auto service = tx.rw(Tables::SERVICE); + auto* service = tx.rw(Tables::SERVICE); auto service_info = service->get(); if (!service_info.has_value()) { @@ -1567,7 +1569,8 @@ namespace ccf } return; } - else if (is_part_of_network()) + + if (is_part_of_network()) { // Otherwise, if the node is part of the network. Open the network // straight away. Recovery shares are allocated to each recovery @@ -1588,11 +1591,9 @@ namespace ccf trigger_snapshot(tx); return; } - else - { - throw std::logic_error( - fmt::format("Node in state {} cannot open service", sm.value())); - } + + throw std::logic_error( + fmt::format("Node in state {} cannot open service", sm.value())); } // Decrypts chain of ledger secrets, and writes those to the ledger @@ -1613,7 +1614,7 @@ namespace ccf LedgerSecretsBroadcast::broadcast_some( InternalTablesAccess::get_trusted_nodes(tx), tx.wo(network.secrets), - std::move(recovered_ledger_secrets)); + recovered_ledger_secrets); } void initiate_private_recovery( @@ -1677,7 +1678,7 @@ namespace ccf auto [msg_type, from, payload] = ringbuffer::read_message(data, size); - auto payload_data = payload.data; + const auto* payload_data = payload.data; auto payload_size = payload.size; if (msg_type == NodeMsgType::forwarded_msg) @@ -1725,7 +1726,7 @@ namespace ccf // // always available // - bool is_primary() const override + [[nodiscard]] bool is_primary() const override { return ( (sm.check(NodeStartupState::partOfNetwork) || @@ -1748,32 +1749,32 @@ namespace ccf return consensus->primary(); } - bool is_in_initialised_state() const override + [[nodiscard]] bool is_in_initialised_state() const override { return sm.check(NodeStartupState::initialized); } - bool is_part_of_network() const override + [[nodiscard]] bool is_part_of_network() const override { return sm.check(NodeStartupState::partOfNetwork); } - bool is_reading_public_ledger() const override + [[nodiscard]] bool is_reading_public_ledger() const override { return sm.check(NodeStartupState::readingPublicLedger); } - bool is_reading_private_ledger() const override + [[nodiscard]] bool is_reading_private_ledger() const override { return sm.check(NodeStartupState::readingPrivateLedger); } - bool is_part_of_public_network() const override + [[nodiscard]] bool is_part_of_public_network() const override { return sm.check(NodeStartupState::partOfPublicNetwork); } - bool is_accessible_to_members() const override + [[nodiscard]] bool is_accessible_to_members() const override { const auto val = sm.value(); return val == NodeStartupState::partOfNetwork || @@ -1789,10 +1790,8 @@ namespace ccf { return {s, recovery_v, recovery_store->current_version()}; } - else - { - return {s, std::nullopt, std::nullopt}; - } + + return {s, std::nullopt, std::nullopt}; } bool rekey_ledger(ccf::kv::Tx& tx) override @@ -1829,7 +1828,7 @@ namespace ccf return true; } - NodeId get_node_id() const + [[nodiscard]] NodeId get_node_id() const { return self; } @@ -1880,15 +1879,9 @@ namespace ccf throw std::runtime_error(fmt::format( "{} has a trailing period, is not a valid hostname", hostname)); } - for (const auto c : final_component) - { - if (c < '0' || c > '9') - { - return false; - } - } - return true; + return std::ranges::all_of( + final_component, [](char c) { return c >= '0' && c <= '9'; }); } std::vector get_subject_alternative_names() @@ -1901,18 +1894,16 @@ namespace ccf return ccf::crypto::sans_from_string_list( config.node_certificate.subject_alt_names); } - else + + // Construct SANs from RPC interfaces, manually detecting whether each + // is a domain name or IP + std::vector sans; + for (const auto& [_, interface] : config.network.rpc_interfaces) { - // Construct SANs from RPC interfaces, manually detecting whether each - // is a domain name or IP - std::vector sans; - for (const auto& [_, interface] : config.network.rpc_interfaces) - { - auto host = split_net_address(interface.published_address).first; - sans.push_back({host, is_ip(host)}); - } - return sans; + auto host = split_net_address(interface.published_address).first; + sans.push_back({host, is_ip(host)}); } + return sans; } void accept_node_tls_connections() @@ -1933,8 +1924,12 @@ namespace ccf "Node certificate should be endorsed before accepting endorsed " "client " "connections"); - rpcsessions->set_network_cert( - endorsed_node_cert.value(), node_sign_kp->private_key_pem()); + if (auto cert_opt = endorsed_node_cert; cert_opt.has_value()) + { + const auto& endorsed_cert = cert_opt.value(); + rpcsessions->set_network_cert( + endorsed_cert, node_sign_kp->private_key_pem()); + } LOG_INFO_FMT("Network TLS connections now accepted"); } @@ -2123,14 +2118,14 @@ namespace ccf { network.tables->set_map_hook( network.secrets.get_name(), - network.secrets.wrap_map_hook( + Secrets::wrap_map_hook( [this](ccf::kv::Version hook_version, const Secrets::Write& w) -> ccf::kv::ConsensusHookPtr { // Used to rekey the ledger on a live service if (!is_part_of_network()) { // Ledger rekey is not allowed during recovery - return ccf::kv::ConsensusHookPtr(nullptr); + return {nullptr}; } const auto& ledger_secrets_for_nodes = w; @@ -2167,14 +2162,14 @@ namespace ccf } } - return ccf::kv::ConsensusHookPtr(nullptr); + return {nullptr}; })); network.tables->set_global_hook( network.secrets.get_name(), - network.secrets.wrap_commit_hook([this]( - ccf::kv::Version hook_version, - const Secrets::Write& w) { + Secrets::wrap_commit_hook([this]( + ccf::kv::Version hook_version, + const Secrets::Write& w) { // Used on recovery to initiate private recovery on backup nodes. if (!is_part_of_public_network()) { @@ -2243,7 +2238,7 @@ namespace ccf network.tables->set_global_hook( network.nodes.get_name(), - network.nodes.wrap_commit_hook( + Nodes::wrap_commit_hook( [this](ccf::kv::Version hook_version, const Nodes::Write& w) { std::vector retired_committed_nodes; for (const auto& [node_id, node_info] : w) @@ -2265,7 +2260,7 @@ namespace ccf // of the service. network.tables->set_map_hook( network.node_endorsed_certificates.get_name(), - network.node_endorsed_certificates.wrap_map_hook( + NodeEndorsedCertificates::wrap_map_hook( [this]( ccf::kv::Version hook_version, const NodeEndorsedCertificates::Write& w) @@ -2310,12 +2305,12 @@ namespace ccf n2n_channels->set_endorsed_node_cert(endorsed_node_cert.value()); } - return ccf::kv::ConsensusHookPtr(nullptr); + return {nullptr}; })); network.tables->set_global_hook( network.node_endorsed_certificates.get_name(), - network.node_endorsed_certificates.wrap_commit_hook( + NodeEndorsedCertificates::wrap_commit_hook( [this]( ccf::kv::Version hook_version, const NodeEndorsedCertificates::Write& w) { @@ -2390,7 +2385,7 @@ namespace ccf network.tables->set_global_hook( network.service.get_name(), - network.service.wrap_commit_hook( + Service::wrap_commit_hook( [this](ccf::kv::Version hook_version, const Service::Write& w) { if (!w.has_value()) { @@ -2445,7 +2440,7 @@ namespace ccf { network.tables->set_map_hook( network.encrypted_ledger_secrets.get_name(), - network.encrypted_ledger_secrets.wrap_map_hook( + EncryptedLedgerSecretsInfo::wrap_map_hook( [this]( ccf::kv::Version version, const EncryptedLedgerSecretsInfo::Write& w) @@ -2476,7 +2471,7 @@ namespace ccf recovered_encrypted_ledger_secrets.emplace_back( std::move(encrypted_ledger_secret_info.value())); - return ccf::kv::ConsensusHookPtr(nullptr); + return {nullptr}; })); } @@ -2511,7 +2506,7 @@ namespace ccf } history = std::make_shared( - *network.tables.get(), + *network.tables, self, *node_sign_kp, sig_tx_interval, @@ -2560,7 +2555,7 @@ namespace ccf // can add a new active configuration. network.tables->set_map_hook( network.nodes.get_name(), - network.nodes.wrap_map_hook( + Nodes::wrap_map_hook( [](ccf::kv::Version version, const Nodes::Write& w) -> ccf::kv::ConsensusHookPtr { return std::make_unique(version, w); @@ -2574,35 +2569,38 @@ namespace ccf network.tables->set_map_hook( network.signatures.get_name(), - network.signatures.wrap_map_hook( + Signatures::wrap_map_hook( [s = this->snapshotter]( - ccf::kv::Version version, const Signatures::Write& w) { + ccf::kv::Version version, + const Signatures::Write& w) -> ccf::kv::ConsensusHookPtr { assert(w.has_value()); auto sig = w.value(); s->record_signature(version, sig.sig, sig.node, sig.cert); - return ccf::kv::ConsensusHookPtr(nullptr); + return {nullptr}; })); network.tables->set_map_hook( network.serialise_tree.get_name(), - network.serialise_tree.wrap_map_hook( + SerialisedMerkleTree::wrap_map_hook( [s = this->snapshotter]( - ccf::kv::Version version, const SerialisedMerkleTree::Write& w) { + ccf::kv::Version version, + const SerialisedMerkleTree::Write& w) -> ccf::kv::ConsensusHookPtr { assert(w.has_value()); - auto tree = w.value(); + const auto& tree = w.value(); s->record_serialised_tree(version, tree); - return ccf::kv::ConsensusHookPtr(nullptr); + return {nullptr}; })); network.tables->set_map_hook( network.snapshot_evidence.get_name(), - network.snapshot_evidence.wrap_map_hook( + SnapshotEvidence::wrap_map_hook( [s = this->snapshotter]( - ccf::kv::Version version, const SnapshotEvidence::Write& w) { + ccf::kv::Version version, + const SnapshotEvidence::Write& w) -> ccf::kv::ConsensusHookPtr { assert(w.has_value()); auto snapshot_evidence = w.value(); s->record_snapshot_evidence_idx(version, snapshot_evidence); - return ccf::kv::ConsensusHookPtr(nullptr); + return {nullptr}; })); setup_basic_hooks(); @@ -2650,11 +2648,17 @@ namespace ccf CCF_ASSERT( snp_tcb_version.has_value(), "TCB version must be set before sealing"); - seal_ledger_secret_to_disk( - config.sealed_ledger_secret_location.value(), - snp_tcb_version.value(), - version, - ledger_secret); + if (auto loc_opt = config.sealed_ledger_secret_location; + loc_opt.has_value()) + { + if (auto tcb_opt = snp_tcb_version; tcb_opt.has_value()) + { + const auto& sealed_location = loc_opt.value(); + const auto& tcb_version = tcb_opt.value(); + seal_ledger_secret_to_disk( + sealed_location, tcb_version, version, ledger_secret); + } + } } LedgerSecretPtr unseal_ledger_secret() @@ -2666,14 +2670,17 @@ namespace ccf CCF_ASSERT( config.recover.previous_sealed_ledger_secret_location.has_value(), "Previous sealed ledger secret location must be set"); - auto ledger_secret_path = - config.recover.previous_sealed_ledger_secret_location.value(); - auto max_version = network.tables->current_version(); + if (auto path_opt = config.recover.previous_sealed_ledger_secret_location; + path_opt.has_value()) + { + const auto& ledger_secret_path = path_opt.value(); + auto max_version = network.tables->current_version(); + return find_and_unseal_ledger_secret_from_disk( + ledger_secret_path, max_version); + } - return find_and_unseal_ledger_secret_from_disk( - config.recover.previous_sealed_ledger_secret_location.value(), - max_version); + return nullptr; } public: @@ -2687,18 +2694,18 @@ namespace ccf n2n_channels->set_idle_timeout(idle_timeout); } - virtual const ccf::StartupConfig& get_node_config() const override + [[nodiscard]] const ccf::StartupConfig& get_node_config() const override { return config; } - virtual ccf::crypto::Pem get_network_cert() override + ccf::crypto::Pem get_network_cert() override { return network.identity->cert; } // Stop-gap until it becomes easier to use other HTTP clients - virtual void make_http_request( + void make_http_request( const ::http::URL& url, ::http::Request&& req, std::functionwrite_snapshot(snapshot_buf, request_id); } - virtual std::shared_ptr get_store() override + std::shared_ptr get_store() override { return network.tables; } - virtual ringbuffer::AbstractWriterFactory& get_writer_factory() override + ringbuffer::AbstractWriterFactory& get_writer_factory() override { return writer_factory; } diff --git a/src/node/node_to_node.h b/src/node/node_to_node.h index 47831ae3f219..69333cd15193 100644 --- a/src/node/node_to_node.h +++ b/src/node/node_to_node.h @@ -22,7 +22,7 @@ namespace ccf { public: NodeId from; - DroppedMessageException(const NodeId& from) : from(from) {} + DroppedMessageException(NodeId from_) : from(std::move(from_)) {} }; virtual void associate_node_address( diff --git a/src/node/node_to_node_channel_manager.h b/src/node/node_to_node_channel_manager.h index 4608afd50001..0e5a01e746c0 100644 --- a/src/node/node_to_node_channel_manager.h +++ b/src/node/node_to_node_channel_manager.h @@ -72,17 +72,31 @@ namespace ccf } // Create channel - auto channel = std::make_shared( - writer_factory, - this_node->service_cert, - this_node->node_kp, - this_node->endorsed_node_cert.value(), - this_node->node_id, - peer_id, - message_limit.value()); - auto info = ChannelInfo{channel, std::chrono::milliseconds(0)}; - channels.try_emplace(peer_id, info); - return channel; + CCF_ASSERT_FMT( + this_node->endorsed_node_cert.has_value(), + "Endorsed node cert must be set before creating channels"); + CCF_ASSERT_FMT( + message_limit.has_value(), + "Message limit must be set before creating channels"); + + if (auto cert_opt = this_node->endorsed_node_cert; cert_opt.has_value()) + { + if (auto limit_opt = message_limit; limit_opt.has_value()) + { + auto channel = std::make_shared( + writer_factory, + this_node->service_cert, + this_node->node_kp, + cert_opt.value(), + this_node->node_id, + peer_id, + limit_opt.value()); + auto info = ChannelInfo{channel, std::chrono::milliseconds(0)}; + channels.try_emplace(peer_id, info); + return channel; + } + } + return nullptr; } public: @@ -114,8 +128,8 @@ namespace ccf return; } - this_node = std::unique_ptr( - new ThisNode{self_id, service_cert, node_kp, node_cert}); + this_node = std::make_unique( + ThisNode{self_id, service_cert, node_kp, node_cert}); } void set_endorsed_node_cert( @@ -165,7 +179,7 @@ namespace ccf } } - virtual void associate_node_address( + void associate_node_address( const NodeId& peer_id, const std::string& peer_hostname, const std::string& peer_service) override diff --git a/src/node/node_types.h b/src/node/node_types.h index 7998cb891b50..7f8c713f3a77 100644 --- a/src/node/node_types.h +++ b/src/node/node_types.h @@ -14,6 +14,8 @@ namespace ccf { using Node2NodeMsg = uint64_t; + // NOLINTBEGIN(performance-enum-size) + // Type of messages exchanged between nodes enum NodeMsgType : Node2NodeMsg { @@ -51,6 +53,8 @@ namespace ccf forwarded_response_v3 }; + // NOLINTEND(performance-enum-size) + #pragma pack(push, 1) // Channel-specific header for key exchange struct ChannelHeader @@ -62,46 +66,46 @@ namespace ccf // Frontend-specific header for forwarding struct ForwardedHeader_v1 { - ForwardedMsg msg; + ForwardedMsg msg{}; ccf::FrameFormat frame_format = ccf::FrameFormat::http; }; struct ForwardedHeader_v2 : public ForwardedHeader_v1 { using ForwardedCommandId = size_t; - ForwardedCommandId id; + ForwardedCommandId id{}; }; struct ForwardedCommandHeader_v3 : public ForwardedHeader_v2 { ForwardedCommandHeader_v3() = default; ForwardedCommandHeader_v3( - ForwardedHeader_v2::ForwardedCommandId cmd_id, ccf::View view) + ForwardedHeader_v2::ForwardedCommandId cmd_id, ccf::View view) : + active_view(view) { ForwardedHeader_v1::msg = ForwardedMsg::forwarded_cmd_v3; ForwardedHeader_v2::id = cmd_id; - active_view = view; } // The view in which this session is being executed. For consistency, we // pessimistically close this session if the node is in any other view. - ccf::View active_view; + ccf::View active_view{}; }; struct ForwardedResponseHeader_v3 : public ForwardedHeader_v2 { ForwardedResponseHeader_v3() = default; ForwardedResponseHeader_v3( - ForwardedHeader_v2::ForwardedCommandId cmd_id, bool terminate) + ForwardedHeader_v2::ForwardedCommandId cmd_id, bool terminate) : + terminate_session(terminate) { ForwardedHeader_v1::msg = ForwardedMsg::forwarded_response_v3; ForwardedHeader_v2::id = cmd_id; - terminate_session = terminate; } // If the response contains a fatal error, indicate to the original node // that the session should be terminated. - bool terminate_session; + bool terminate_session{}; }; struct MessageHash @@ -112,7 +116,7 @@ namespace ccf hash(std::move(hash_)) {} - ForwardedMsg msg; + ForwardedMsg msg{}; ccf::crypto::Sha256Hash hash; }; #pragma pack(pop) diff --git a/src/node/quote_endorsements_client.h b/src/node/quote_endorsements_client.h index e32572e9abb5..f65cc97af813 100644 --- a/src/node/quote_endorsements_client.h +++ b/src/node/quote_endorsements_client.h @@ -59,10 +59,9 @@ namespace ccf struct QuoteEndorsementsClientMsg { QuoteEndorsementsClientMsg( - const std::shared_ptr& self_, - const Server& server_) : - self(self_), - server(server_) + std::shared_ptr self_, Server server_) : + self(std::move(self_)), + server(std::move(server_)) {} std::shared_ptr self; @@ -149,7 +148,7 @@ namespace ccf std::unique_ptr&& request_, CURLcode curl_response_, long status_code_) : - self(self_), + self(std::move(self_)), request(std::move(request_)), curl_response(curl_response_), status_code(status_code_) @@ -193,7 +192,7 @@ namespace ccf self->config.servers.end(), std::string{}, [](const std::string& a, const Server& b) { - return a + (a.length() > 0 ? ", " : "") + b.front().host; + return a + (!a.empty() ? ", " : "") + b.front().host; }); LOG_FAIL_FMT( "Giving up retrying fetching attestation endorsements from [{}] " @@ -256,7 +255,7 @@ namespace ccf } } - const std::string& get_name() const override + [[nodiscard]] const std::string& get_name() const override { static const std::string name = "QuoteEndorsementsClient::HandleResponseTask"; @@ -334,11 +333,11 @@ namespace ccf public: QuoteEndorsementsClient( const std::shared_ptr& rpcsessions_, - const pal::snp::EndorsementEndpointsConfiguration& config_, + pal::snp::EndorsementEndpointsConfiguration config_, QuoteEndorsementsFetchedCallback cb) : rpcsessions(rpcsessions_), - config(config_), - done_cb(cb) {}; + config(std::move(config_)), + done_cb(std::move(cb)) {}; void fetch_endorsements() { diff --git a/src/node/rpc_context_impl.h b/src/node/rpc_context_impl.h index 6d3fe5dd1331..9ab68c171bca 100644 --- a/src/node/rpc_context_impl.h +++ b/src/node/rpc_context_impl.h @@ -7,7 +7,7 @@ namespace ccf { - enum class HttpVersion + enum class HttpVersion : uint8_t { HTTP1 = 0, HTTP2 @@ -33,17 +33,18 @@ namespace ccf http_version(v) {} - std::shared_ptr get_session_context() const override + [[nodiscard]] std::shared_ptr get_session_context() + const override { return session; } - virtual void set_user_data(std::shared_ptr data) override + void set_user_data(std::shared_ptr data) override { user_data = data; } - virtual void* get_user_data() const override + [[nodiscard]] void* get_user_data() const override { return user_data.get(); } @@ -56,24 +57,24 @@ namespace ccf } // NOLINTEND(performance-move-const-arg) - ccf::PathParams path_params = {}; - virtual const ccf::PathParams& get_request_path_params() override + ccf::PathParams path_params; + const ccf::PathParams& get_request_path_params() override { return path_params; } - ccf::PathParams decoded_path_params = {}; - virtual const ccf::PathParams& get_decoded_request_path_params() override + ccf::PathParams decoded_path_params; + const ccf::PathParams& get_decoded_request_path_params() override { return decoded_path_params; } - HttpVersion get_http_version() const + [[nodiscard]] HttpVersion get_http_version() const { return http_version; } - virtual void set_error( + void set_error( ccf::http_status status, const std::string& code, std::string&& msg, @@ -109,9 +110,9 @@ namespace ccf bool terminate_session = false; virtual void set_tx_id(const ccf::TxID& tx_id) = 0; - virtual bool should_apply_writes() const = 0; + [[nodiscard]] virtual bool should_apply_writes() const = 0; virtual void reset_response() = 0; - virtual std::vector serialise_response() const = 0; + [[nodiscard]] virtual std::vector serialise_response() const = 0; virtual const std::vector& get_serialised_request() = 0; }; } \ No newline at end of file diff --git a/src/node/secret_broadcast.h b/src/node/secret_broadcast.h index 15550ee900ad..184c216f7f3a 100644 --- a/src/node/secret_broadcast.h +++ b/src/node/secret_broadcast.h @@ -23,11 +23,11 @@ namespace ccf { LedgerSecretsForNodes secrets_for_nodes; - for (auto [nid, ni] : nodes) + for (const auto& [nid, ni] : nodes) { std::vector ledger_secrets_for_node; - for (auto s : some_ledger_secrets) + for (const auto& s : some_ledger_secrets) { ledger_secrets_for_node.push_back( {s.first, @@ -50,7 +50,7 @@ namespace ccf { LedgerSecretsForNodes secrets_for_nodes; - for (auto [nid, ni] : nodes) + for (const auto& [nid, ni] : nodes) { std::vector ledger_secrets_for_node; diff --git a/src/node/session_metrics.h b/src/node/session_metrics.h index 467032d6580b..9c086f7202e7 100644 --- a/src/node/session_metrics.h +++ b/src/node/session_metrics.h @@ -27,8 +27,8 @@ namespace ccf Errors errors; }; - size_t active; - size_t peak; + size_t active = 0; + size_t peak = 0; std::map interfaces; }; diff --git a/src/node/share_manager.h b/src/node/share_manager.h index dc5c41c9eacc..df54121bd513 100644 --- a/src/node/share_manager.h +++ b/src/node/share_manager.h @@ -15,6 +15,7 @@ #include "service/internal_tables_access.h" #include +#include #include namespace ccf @@ -40,22 +41,23 @@ namespace ccf secret, shares, recovery_threshold); } - size_t get_num_shares() const + [[nodiscard]] size_t get_num_shares() const { return num_shares; } - size_t get_recovery_threshold() const + [[nodiscard]] size_t get_recovery_threshold() const { return recovery_threshold; } - std::vector> get_shares() const + [[nodiscard]] std::vector> get_shares() const { std::vector> shares_; for (const ccf::crypto::sharing::Share& share : shares) { - std::vector share_serialised(share.serialised_size); + std::vector share_serialised( + ccf::crypto::sharing::Share::serialised_size); share.serialise(share_serialised); shares_.emplace_back(share_serialised); } @@ -117,10 +119,9 @@ namespace ccf } ReconstructedLedgerSecretWrappingKey( - const ccf::crypto::sharing::Share& secret_) - { - secret = secret_; - } + const ccf::crypto::sharing::Share& secret_) : + secret(secret_) + {} LedgerSecretPtr unwrap( const std::vector& wrapped_latest_ledger_secret) @@ -192,7 +193,7 @@ namespace ccf auto active_recovery_owners_info = InternalTablesAccess::get_active_recovery_owners(tx); - if (active_recovery_owners_info.size() > 0) + if (!active_recovery_owners_info.empty()) { std::vector full_share_serialised( ccf::crypto::sharing::Share::serialised_size); @@ -238,7 +239,7 @@ namespace ccf "shares are computed"); } - size_t num_shares; + size_t num_shares = 0; if (!active_recovery_participants_info.empty()) { if (recovery_threshold > active_recovery_participants_info.size()) @@ -270,7 +271,7 @@ namespace ccf SharedLedgerSecretWrappingKey(num_shares, recovery_threshold); auto wrapped_latest_ls = ls_wrapping_key.wrap(latest_ledger_secret); - auto recovery_shares = tx.rw(Tables::SHARES); + auto* recovery_shares = tx.rw(Tables::SHARES); recovery_shares->put( {wrapped_latest_ls, compute_encrypted_shares(tx, ls_wrapping_key), @@ -293,7 +294,7 @@ namespace ccf shuffle_recovery_shares(tx, latest_ledger_secret); - auto encrypted_ls = tx.rw( + auto* encrypted_ls = tx.rw( Tables::ENCRYPTED_PAST_LEDGER_SECRET); std::vector encrypted_previous_secret = {}; @@ -370,9 +371,9 @@ namespace ccf ReconstructedLedgerSecretWrappingKey combine_from_encrypted_submitted_shares(ccf::kv::Tx& tx) { - auto encrypted_submitted_shares = tx.rw( + auto* encrypted_submitted_shares = tx.rw( Tables::ENCRYPTED_SUBMITTED_SHARES); - auto config = tx.rw(Tables::CONFIGURATION); + auto* config = tx.rw(Tables::CONFIGURATION); std::optional full_share; std::vector new_shares = {}; @@ -412,22 +413,22 @@ namespace ccf } } OPENSSL_cleanse(decrypted_share.data(), decrypted_share.size()); - if (full_share.has_value()) - { - return false; - } - - return true; + return !full_share.has_value(); }); if (full_share.has_value()) { - return ReconstructedLedgerSecretWrappingKey(full_share.value()); + return {full_share.value()}; } auto num_shares = new_shares.size(); - auto recovery_threshold = config->get()->recovery_threshold; + auto config_val = config->get(); + if (!config_val.has_value()) + { + throw std::logic_error("Configuration is not set"); + } + auto recovery_threshold = config_val->recovery_threshold; if (recovery_threshold > num_shares) { throw std::logic_error(fmt::format( @@ -437,8 +438,7 @@ namespace ccf recovery_threshold)); } - return ReconstructedLedgerSecretWrappingKey( - std::move(new_shares), recovery_threshold); + return {std::move(new_shares), recovery_threshold}; } public: @@ -546,7 +546,7 @@ namespace ccf "Recovering {} encrypted ledger secrets", recovery_ledger_secrets.size()); - auto& current_ledger_secret_version = + const auto& current_ledger_secret_version = recovery_ledger_secrets.back().next_version; if (!current_ledger_secret_version.has_value()) { @@ -555,7 +555,7 @@ namespace ccf throw std::logic_error("Current ledger secret version should be set"); } - auto encrypted_previous_ledger_secret = + auto* encrypted_previous_ledger_secret = tx.ro( Tables::ENCRYPTED_PAST_LEDGER_SECRET); @@ -567,39 +567,41 @@ namespace ccf encrypted_previous_ledger_secret->get_version_of_previous_write())); auto latest_ls = s.first->second; - for (auto it = recovery_ledger_secrets.rbegin(); - it != recovery_ledger_secrets.rend(); - it++) + for (const auto& recovery_ledger_secret : + std::ranges::reverse_view(recovery_ledger_secrets)) { - LOG_DEBUG_FMT( - "Recovering encrypted ledger secret valid at seqno {}", - it->previous_ledger_secret->version); - - if (!it->previous_ledger_secret.has_value()) + if (!recovery_ledger_secret.previous_ledger_secret.has_value()) { // Very first entry does not encrypt any other ledger secret break; } + const auto& prev_secret = + recovery_ledger_secret.previous_ledger_secret.value(); + + LOG_DEBUG_FMT( + "Recovering encrypted ledger secret valid at seqno {}", + prev_secret.version); + if ( - restored_ledger_secrets.find(it->previous_ledger_secret->version) != + restored_ledger_secrets.find(prev_secret.version) != restored_ledger_secrets.end()) { // Already decrypted this ledger secret LOG_INFO_FMT( "Skipping, already decrypted ledger secret with version {}", - it->previous_ledger_secret->version); + prev_secret.version); continue; } auto decrypted_ls_raw = decrypt_previous_ledger_secret_raw( - latest_ls, it->previous_ledger_secret->encrypted_data); + latest_ls, prev_secret.encrypted_data); auto secret = restored_ledger_secrets.emplace( - it->previous_ledger_secret->version, + prev_secret.version, std::make_shared( std::move(decrypted_ls_raw), - it->previous_ledger_secret->previous_secret_stored_version)); + prev_secret.previous_secret_stored_version)); latest_ls = secret.first->second; } @@ -629,8 +631,8 @@ namespace ccf MemberId member_id, const std::vector& submitted_recovery_share) { - auto service = tx.rw(Tables::SERVICE); - auto encrypted_submitted_shares = tx.rw( + auto* service = tx.rw(Tables::SERVICE); + auto* encrypted_submitted_shares = tx.rw( Tables::ENCRYPTED_SUBMITTED_SHARES); auto active_service = service->get(); if (!active_service.has_value()) @@ -648,7 +650,7 @@ namespace ccf static void clear_submitted_recovery_shares(ccf::kv::Tx& tx) { - auto encrypted_submitted_shares = tx.rw( + auto* encrypted_submitted_shares = tx.rw( Tables::ENCRYPTED_SUBMITTED_SHARES); encrypted_submitted_shares->clear(); } diff --git a/src/node/snapshot_serdes.h b/src/node/snapshot_serdes.h index fa9f1c41405b..eae739ccf96a 100644 --- a/src/node/snapshot_serdes.h +++ b/src/node/snapshot_serdes.h @@ -55,7 +55,7 @@ namespace ccf throw std::logic_error("Snapshot transaction size should not be zero"); } - auto receipt_data = data + store_snapshot_size; + const auto* receipt_data = data + store_snapshot_size; auto receipt_size = size - store_snapshot_size; if (receipt_size == 0) @@ -192,6 +192,6 @@ namespace ccf auto receipt = ccf::describe_receipt_v1(tx_receipt); const auto receipt_str = receipt.dump(); - return std::vector(receipt_str.begin(), receipt_str.end()); + return {receipt_str.begin(), receipt_str.end()}; } } diff --git a/src/node/snapshotter.h b/src/node/snapshotter.h index 84192d0422c9..780b2bd3cb8a 100644 --- a/src/node/snapshotter.h +++ b/src/node/snapshotter.h @@ -40,7 +40,7 @@ namespace ccf struct SnapshotInfo { - ccf::kv::Version version; + ccf::kv::Version version = 0; ccf::crypto::Sha256Hash write_set_digest; std::string commit_evidence; ccf::crypto::Sha256Hash snapshot_digest; @@ -108,7 +108,7 @@ namespace ccf std::shared_ptr _self, std::unique_ptr&& _snapshot, uint32_t _generation_count) : - self(_self), + self(std::move(_self)), snapshot(std::move(_snapshot)), generation_count(_generation_count), name(fmt::format( @@ -120,7 +120,7 @@ namespace ccf self->snapshot_(std::move(snapshot), generation_count); } - const std::string& get_name() const override + [[nodiscard]] const std::string& get_name() const override { return name; } @@ -156,7 +156,7 @@ namespace ccf auto serialised_snapshot_size = serialised_snapshot.size(); auto tx = store->create_tx(); - auto evidence = tx.rw(Tables::SNAPSHOT_EVIDENCE); + auto* evidence = tx.rw(Tables::SNAPSHOT_EVIDENCE); auto snapshot_hash = ccf::crypto::Sha256Hash(serialised_snapshot); evidence->put({snapshot_hash, snapshot_version}); @@ -229,7 +229,10 @@ namespace ccf if ( snapshot_info.is_stored && snapshot_info.evidence_idx.has_value() && - idx > snapshot_info.evidence_idx.value()) + idx > snapshot_info.evidence_idx.value() && + snapshot_info.sig.has_value() && snapshot_info.tree.has_value() && + snapshot_info.node_id.has_value() && + snapshot_info.node_cert.has_value()) { auto serialised_receipt = build_and_serialise_receipt( snapshot_info.sig.value(), @@ -357,13 +360,12 @@ namespace ccf ccf::kv::AbstractStore::StoreFlag::SNAPSHOT_AT_NEXT_SIGNATURE); ::consensus::Index last_unforced_idx = last_snapshot_idx; - for (auto it = next_snapshot_indices.rbegin(); - it != next_snapshot_indices.rend(); - it++) + for (const auto& next_snapshot_indice : + std::ranges::reverse_view(next_snapshot_indices)) { - if (!it->forced) + if (!next_snapshot_indice.forced) { - last_unforced_idx = it->idx; + last_unforced_idx = next_snapshot_indice.idx; break; } } @@ -497,7 +499,8 @@ namespace ccf auto due = next.idx - last_snapshot_idx >= snapshot_tx_interval; if (due || (next.forced && !next.done)) { - if (snapshot_generation_enabled && generate_snapshot && next.idx) + if ( + snapshot_generation_enabled && generate_snapshot && (next.idx != 0u)) { schedule_snapshot(next.idx); next.done = true; @@ -537,9 +540,8 @@ namespace ccf while (!pending_snapshots.empty()) { const auto& last_snapshot = std::prev(pending_snapshots.end()); - if ( - last_snapshot->second.evidence_idx.has_value() && - idx >= last_snapshot->second.evidence_idx.value()) + if (auto evidence_opt = last_snapshot->second.evidence_idx; + evidence_opt.has_value() && idx >= evidence_opt.value()) { break; } diff --git a/src/node/tx_receipt_impl.h b/src/node/tx_receipt_impl.h index d1c9edaa291a..69efb817f92d 100644 --- a/src/node/tx_receipt_impl.h +++ b/src/node/tx_receipt_impl.h @@ -11,15 +11,15 @@ namespace ccf // public interface by ccf::Receipt struct TxReceiptImpl { - std::vector signature = {}; + std::vector signature; std::optional> cose_signature = std::nullopt; - HistoryTree::Hash root = {}; - std::shared_ptr path = {}; - ccf::NodeId node_id = {}; + HistoryTree::Hash root; + std::shared_ptr path; + ccf::NodeId node_id; std::optional node_cert = std::nullopt; std::optional write_set_digest = std::nullopt; std::optional commit_evidence = std::nullopt; - ccf::ClaimsDigest claims_digest = {}; + ccf::ClaimsDigest claims_digest; std::optional> service_endorsements = std::nullopt; std::optional>> cose_endorsements = @@ -30,14 +30,14 @@ namespace ccf const std::optional>& cose_signature, const HistoryTree::Hash& root_, std::shared_ptr path_, - const NodeId& node_id_, + NodeId node_id_, const std::optional& node_cert_, const std::optional& write_set_digest_ = std::nullopt, // Optional to support historical transactions, where it may be absent const std::optional& commit_evidence_ = std::nullopt, // May not be set on historical transactions - const ccf::ClaimsDigest& claims_digest_ = ccf::no_claims(), + ccf::ClaimsDigest claims_digest_ = ccf::no_claims(), const std::optional>& service_endorsements_ = std::nullopt, const std::optional>>& @@ -45,12 +45,12 @@ namespace ccf signature(signature_), cose_signature(cose_signature), root(root_), - path(path_), - node_id(node_id_), + path(std::move(path_)), + node_id(std::move(node_id_)), node_cert(node_cert_), write_set_digest(write_set_digest_), commit_evidence(commit_evidence_), - claims_digest(claims_digest_), + claims_digest(std::move(claims_digest_)), service_endorsements(service_endorsements_), cose_endorsements(cose_endorsements_) {} From 5ed7d1f433662d87f1a5c32402182c776b254bbf Mon Sep 17 00:00:00 2001 From: Amaury Chamayou Date: Mon, 8 Dec 2025 17:02:26 +0000 Subject: [PATCH 09/18] fix --- src/node/local_sealing.h | 2 +- src/node/quote_endorsements_client.h | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/node/local_sealing.h b/src/node/local_sealing.h index d688b6740f63..95ccba30fc02 100644 --- a/src/node/local_sealing.h +++ b/src/node/local_sealing.h @@ -138,7 +138,7 @@ namespace ccf } inline std::optional unseal_ledger_secret_from_disk( - ccf::kv::Version /*expected_version*/, + ccf::kv::Version expected_version, const files::fs::path& ledger_secret_path) { try diff --git a/src/node/quote_endorsements_client.h b/src/node/quote_endorsements_client.h index ef3e88e23c65..a40ef651be9d 100644 --- a/src/node/quote_endorsements_client.h +++ b/src/node/quote_endorsements_client.h @@ -335,10 +335,10 @@ namespace ccf public: QuoteEndorsementsClient( - const pal::snp::EndorsementEndpointsConfiguration& config_, + pal::snp::EndorsementEndpointsConfiguration config_, QuoteEndorsementsFetchedCallback cb) : - config(config_), - done_cb(cb) {}; + config(std::move(config_)), + done_cb(std::move(cb)) {}; void fetch_endorsements() { From 27c9785bcdb76579bdd92d541bf1fc4366b42dc2 Mon Sep 17 00:00:00 2001 From: Amaury Chamayou Date: Mon, 8 Dec 2025 17:03:33 +0000 Subject: [PATCH 10/18] unused in release --- src/node/local_sealing.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/node/local_sealing.h b/src/node/local_sealing.h index 95ccba30fc02..098930bb3437 100644 --- a/src/node/local_sealing.h +++ b/src/node/local_sealing.h @@ -138,7 +138,7 @@ namespace ccf } inline std::optional unseal_ledger_secret_from_disk( - ccf::kv::Version expected_version, + [[maybe_unused]] ccf::kv::Version expected_version, const files::fs::path& ledger_secret_path) { try From eebdb923647feded465bd207d6218a14e79048c9 Mon Sep 17 00:00:00 2001 From: Amaury Chamayou Date: Mon, 8 Dec 2025 17:54:20 +0000 Subject: [PATCH 11/18] . --- src/node/cose_common.h | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/src/node/cose_common.h b/src/node/cose_common.h index 0e7c4a6cdafd..8bcfda5dac8f 100644 --- a/src/node/cose_common.h +++ b/src/node/cose_common.h @@ -75,19 +75,19 @@ namespace ccf::cose struct CwtClaims { int64_t iat{}; - std::string iss{}; - std::string sub{}; + std::string iss; + std::string sub; }; struct CcfClaims { - std::string txid{}; + std::string txid; }; struct CcfCoseReceiptPhdr { int alg{}; - std::vector kid{}; + std::vector kid; CwtClaims cwt{}; CcfClaims ccf{}; int vds{}; @@ -140,7 +140,7 @@ namespace ccf::cose for (const auto& element : proof.path) { - if (element.first) + if (element.first != 0) { std::span sibling{ element.second.data(), ccf::crypto::Sha256Hash::SIZE}; @@ -162,7 +162,7 @@ namespace ccf::cose static void decode_receipt_top_level_phdr( QCBORDecodeContext& ctx, CcfCoseReceiptPhdr& phdr) { - enum + enum : std::uint8_t { ALG_INDEX, KID_INDEX, @@ -242,7 +242,7 @@ namespace ccf::cose fmt::format("Failed to decode CWT claims: {}", decode_error)); } - enum + enum : std::uint8_t { IAT_INDEX, ISS_INDEX, @@ -306,7 +306,7 @@ namespace ccf::cose fmt::format("Failed to decode CCF claims: {}", decode_error)); } - enum + enum : std::uint8_t { TXID_INDEX, END_CCF_INDEX, @@ -341,8 +341,9 @@ namespace ccf::cose static CcfCoseReceiptPhdr decode_ccf_receipt_phdr(QCBORDecodeContext& ctx) { - QCBORDecode_EnterBstrWrapped(&ctx, QCBOR_TAG_REQUIREMENT_NOT_A_TAG, NULL); - QCBORDecode_EnterMap(&ctx, NULL); + QCBORDecode_EnterBstrWrapped( + &ctx, QCBOR_TAG_REQUIREMENT_NOT_A_TAG, nullptr); + QCBORDecode_EnterMap(&ctx, nullptr); CcfCoseReceiptPhdr phdr{}; @@ -359,7 +360,7 @@ namespace ccf::cose /* Expects QCBORDecodeContext to be at 'uhdr'. */ static std::vector decode_merkle_proofs(QCBORDecodeContext& ctx) { - QCBORDecode_EnterMap(&ctx, NULL); + QCBORDecode_EnterMap(&ctx, nullptr); auto err = QCBORDecode_GetError(&ctx); if (err != QCBOR_SUCCESS) { @@ -387,7 +388,8 @@ namespace ccf::cose std::vector proofs; for (;;) { - QCBORDecode_EnterBstrWrapped(&ctx, QCBOR_TAG_REQUIREMENT_NOT_A_TAG, NULL); + QCBORDecode_EnterBstrWrapped( + &ctx, QCBOR_TAG_REQUIREMENT_NOT_A_TAG, nullptr); err = QCBORDecode_GetError(&ctx); if (err != QCBOR_SUCCESS) { @@ -400,7 +402,7 @@ namespace ccf::cose break; } - QCBORDecode_EnterMap(&ctx, NULL); + QCBORDecode_EnterMap(&ctx, nullptr); err = QCBORDecode_GetError(&ctx); if (err != QCBOR_SUCCESS) { @@ -478,11 +480,11 @@ namespace ccf::cose if (item.uDataType == CBOR_SIMPLEV_TRUE) { - path_item.first = true; + path_item.first = 1; } else if (item.uDataType == CBOR_SIMPLEV_FALSE) { - path_item.first = false; + path_item.first = 0; } else { From e73a1df496fc13b65ba5854b55ac090497460753 Mon Sep 17 00:00:00 2001 From: Amaury Chamayou Date: Mon, 8 Dec 2025 18:14:07 +0000 Subject: [PATCH 12/18] fix --- src/node/node_to_node_channel_manager.h | 36 ++++++++----------------- 1 file changed, 11 insertions(+), 25 deletions(-) diff --git a/src/node/node_to_node_channel_manager.h b/src/node/node_to_node_channel_manager.h index 0e5a01e746c0..9dbc2973239d 100644 --- a/src/node/node_to_node_channel_manager.h +++ b/src/node/node_to_node_channel_manager.h @@ -72,31 +72,17 @@ namespace ccf } // Create channel - CCF_ASSERT_FMT( - this_node->endorsed_node_cert.has_value(), - "Endorsed node cert must be set before creating channels"); - CCF_ASSERT_FMT( - message_limit.has_value(), - "Message limit must be set before creating channels"); - - if (auto cert_opt = this_node->endorsed_node_cert; cert_opt.has_value()) - { - if (auto limit_opt = message_limit; limit_opt.has_value()) - { - auto channel = std::make_shared( - writer_factory, - this_node->service_cert, - this_node->node_kp, - cert_opt.value(), - this_node->node_id, - peer_id, - limit_opt.value()); - auto info = ChannelInfo{channel, std::chrono::milliseconds(0)}; - channels.try_emplace(peer_id, info); - return channel; - } - } - return nullptr; + auto channel = std::make_shared( + writer_factory, + this_node->service_cert, + this_node->node_kp, + this_node->endorsed_node_cert.value(), + this_node->node_id, + peer_id, + message_limit.value()); + auto info = ChannelInfo{channel, std::chrono::milliseconds(0)}; + channels.try_emplace(peer_id, info); + return channel; } public: From f572e712e1a98e659d4e0a2372e477c9b0b45436 Mon Sep 17 00:00:00 2001 From: Amaury Chamayou Date: Tue, 9 Dec 2025 09:46:55 +0000 Subject: [PATCH 13/18] optionals --- src/node/node_to_node_channel_manager.h | 27 ++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/src/node/node_to_node_channel_manager.h b/src/node/node_to_node_channel_manager.h index 9dbc2973239d..61340ac3c81f 100644 --- a/src/node/node_to_node_channel_manager.h +++ b/src/node/node_to_node_channel_manager.h @@ -54,14 +54,13 @@ namespace ccf "Requested channel with self {}", peer_id); - CCF_ASSERT_FMT( - message_limit.has_value(), - "Node-to-node message limit has not yet been set"); + if (!message_limit.has_value()) + { + throw std::runtime_error( + "Node-to-node message limit has not yet been set"); + } std::lock_guard guard(lock); - CCF_ASSERT_FMT( - this_node != nullptr && this_node->endorsed_node_cert.has_value(), - "Endorsed node certificate has not yet been set"); auto search = channels.find(peer_id); if (search != channels.end()) @@ -71,12 +70,26 @@ namespace ccf return channel_info.channel; } + if (this_node == nullptr) + { + throw std::runtime_error( + "Endorsed node certificate has not yet been set"); + } + + auto& endorsed_node_cert = this_node->endorsed_node_cert; + if (!endorsed_node_cert.has_value()) + { + throw std::runtime_error( + "Cannot create node-to-node channel without endorsed node " + "certificate"); + } + // Create channel auto channel = std::make_shared( writer_factory, this_node->service_cert, this_node->node_kp, - this_node->endorsed_node_cert.value(), + *endorsed_node_cert, this_node->node_id, peer_id, message_limit.value()); From 62fb593282afe11ce7aed377bee1588cb411679f Mon Sep 17 00:00:00 2001 From: Amaury Chamayou Date: Tue, 9 Dec 2025 14:36:45 +0000 Subject: [PATCH 14/18] tweaks --- src/kv/store.h | 3 +-- src/node/node_state.h | 15 +++------------ src/node/node_to_node_channel_manager.h | 4 ++-- 3 files changed, 6 insertions(+), 16 deletions(-) diff --git a/src/kv/store.h b/src/kv/store.h index df1af6510122..08d2d50ea721 100644 --- a/src/kv/store.h +++ b/src/kv/store.h @@ -143,8 +143,7 @@ namespace ccf::kv bool has_map_internal(const std::string& name) { - auto search = maps.find(name); - return search != maps.end(); + return maps.contains(name); } Version next_version_unsafe() diff --git a/src/node/node_state.h b/src/node/node_state.h index 229b6bd2761a..492ba2db5bee 100644 --- a/src/node/node_state.h +++ b/src/node/node_state.h @@ -527,18 +527,9 @@ namespace ccf return; } - // Non-SNP - if ( - (quote_info.format == QuoteFormat::oe_sgx_v1 && - quote_info.endorsements.empty()) || - (quote_info.format != QuoteFormat::oe_sgx_v1 && - !quote_info.endorsements.empty())) - { - throw std::runtime_error( - "SGX quote generation should have already fetched endorsements"); - } - - launch_node(); + throw std::runtime_error(fmt::format( + "Unsupported quote format for endorsements fetching: {}", + static_cast(quote_info.format))); }; pal::PlatformAttestationReportData report_data = diff --git a/src/node/node_to_node_channel_manager.h b/src/node/node_to_node_channel_manager.h index 61340ac3c81f..85757a6e3e3f 100644 --- a/src/node/node_to_node_channel_manager.h +++ b/src/node/node_to_node_channel_manager.h @@ -127,8 +127,8 @@ namespace ccf return; } - this_node = std::make_unique( - ThisNode{self_id, service_cert, node_kp, node_cert}); + this_node = + std::make_unique(self_id, service_cert, node_kp, node_cert); } void set_endorsed_node_cert( From 301a52d3c596dfe5bfe5cae90c143b10f2c980e9 Mon Sep 17 00:00:00 2001 From: Amaury Chamayou Date: Tue, 9 Dec 2025 14:51:46 +0000 Subject: [PATCH 15/18] what about virtual nodes --- src/node/node_state.h | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/node/node_state.h b/src/node/node_state.h index 492ba2db5bee..49a3662fe967 100644 --- a/src/node/node_state.h +++ b/src/node/node_state.h @@ -527,9 +527,14 @@ namespace ccf return; } - throw std::runtime_error(fmt::format( - "Unsupported quote format for endorsements fetching: {}", - static_cast(quote_info.format))); + if (quote_info.format != QuoteFormat::insecure_virtual) + { + throw std::runtime_error(fmt::format( + "Unsupported quote format: {}", + static_cast(quote_info.format))); + } + + launch_node(); }; pal::PlatformAttestationReportData report_data = From b75a1204b850b22206701cf6228de0543847c103 Mon Sep 17 00:00:00 2001 From: Amaury Chamayou Date: Tue, 9 Dec 2025 17:20:01 +0000 Subject: [PATCH 16/18] short --- src/node/ledger_secret.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/node/ledger_secret.h b/src/node/ledger_secret.h index 57449b8be7e0..2a2e6c301309 100644 --- a/src/node/ledger_secret.h +++ b/src/node/ledger_secret.h @@ -13,7 +13,7 @@ namespace ccf { - static constexpr auto commit_secret_label_ = "Commit Secret Label"; + static constexpr auto commit_secret_label_ = "Commit S"; struct LedgerSecret { From d7fe643c0d2a9ba9f3a6b3d611863a2518d67251 Mon Sep 17 00:00:00 2001 From: Amaury Chamayou Date: Tue, 9 Dec 2025 17:42:40 +0000 Subject: [PATCH 17/18] tidy --- include/ccf/crypto/hmac.h | 4 ++-- src/crypto/hmac.cpp | 8 ++++---- src/node/ledger_secret.h | 16 ++++++++++------ 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/include/ccf/crypto/hmac.h b/include/ccf/crypto/hmac.h index 8efe0896c506..807232800f52 100644 --- a/include/ccf/crypto/hmac.h +++ b/include/ccf/crypto/hmac.h @@ -11,6 +11,6 @@ namespace ccf::crypto */ HashBytes hmac( MDType type, - const std::vector& key, - const std::vector& data); + const std::span& key, + const std::span& data); } diff --git a/src/crypto/hmac.cpp b/src/crypto/hmac.cpp index eea25ea04e4f..06369e80c27f 100644 --- a/src/crypto/hmac.cpp +++ b/src/crypto/hmac.cpp @@ -13,8 +13,8 @@ namespace ccf::crypto { HashBytes hmac( MDType type, - const std::vector& key, - const std::vector& data) + const std::span& key, + const std::span& data) { const auto* o_md_type = OpenSSL::get_md_type(type); HashBytes r(EVP_MD_size(o_md_type)); @@ -42,8 +42,8 @@ namespace ccf::crypto HashBytes hmac( MDType type, - const std::vector& key, - const std::vector& data) + const std::span& key, + const std::span& data) { return OpenSSL::hmac(type, key, data); } diff --git a/src/node/ledger_secret.h b/src/node/ledger_secret.h index 2a2e6c301309..caf73ccf6f3e 100644 --- a/src/node/ledger_secret.h +++ b/src/node/ledger_secret.h @@ -13,8 +13,15 @@ namespace ccf { - static constexpr auto commit_secret_label_ = "Commit S"; - + // Unique label for deriving commit secrets from ledger secrets. + // See logic in get_commit_secret() below for derivation implementation. + // It is important that this label is _not_ re-used for other purposes, + // nor changed during the lifetime of a ledger, to preserve the semantics of + // commit evidence (i.e. their reveal implies an entry is committed). + static constexpr uint8_t commit_secret_label_[] = { + 'C', 'o', 'm', 'm', 'i', 't', ' ', 'S'}; + static std::span commit_secret_label{ + commit_secret_label_, sizeof(commit_secret_label_)}; struct LedgerSecret { std::vector raw_key; @@ -28,10 +35,7 @@ namespace ccf if (!commit_secret.has_value()) { commit_secret = ccf::crypto::hmac( - ccf::crypto::MDType::SHA256, - raw_key, - {commit_secret_label_, - commit_secret_label_ + strlen(commit_secret_label_)}); + ccf::crypto::MDType::SHA256, raw_key, commit_secret_label); } return commit_secret.value(); } From 0f4c09d8695f6149220872f6036a3b79589f7caa Mon Sep 17 00:00:00 2001 From: Amaury Chamayou Date: Tue, 9 Dec 2025 19:05:23 +0000 Subject: [PATCH 18/18] fix doc --- doc/build_apps/crypto.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/build_apps/crypto.rst b/doc/build_apps/crypto.rst index 97d2b696f349..249138f92738 100644 --- a/doc/build_apps/crypto.rst +++ b/doc/build_apps/crypto.rst @@ -11,7 +11,7 @@ Hashing .. doxygenfunction:: ccf::crypto::sha256(const std::vector &data) :project: CCF -.. doxygenfunction:: ccf::crypto::hmac(MDType, const std::vector&, const std::vector&) +.. doxygenfunction:: ccf::crypto::hmac(MDType, const std::span&, const std::span&) :project: CCF .. doxygenClass:: ccf::crypto::HashProvider