diff --git a/CMakeLists.txt b/CMakeLists.txt index afc4921b36..f7629b33e3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -444,7 +444,10 @@ if(BUILD_TESTS) # Merkle Tree memory test add_executable(merkle_mem src/node/test/merkle_mem.cpp) - target_link_libraries(merkle_mem PRIVATE ${CMAKE_THREAD_LIBS_INIT} crypto) + target_compile_options(merkle_mem PRIVATE ${COMPILE_LIBCXX}) + target_link_libraries( + merkle_mem PRIVATE ${CMAKE_THREAD_LIBS_INIT} ${LINK_LIBCXX} crypto + ) # Raft driver and scenario test add_executable( diff --git a/doc/build_apps/api.rst b/doc/build_apps/api.rst index f1df17ceb8..87f32f1577 100644 --- a/doc/build_apps/api.rst +++ b/doc/build_apps/api.rst @@ -65,6 +65,15 @@ Supporting Types .. doxygenenum:: ccf::TxStatus :project: CCF +.. doxygentypedef:: ccf::View + :project: CCF + +.. doxygentypedef:: ccf::SeqNo + :project: CCF + +.. doxygentypedef:: ccf::TxID + :project: CCF + .. doxygenenum:: ccf::ApiResult :project: CCF diff --git a/doc/schemas/node_openapi.json b/doc/schemas/node_openapi.json index 7aa96df76a..a7de64bb51 100644 --- a/doc/schemas/node_openapi.json +++ b/doc/schemas/node_openapi.json @@ -106,7 +106,7 @@ "GetNetworkInfo__Out": { "properties": { "current_view": { - "$ref": "#/components/schemas/int64" + "$ref": "#/components/schemas/uint64" }, "primary_id": { "$ref": "#/components/schemas/EntityId" @@ -188,16 +188,16 @@ "GetState__Out": { "properties": { "last_recovered_seqno": { - "$ref": "#/components/schemas/int64" + "$ref": "#/components/schemas/uint64" }, "last_signed_seqno": { - "$ref": "#/components/schemas/int64" + "$ref": "#/components/schemas/uint64" }, "node_id": { "$ref": "#/components/schemas/EntityId" }, "recovery_target_seqno": { - "$ref": "#/components/schemas/int64" + "$ref": "#/components/schemas/uint64" }, "state": { "$ref": "#/components/schemas/ccf__State" @@ -376,11 +376,6 @@ ], "type": "string" }, - "int64": { - "maximum": 9223372036854775807, - "minimum": -9223372036854775808, - "type": "integer" - }, "json": {}, "string": { "type": "string" diff --git a/include/ccf/base_endpoint_registry.h b/include/ccf/base_endpoint_registry.h index db6f6eefc8..a004a94b4c 100644 --- a/include/ccf/base_endpoint_registry.h +++ b/include/ccf/base_endpoint_registry.h @@ -88,14 +88,11 @@ namespace ccf * @see ccf::TxStatus */ ApiResult get_status_for_txid_v1( - kv::Consensus::View view, - kv::Consensus::SeqNo seqno, - ccf::TxStatus& tx_status); + ccf::View view, ccf::SeqNo seqno, ccf::TxStatus& tx_status); /** Get the ID of latest transaction known to be committed. */ - ApiResult get_last_committed_txid_v1( - kv::Consensus::View& view, kv::Consensus::SeqNo& seqno); + ApiResult get_last_committed_txid_v1(ccf::View& view, ccf::SeqNo& seqno); /** Generate an OpenAPI document describing the currently installed * endpoints. @@ -120,7 +117,7 @@ namespace ccf /** Get the view associated with a given seqno, to construct a valid TxID */ - ApiResult get_view_for_seqno_v1(kv::SeqNo seqno, kv::Consensus::View& view); + ApiResult get_view_for_seqno_v1(ccf::SeqNo seqno, ccf::View& view); /** Get the user data associated with a given user id */ diff --git a/include/ccf/historical_queries_adapter.h b/include/ccf/historical_queries_adapter.h index 984802bd73..a4822e0869 100644 --- a/include/ccf/historical_queries_adapter.h +++ b/include/ccf/historical_queries_adapter.h @@ -9,7 +9,7 @@ namespace ccf::historical { using CheckAvailability = std::function; + ccf::View view, ccf::SeqNo seqno, std::string& error_reason)>; using HandleHistoricalQuery = std::function; @@ -52,8 +52,8 @@ namespace ccf::historical static inline bool is_tx_committed( kv::Consensus* consensus, - kv::Consensus::View view, - kv::Consensus::SeqNo seqno, + ccf::View view, + ccf::SeqNo seqno, std::string& error_reason) { if (consensus == nullptr) diff --git a/include/ccf/historical_queries_interface.h b/include/ccf/historical_queries_interface.h index aa525f33d7..a6530c53a2 100644 --- a/include/ccf/historical_queries_interface.h +++ b/include/ccf/historical_queries_interface.h @@ -3,6 +3,7 @@ #pragma once #include "ccf/receipt.h" +#include "ccf/tx_id.h" #include "consensus/ledger_enclave_types.h" #include "kv/store.h" #include "node/history.h" @@ -63,12 +64,12 @@ namespace ccf::historical /// Receipt for ledger entry at transaction_id TxReceiptPtr receipt = nullptr; /// View and Sequence Number for the State - kv::TxID transaction_id; + ccf::TxID transaction_id; State( const StorePtr& store_, const TxReceiptPtr& receipt_, - const kv::TxID& transaction_id_) : + const ccf::TxID& transaction_id_) : store(store_), receipt(receipt_), transaction_id(transaction_id_) @@ -119,18 +120,18 @@ namespace ccf::historical */ virtual StorePtr get_store_at( RequestHandle handle, - kv::SeqNo seqno, + ccf::SeqNo seqno, ExpiryDuration seconds_until_expiry) = 0; /** Same as @c get_store_at but uses default expiry value. * @see get_store_at */ - virtual StorePtr get_store_at(RequestHandle handle, kv::SeqNo seqno) = 0; + virtual StorePtr get_store_at(RequestHandle handle, ccf::SeqNo seqno) = 0; /** Retrieve a full state at a given seqno, including the Store, the TxID * assigned by consensus, and an offline-verifiable receipt for the Tx. */ - virtual StatePtr get_state_at(RequestHandle handle, kv::SeqNo seqno) = 0; + virtual StatePtr get_state_at(RequestHandle handle, ccf::SeqNo seqno) = 0; /** Retrieve a range of Stores containing the state written at the given * indices. @@ -152,15 +153,15 @@ namespace ccf::historical */ virtual std::vector get_store_range( RequestHandle handle, - kv::SeqNo start_seqno, - kv::SeqNo end_seqno, + ccf::SeqNo start_seqno, + ccf::SeqNo end_seqno, ExpiryDuration seconds_until_expiry) = 0; /** Same as @c get_store_range but uses default expiry value. * @see get_store_range */ virtual std::vector get_store_range( - RequestHandle handle, kv::SeqNo start_seqno, kv::SeqNo end_seqno) = 0; + RequestHandle handle, ccf::SeqNo start_seqno, ccf::SeqNo end_seqno) = 0; /** Drop state for the given handle. * diff --git a/include/ccf/tx_id.h b/include/ccf/tx_id.h index 6f30a40978..ff4d45e354 100644 --- a/include/ccf/tx_id.h +++ b/include/ccf/tx_id.h @@ -14,9 +14,31 @@ namespace ccf { + /** Transactions occur within a fixed View. Each View generally spans a range + * of transactions, though empty Views are also possible. The View is advanced + * by the consensus protocol during election of a new leader, and a single + * leader is assigned in each View. + */ using View = uint64_t; + + // No transactions occur in View 0. + constexpr View VIEW_UNKNOWN = 0; + + /** Each transaction is assigned a unique incrementing SeqNo, maintained + * across View transitions. This matches the order in which transactions are + * applied, where a higher SeqNo means that a transaction executed later. + * SeqNos are unique during normal operation, but around elections it is + * possible for distinct transactions in separate Views to have the same + * SeqNo. Only one of these transactions will ever commit, and the others are + * ephemeral. + */ using SeqNo = uint64_t; + // No transaction is assigned seqno 0. + constexpr SeqNo SEQNO_UNKNOWN = 0; + + // The combination of View and SeqNo produce a unique TxID for each + // transaction executed by CCF. struct TxID { View view; diff --git a/samples/apps/logging/logging.cpp b/samples/apps/logging/logging.cpp index f26aeec552..2c80680575 100644 --- a/samples/apps/logging/logging.cpp +++ b/samples/apps/logging/logging.cpp @@ -667,13 +667,11 @@ namespace loggingapp } }; - auto is_tx_committed = [this]( - kv::Consensus::View view, - kv::Consensus::SeqNo seqno, - std::string& error_reason) { - return ccf::historical::is_tx_committed( - consensus, view, seqno, error_reason); - }; + auto is_tx_committed = + [this](ccf::View view, ccf::SeqNo seqno, std::string& error_reason) { + return ccf::historical::is_tx_committed( + consensus, view, seqno, error_reason); + }; make_endpoint( "log/private/historical", HTTP_GET, diff --git a/samples/apps/nobuiltins/nobuiltins.cpp b/samples/apps/nobuiltins/nobuiltins.cpp index 5881140921..66ef2d615b 100644 --- a/samples/apps/nobuiltins/nobuiltins.cpp +++ b/samples/apps/nobuiltins/nobuiltins.cpp @@ -19,8 +19,8 @@ namespace nobuiltins std::vector quote; std::vector endorsements; - kv::Consensus::View committed_view; - kv::Consensus::SeqNo committed_seqno; + ccf::View committed_view; + ccf::SeqNo committed_seqno; }; DECLARE_JSON_TYPE(NodeSummary) @@ -119,8 +119,8 @@ namespace nobuiltins .install(); auto get_commit = [this](auto&, nlohmann::json&&) { - kv::Consensus::View view; - kv::Consensus::SeqNo seqno; + ccf::View view; + ccf::SeqNo seqno; const auto result = get_last_committed_txid_v1(view, seqno); if (result == ccf::ApiResult::OK) @@ -159,7 +159,7 @@ namespace nobuiltins nonstd::split_1(query_param, "="); if (query_key == "seqno") { - kv::SeqNo seqno; + ccf::SeqNo seqno; const auto qv_begin = query_value.data(); const auto qv_end = qv_begin + query_value.size(); const auto [p, ec] = std::from_chars(qv_begin, qv_end, seqno); @@ -173,7 +173,7 @@ namespace nobuiltins query_value)); } - kv::Consensus::View view; + ccf::View view; const auto result = get_view_for_seqno_v1(seqno, view); if (result == ccf::ApiResult::OK) { diff --git a/src/apps/js_generic/js_generic.cpp b/src/apps/js_generic/js_generic.cpp index 43819c9c1c..d4b038bdd6 100644 --- a/src/apps/js_generic/js_generic.cpp +++ b/src/apps/js_generic/js_generic.cpp @@ -284,13 +284,11 @@ namespace ccfapp info.has_value() && info.value().mode == ccf::endpoints::Mode::Historical) { - auto is_tx_committed = [this]( - kv::Consensus::View view, - kv::Consensus::SeqNo seqno, - std::string& error_reason) { - return ccf::historical::is_tx_committed( - consensus, view, seqno, error_reason); - }; + auto is_tx_committed = + [this](ccf::View view, ccf::SeqNo seqno, std::string& error_reason) { + return ccf::historical::is_tx_committed( + consensus, view, seqno, error_reason); + }; ccf::historical::adapter( [this, &method, &verb]( @@ -315,7 +313,7 @@ namespace ccfapp const ccf::RESTVerb& verb, ccf::endpoints::EndpointContext& args, kv::Tx& target_tx, - const std::optional& transaction_id, + const std::optional& transaction_id, ccf::historical::TxReceiptPtr receipt) { const auto local_method = method.substr(method.find_first_not_of('/')); diff --git a/src/consensus/aft/impl/execution.cpp b/src/consensus/aft/impl/execution.cpp index 2167a4cb70..218430d6c6 100644 --- a/src/consensus/aft/impl/execution.cpp +++ b/src/consensus/aft/impl/execution.cpp @@ -52,9 +52,9 @@ namespace aft kv::Version ExecutorImpl::execute_request( std::unique_ptr request, bool is_create_request, - kv::Consensus::SeqNo prescribed_commit_version, + ccf::SeqNo prescribed_commit_version, std::shared_ptr request_tracker, - kv::Consensus::SeqNo max_conflict_version) + ccf::SeqNo max_conflict_version) { std::shared_ptr& ctx = request->get_request_ctx().ctx; std::shared_ptr& frontend = @@ -92,8 +92,7 @@ namespace aft } std::unique_ptr ExecutorImpl::create_request_message( - const kv::TxHistory::RequestCallbackArgs& args, - kv::Consensus::SeqNo committed_seqno) + const kv::TxHistory::RequestCallbackArgs& args, ccf::SeqNo committed_seqno) { Request request = { args.rid, args.caller_cert, args.request, args.frame_format}; @@ -119,8 +118,8 @@ namespace aft kv::Version ExecutorImpl::execute_request( aft::Request& request, std::shared_ptr request_tracker, - kv::Consensus::SeqNo prescribed_commit_version, - kv::Consensus::SeqNo max_conflict_version) + ccf::SeqNo prescribed_commit_version, + ccf::SeqNo max_conflict_version) { auto ctx = create_request_ctx(request); diff --git a/src/consensus/aft/impl/execution.h b/src/consensus/aft/impl/execution.h index 27177280ae..e1114206a9 100644 --- a/src/consensus/aft/impl/execution.h +++ b/src/consensus/aft/impl/execution.h @@ -37,19 +37,19 @@ namespace aft virtual kv::Version execute_request( std::unique_ptr request, bool is_create_request, - kv::Consensus::SeqNo prescribed_commit_version = kv::NoVersion, + ccf::SeqNo prescribed_commit_version = kv::NoVersion, std::shared_ptr request_tracker = nullptr, - kv::Consensus::SeqNo max_conflict_version = kv::NoVersion) = 0; + ccf::SeqNo max_conflict_version = kv::NoVersion) = 0; virtual std::unique_ptr create_request_message( const kv::TxHistory::RequestCallbackArgs& args, - kv::Consensus::SeqNo committed_seqno) = 0; + ccf::SeqNo committed_seqno) = 0; virtual kv::Version execute_request( aft::Request& request, std::shared_ptr request_tracker, - kv::Consensus::SeqNo prescribed_commit_version, - kv::Consensus::SeqNo max_conflict_version) = 0; + ccf::SeqNo prescribed_commit_version, + ccf::SeqNo max_conflict_version) = 0; }; class ExecutorImpl : public Executor @@ -72,19 +72,19 @@ namespace aft kv::Version execute_request( std::unique_ptr request, bool is_create_request, - kv::Consensus::SeqNo prescribed_commit_version = kv::NoVersion, + ccf::SeqNo prescribed_commit_version = kv::NoVersion, std::shared_ptr request_tracker = nullptr, - kv::Consensus::SeqNo max_conflict_version = kv::NoVersion) override; + ccf::SeqNo max_conflict_version = kv::NoVersion) override; std::unique_ptr create_request_message( const kv::TxHistory::RequestCallbackArgs& args, - kv::Consensus::SeqNo committed_seqno) override; + ccf::SeqNo committed_seqno) override; kv::Version execute_request( aft::Request& request, std::shared_ptr request_tracker, - kv::Consensus::SeqNo prescribed_commit_version, - kv::Consensus::SeqNo max_conflict_version) override; + ccf::SeqNo prescribed_commit_version, + ccf::SeqNo max_conflict_version) override; private: std::shared_ptr state; diff --git a/src/consensus/aft/impl/state.h b/src/consensus/aft/impl/state.h index 813c4a46c3..5712443906 100644 --- a/src/consensus/aft/impl/state.h +++ b/src/consensus/aft/impl/state.h @@ -21,7 +21,7 @@ namespace aft std::vector views; public: - static constexpr kv::Consensus::View InvalidView = ccf::VIEW_UNKNOWN; + static constexpr ccf::View InvalidView = ccf::VIEW_UNKNOWN; void initialise(const std::vector& terms_) { @@ -33,7 +33,7 @@ namespace aft LOG_DEBUG_FMT("Initialised views: {}", fmt::join(views, ", ")); } - void update(kv::Version idx, kv::Consensus::View view) + void update(kv::Version idx, ccf::View view) { LOG_DEBUG_FMT("Updating view to: {} at version: {}", view, idx); if (!views.empty()) @@ -48,14 +48,14 @@ namespace aft } } - for (int64_t i = views.size(); i < view; ++i) + for (ccf::View i = views.size(); i < view; ++i) { views.push_back(idx); } LOG_DEBUG_FMT("Resulting views: {}", fmt::join(views, ", ")); } - kv::Consensus::View view_at(kv::Version idx) + ccf::View view_at(kv::Version idx) { auto it = upper_bound(views.begin(), views.end(), idx); @@ -107,7 +107,7 @@ namespace aft std::map> configuration; ccf::NodeId my_node_id; - kv::Consensus::View current_view; + ccf::View current_view; kv::Version last_idx; kv::Version commit_idx; diff --git a/src/consensus/aft/impl/view_change_tracker.h b/src/consensus/aft/impl/view_change_tracker.h index 23c4b86f34..a55f25c7e0 100644 --- a/src/consensus/aft/impl/view_change_tracker.h +++ b/src/consensus/aft/impl/view_change_tracker.h @@ -15,14 +15,14 @@ namespace aft { struct ViewChange { - ViewChange(kv::Consensus::View view_, kv::Consensus::SeqNo seqno_) : + ViewChange(ccf::View view_, ccf::SeqNo seqno_) : view(view_), seqno(seqno_), new_view_sent(false) {} - kv::Consensus::View view; - kv::Consensus::SeqNo seqno; + ccf::View view; + ccf::SeqNo seqno; bool new_view_sent; std::map received_view_changes; @@ -55,12 +55,12 @@ namespace aft (time_previous_view_change_increment != std::chrono::milliseconds(0)); } - kv::Consensus::View get_target_view() const + ccf::View get_target_view() const { return last_view_change_sent; } - void set_current_view_change(kv::Consensus::View view) + void set_current_view_change(ccf::View view) { view_changes.clear(); last_view_change_sent = view; @@ -75,8 +75,8 @@ namespace aft ResultAddView add_request_view_change( ccf::ViewChangeRequest& v, const ccf::NodeId& from, - kv::Consensus::View view, - kv::Consensus::SeqNo seqno, + ccf::View view, + ccf::SeqNo seqno, uint32_t node_count) { auto it = view_changes.find(view); @@ -101,16 +101,14 @@ namespace aft return ResultAddView::OK; } - kv::Consensus::SeqNo write_view_change_confirmation_append_entry( - kv::Consensus::View view) + ccf::SeqNo write_view_change_confirmation_append_entry(ccf::View view) { ccf::ViewChangeConfirmation nv = create_view_change_confirmation_msg(view); return store->write_view_change_confirmation(nv); } - std::vector get_serialized_view_change_confirmation( - kv::Consensus::View view) + std::vector get_serialized_view_change_confirmation(ccf::View view) { ccf::ViewChangeConfirmation nv = create_view_change_confirmation_msg(view); @@ -121,7 +119,7 @@ namespace aft } bool add_unknown_primary_evidence( - CBuffer data, kv::Consensus::View view, uint32_t node_count) + CBuffer data, ccf::View view, uint32_t node_count) { nlohmann::json j = nlohmann::json::parse(data.p); auto vc = j.get(); @@ -150,12 +148,12 @@ namespace aft return true; } - bool check_evidence(kv::Consensus::View view) const + bool check_evidence(ccf::View view) const { return last_valid_view == view; } - void clear(bool is_primary, kv::Consensus::View view) + void clear(bool is_primary, ccf::View view) { for (auto it = view_changes.begin(); it != view_changes.end();) { @@ -174,15 +172,15 @@ namespace aft private: std::shared_ptr store; - std::map view_changes; + std::map view_changes; std::chrono::milliseconds time_previous_view_change_increment = std::chrono::milliseconds(0); - kv::Consensus::View last_view_change_sent = 0; - kv::Consensus::View last_valid_view = aft::starting_view_change; + ccf::View last_view_change_sent = 0; + ccf::View last_valid_view = aft::starting_view_change; const std::chrono::milliseconds time_between_attempts; ccf::ViewChangeConfirmation create_view_change_confirmation_msg( - kv::Consensus::View view) + ccf::View view) { auto it = view_changes.find(view); if (it == view_changes.end()) diff --git a/src/consensus/aft/raft.h b/src/consensus/aft/raft.h index 83c732e891..7426ebe67a 100644 --- a/src/consensus/aft/raft.h +++ b/src/consensus/aft/raft.h @@ -281,7 +281,7 @@ namespace aft return replica_state == Follower; } - ccf::NodeId get_primary(kv::Consensus::View view) + ccf::NodeId get_primary(ccf::View view) { CCF_ASSERT_FMT( consensus_type == ConsensusType::BFT, @@ -742,8 +742,8 @@ namespace aft // We have not seen a request executed within an expected period of // time. We should invoke a view-change. // - kv::Consensus::View new_view = view_change_tracker->get_target_view(); - kv::Consensus::SeqNo seqno; + ccf::View new_view = view_change_tracker->get_target_view(); + ccf::SeqNo seqno; std::unique_ptr vc; auto progress_tracker = store->get_progress_tracker(); @@ -922,7 +922,7 @@ namespace aft entries_batch_size = std::max((batch_window_sum / batch_window_size), 1); } - void append_new_view(kv::Consensus::View view) + void append_new_view(ccf::View view) { state->current_view = view; become_leader(); @@ -936,7 +936,7 @@ namespace aft bool has_bft_timeout_occurred(std::chrono::milliseconds time) { auto oldest_entry = request_tracker->oldest_entry(); - kv::Consensus::SeqNo last_sig_seqno; + ccf::SeqNo last_sig_seqno; std::chrono::milliseconds last_sig_time; std::tie(last_sig_seqno, last_sig_time) = request_tracker->get_seqno_time_last_request(); @@ -1871,7 +1871,7 @@ namespace aft try_send_sig_ack({r.term, r.last_log_idx}, result); } - void try_send_sig_ack(kv::TxID tx_id, kv::TxHistory::Result r) + void try_send_sig_ack(ccf::TxID tx_id, kv::TxHistory::Result r) { switch (r) { @@ -1883,7 +1883,7 @@ namespace aft case kv::TxHistory::Result::SEND_SIG_RECEIPT_ACK: { SignaturesReceivedAck r = { - {bft_signature_received_ack}, tx_id.term, tx_id.version}; + {bft_signature_received_ack}, tx_id.view, tx_id.seqno}; for (auto it = nodes.begin(); it != nodes.end(); ++it) { auto to = it->first; @@ -1936,7 +1936,7 @@ namespace aft try_send_reply_and_nonce({r.term, r.idx}, result); } - void try_send_reply_and_nonce(kv::TxID tx_id, kv::TxHistory::Result r) + void try_send_reply_and_nonce(ccf::TxID tx_id, kv::TxHistory::Result r) { switch (r) { @@ -1953,7 +1953,7 @@ namespace aft progress_tracker != nullptr, "progress_tracker is not set"); nonce = progress_tracker->get_node_nonce(tx_id); NonceRevealMsg r = { - {bft_nonce_reveal}, tx_id.term, tx_id.version, nonce}; + {bft_nonce_reveal}, tx_id.view, tx_id.seqno, nonce}; for (auto it = nodes.begin(); it != nodes.end(); ++it) { diff --git a/src/consensus/aft/raft_consensus.h b/src/consensus/aft/raft_consensus.h index 79c8e4c061..724bfcb6f2 100644 --- a/src/consensus/aft/raft_consensus.h +++ b/src/consensus/aft/raft_consensus.h @@ -44,28 +44,28 @@ namespace aft } void force_become_primary( - SeqNo seqno, - View view, + ccf::SeqNo seqno, + ccf::View view, const std::vector& terms, - SeqNo commit_seqno) override + ccf::SeqNo commit_seqno) override { aft->force_become_leader(seqno, view, terms, commit_seqno); } void init_as_backup( - SeqNo seqno, - View view, + ccf::SeqNo seqno, + ccf::View view, const std::vector& view_history) override { aft->init_as_follower(seqno, view, view_history); } - bool replicate(const kv::BatchVector& entries, View view) override + bool replicate(const kv::BatchVector& entries, ccf::View view) override { return aft->replicate(entries, view); } - std::pair get_committed_txid() override + std::pair get_committed_txid() override { return aft->get_commit_term_and_idx(); } @@ -75,28 +75,28 @@ namespace aft return aft->get_signable_commit_term_and_idx(); } - View get_view(SeqNo seqno) override + ccf::View get_view(ccf::SeqNo seqno) override { return aft->get_term(seqno); } - View get_view() override + ccf::View get_view() override { return aft->get_term(); } - std::vector get_view_history(SeqNo seqno) override + std::vector get_view_history(ccf::SeqNo seqno) override { return aft->get_term_history(seqno); } void initialise_view_history( - const std::vector& view_history) override + const std::vector& view_history) override { aft->initialise_term_history(view_history); } - SeqNo get_committed_seqno() override + ccf::SeqNo get_committed_seqno() override { return aft->get_commit_idx(); } @@ -122,7 +122,7 @@ namespace aft } void add_configuration( - SeqNo seqno, const Configuration::Nodes& conf) override + ccf::SeqNo seqno, const Configuration::Nodes& conf) override { aft->add_configuration(seqno, conf); } diff --git a/src/consensus/aft/raft_types.h b/src/consensus/aft/raft_types.h index 81341818b2..faf20a189e 100644 --- a/src/consensus/aft/raft_types.h +++ b/src/consensus/aft/raft_types.h @@ -19,8 +19,8 @@ namespace aft { - using Index = int64_t; - using Term = int64_t; + using Index = uint64_t; + using Term = uint64_t; using Node2NodeMsg = uint64_t; using Nonce = crypto::Sha256Hash; @@ -185,13 +185,13 @@ namespace aft struct RequestViewChangeMsg : RaftHeader { - kv::Consensus::View view = 0; - kv::Consensus::SeqNo seqno = 0; + ccf::View view = 0; + ccf::SeqNo seqno = 0; }; struct ViewChangeEvidenceMsg : RaftHeader { - kv::Consensus::View view = 0; + ccf::View view = 0; }; struct RequestVote : RaftHeader diff --git a/src/consensus/aft/revealed_nonces.h b/src/consensus/aft/revealed_nonces.h index 82cb7d9780..9fec06efc2 100644 --- a/src/consensus/aft/revealed_nonces.h +++ b/src/consensus/aft/revealed_nonces.h @@ -29,12 +29,12 @@ namespace aft struct RevealedNonces { - kv::TxID tx_id; + ccf::TxID tx_id; std::vector nonces; RevealedNonces() = default; - RevealedNonces(kv::TxID tx_id_) : tx_id(tx_id_) {} + RevealedNonces(ccf::TxID tx_id_) : tx_id(tx_id_) {} }; DECLARE_JSON_TYPE(RevealedNonces); DECLARE_JSON_REQUIRED_FIELDS(RevealedNonces, tx_id, nonces) diff --git a/src/consensus/consensus_types.h b/src/consensus/consensus_types.h index 4b313acebf..f21233f815 100644 --- a/src/consensus/consensus_types.h +++ b/src/consensus/consensus_types.h @@ -35,8 +35,8 @@ namespace consensus struct AppendEntriesIndex { - ccf::Index idx; - ccf::Index prev_idx; + ccf::SeqNo idx; + ccf::SeqNo prev_idx; }; #pragma pack(pop) } \ No newline at end of file diff --git a/src/ds/champ_map_serializers.h b/src/ds/champ_map_serializers.h index a1152aaf19..8070231de9 100644 --- a/src/ds/champ_map_serializers.h +++ b/src/ds/champ_map_serializers.h @@ -7,20 +7,21 @@ namespace champ { - using Version = int64_t; + using Version = uint64_t; + using DeletableVersion = int64_t; template struct VersionV { - Version version; + DeletableVersion version; Version read_version; V value; VersionV() : - version(std::numeric_limits::min()), - read_version(std::numeric_limits::min()) + version(std::numeric_limits::min()), + read_version(std::numeric_limits::min()) {} - VersionV(Version ver, Version read_ver, V val) : + VersionV(DeletableVersion ver, Version read_ver, V val) : version(ver), read_version(read_ver), value(val) diff --git a/src/enclave/rpc_handler.h b/src/enclave/rpc_handler.h index 17e5bbacf7..e3cc1fc3b4 100644 --- a/src/enclave/rpc_handler.h +++ b/src/enclave/rpc_handler.h @@ -43,12 +43,12 @@ namespace enclave virtual ProcessBftResp process_bft( std::shared_ptr ctx, - kv::Consensus::SeqNo prescribed_commit_version, - kv::Consensus::SeqNo max_conflict_version) = 0; + ccf::SeqNo prescribed_commit_version, + ccf::SeqNo max_conflict_version) = 0; virtual ProcessBftResp process_bft( std::shared_ptr ctx, kv::Tx& tx, - kv::Consensus::SeqNo prescribed_commit_version = kv::NoVersion, - kv::Consensus::SeqNo max_conflict_version = kv::NoVersion) = 0; + ccf::SeqNo prescribed_commit_version = kv::NoVersion, + ccf::SeqNo max_conflict_version = kv::NoVersion) = 0; }; } diff --git a/src/endpoints/base_endpoint_registry.cpp b/src/endpoints/base_endpoint_registry.cpp index a0b415bd68..03e1e34577 100644 --- a/src/endpoints/base_endpoint_registry.cpp +++ b/src/endpoints/base_endpoint_registry.cpp @@ -15,9 +15,7 @@ namespace ccf {} ApiResult BaseEndpointRegistry::get_status_for_txid_v1( - kv::Consensus::View view, - kv::Consensus::SeqNo seqno, - ccf::TxStatus& tx_status) + ccf::View view, ccf::SeqNo seqno, ccf::TxStatus& tx_status) { try { @@ -45,7 +43,7 @@ namespace ccf } ApiResult BaseEndpointRegistry::get_last_committed_txid_v1( - kv::Consensus::View& view, kv::Consensus::SeqNo& seqno) + ccf::View& view, ccf::SeqNo& seqno) { if (consensus != nullptr) { @@ -115,7 +113,7 @@ namespace ccf } ApiResult BaseEndpointRegistry::get_view_for_seqno_v1( - kv::SeqNo seqno, kv::Consensus::View& view) + ccf::SeqNo seqno, ccf::View& view) { try { diff --git a/src/endpoints/common_endpoint_registry.cpp b/src/endpoints/common_endpoint_registry.cpp index 9c45ed7e28..e981b2a99e 100644 --- a/src/endpoints/common_endpoint_registry.cpp +++ b/src/endpoints/common_endpoint_registry.cpp @@ -65,8 +65,8 @@ namespace ccf BaseEndpointRegistry::init_handlers(); auto get_commit = [this](auto&, nlohmann::json&&) { - kv::Consensus::View view; - kv::Consensus::SeqNo seqno; + ccf::View view; + ccf::SeqNo seqno; const auto result = get_last_committed_txid_v1(view, seqno); if (result == ccf::ApiResult::OK) @@ -223,35 +223,33 @@ namespace ccf ccf::endpoints::ExecuteOutsideConsensus::Locally) .install(); - auto is_tx_committed = [this]( - kv::Consensus::View view, - kv::Consensus::SeqNo seqno, - std::string& error_reason) { - if (consensus == nullptr) - { - error_reason = "Node is not fully configured"; - return false; - } + auto is_tx_committed = + [this](ccf::View view, ccf::SeqNo seqno, std::string& error_reason) { + if (consensus == nullptr) + { + error_reason = "Node is not fully configured"; + return false; + } - const auto tx_view = consensus->get_view(seqno); - const auto committed_seqno = consensus->get_committed_seqno(); - const auto committed_view = consensus->get_view(committed_seqno); + const auto tx_view = consensus->get_view(seqno); + const auto committed_seqno = consensus->get_committed_seqno(); + const auto committed_view = consensus->get_view(committed_seqno); - const auto tx_status = ccf::evaluate_tx_status( - view, seqno, tx_view, committed_view, committed_seqno); - if (tx_status != ccf::TxStatus::Committed) - { - error_reason = fmt::format( - "Only committed transactions can be queried. Transaction {}.{} is " - "{}", - view, - seqno, - ccf::tx_status_to_str(tx_status)); - return false; - } + const auto tx_status = ccf::evaluate_tx_status( + view, seqno, tx_view, committed_view, committed_seqno); + if (tx_status != ccf::TxStatus::Committed) + { + error_reason = fmt::format( + "Only committed transactions can be queried. Transaction {}.{} is " + "{}", + view, + seqno, + ccf::tx_status_to_str(tx_status)); + return false; + } - return true; - }; + return true; + }; auto get_receipt = [](auto& args, ccf::historical::StatePtr historical_state) { diff --git a/src/http/ws_builder.h b/src/http/ws_builder.h index 551f991939..8b22298c61 100644 --- a/src/http/ws_builder.h +++ b/src/http/ws_builder.h @@ -65,7 +65,7 @@ namespace ws static std::vector make_out_frame( size_t code, kv::Version seqno, - kv::Consensus::View view, + ccf::View view, const std::vector& body) { size_t out_frame_size = ws::OUT_CCF_HEADER_SIZE + body.size(); diff --git a/src/http/ws_rpc_context.h b/src/http/ws_rpc_context.h index 808a20c5a9..cbc3e9cc50 100644 --- a/src/http/ws_rpc_context.h +++ b/src/http/ws_rpc_context.h @@ -16,7 +16,7 @@ namespace ws size_t code, const std::vector& body, kv::Version seqno = kv::NoVersion, - kv::Consensus::View view = ccf::VIEW_UNKNOWN) + ccf::View view = ccf::VIEW_UNKNOWN) { return make_out_frame(code, seqno, view, body); }; diff --git a/src/js/wrap.cpp b/src/js/wrap.cpp index 435a21fa0c..9f00196a47 100644 --- a/src/js/wrap.cpp +++ b/src/js/wrap.cpp @@ -483,7 +483,7 @@ namespace js JSValue create_ccf_obj( TxContext* txctx, - const std::optional& transaction_id, + const std::optional& transaction_id, ccf::historical::TxReceiptPtr receipt, JSContext* ctx) { @@ -530,13 +530,17 @@ namespace js // Historical queries if (receipt != nullptr) { + CCF_ASSERT( + transaction_id.has_value(), + "Expected receipt and transaction_id to both be passed"); + auto state = JS_NewObject(ctx); - ccf::TxID tx_id; - tx_id.seqno = static_cast(transaction_id.value().version); - tx_id.view = static_cast(transaction_id.value().term); JS_SetPropertyStr( - ctx, state, "transactionId", JS_NewString(ctx, tx_id.to_str().c_str())); + ctx, + state, + "transactionId", + JS_NewString(ctx, transaction_id->to_str().c_str())); ccf::Receipt receipt_out; receipt->describe(receipt_out); @@ -580,7 +584,7 @@ namespace js void populate_global_ccf( TxContext* txctx, - const std::optional& transaction_id, + const std::optional& transaction_id, ccf::historical::TxReceiptPtr receipt, JSContext* ctx) { diff --git a/src/js/wrap.h b/src/js/wrap.h index d030c443e7..b573f64836 100644 --- a/src/js/wrap.h +++ b/src/js/wrap.h @@ -43,7 +43,7 @@ namespace js void populate_global_console(JSContext* ctx); void populate_global_ccf( TxContext* txctx, - const std::optional& transaction_id, + const std::optional& transaction_id, ccf::historical::TxReceiptPtr receipt, JSContext* ctx); diff --git a/src/kv/change_set.h b/src/kv/change_set.h index 90be950fba..7e0169985f 100644 --- a/src/kv/change_set.h +++ b/src/kv/change_set.h @@ -21,7 +21,7 @@ namespace kv // version of last transaction which read the key and committed successfully using LastReadVersion = Version; template - using Read = std::map>; + using Read = std::map>; // nullopt values represent deletions template diff --git a/src/kv/deserialise.h b/src/kv/deserialise.h index ba6f0cd90e..d40f7f8ea5 100644 --- a/src/kv/deserialise.h +++ b/src/kv/deserialise.h @@ -328,7 +328,7 @@ namespace kv return ApplyResult::FAIL; } - kv::TxID tx_id; + ccf::TxID tx_id; auto success = ApplyResult::PASS; auto r = progress_tracker->receive_backup_signatures( @@ -350,8 +350,8 @@ namespace kv return ApplyResult::FAIL; } - term = tx_id.term; - version = tx_id.version; + term = tx_id.view; + version = tx_id.seqno; history->append(data); return success; diff --git a/src/kv/kv_types.h b/src/kv/kv_types.h index b297f1452d..63a897d647 100644 --- a/src/kv/kv_types.h +++ b/src/kv/kv_types.h @@ -3,6 +3,7 @@ #pragma once #include "ccf/entity_id.h" +#include "ccf/tx_id.h" #include "crypto/hash.h" #include "crypto/pem.h" #include "ds/nonstd.h" @@ -31,12 +32,15 @@ namespace aft namespace kv { - // Version indexes modifications to the local kv store. Negative values - // indicate deletion - using Version = int64_t; - static const Version NoVersion = std::numeric_limits::min(); + // Version indexes modifications to the local kv store. + using Version = uint64_t; + static constexpr Version NoVersion = 0u; - static bool is_deleted(Version version) + // DeletableVersion describes the version of an individual key within each + // table, which may be negative to indicate a deletion + using DeletableVersion = int64_t; + + static bool is_deleted(DeletableVersion version) { return version < 0; } @@ -45,21 +49,29 @@ namespace kv // writer(s) changes. Term and Version combined give a unique identifier for // all accepted kv modifications. Terms are handled by Consensus via the // TermHistory - using Term = int64_t; + using Term = uint64_t; using NodeId = ccf::NodeId; struct TxID { Term term = 0; Version version = 0; + + TxID() = default; + TxID(Term t, Version v) : term(t), version(v) {} + + // Would like to remove these duplicate types, but for now we just do free + // conversion + TxID(const ccf::TxID& other) : term(other.view), version(other.seqno) {} + + operator ccf::TxID() const + { + return {term, version}; + } }; DECLARE_JSON_TYPE(TxID); DECLARE_JSON_REQUIRED_FIELDS(TxID, term, version) - // SeqNo indexes transactions processed by the consensus protocol providing - // ordering - using SeqNo = int64_t; - struct Configuration { struct NodeInfo @@ -77,7 +89,7 @@ namespace kv using Nodes = std::unordered_map; - SeqNo idx; + ccf::SeqNo idx; Nodes nodes; }; @@ -85,7 +97,7 @@ namespace kv { public: virtual void add_configuration( - SeqNo seqno, const Configuration::Nodes& conf) = 0; + ccf::SeqNo seqno, const Configuration::Nodes& conf) = 0; virtual Configuration::Nodes get_latest_configuration() = 0; virtual Configuration::Nodes get_latest_configuration_unsafe() const = 0; }; @@ -285,11 +297,6 @@ namespace kv NodeId local_id; public: - using SeqNo = SeqNo; - // View describes an epoch of SeqNos. View is incremented when Consensus's - // primary changes - using View = int64_t; - Consensus(const NodeId& id) : state(Backup), local_id(id) {} virtual ~Consensus() {} @@ -314,32 +321,33 @@ namespace kv } virtual void force_become_primary( - SeqNo, View, const std::vector&, SeqNo) + ccf::SeqNo, ccf::View, const std::vector&, ccf::SeqNo) { state = Primary; } - virtual void init_as_backup(SeqNo, View, const std::vector&) + virtual void init_as_backup( + ccf::SeqNo, ccf::View, const std::vector&) { state = Backup; } - virtual bool replicate(const BatchVector& entries, View view) = 0; - virtual std::pair get_committed_txid() = 0; + virtual bool replicate(const BatchVector& entries, ccf::View view) = 0; + virtual std::pair get_committed_txid() = 0; struct SignableTxIndices { Term term; - SeqNo version, previous_version; + ccf::SeqNo version, previous_version; }; virtual std::optional get_signable_txid() = 0; - virtual View get_view(SeqNo seqno) = 0; - virtual View get_view() = 0; - virtual std::vector get_view_history(SeqNo) = 0; - virtual void initialise_view_history(const std::vector&) = 0; - virtual SeqNo get_committed_seqno() = 0; + virtual ccf::View get_view(ccf::SeqNo seqno) = 0; + virtual ccf::View get_view() = 0; + virtual std::vector get_view_history(ccf::SeqNo) = 0; + virtual void initialise_view_history(const std::vector&) = 0; + virtual ccf::SeqNo get_committed_seqno() = 0; virtual std::optional primary() = 0; virtual bool view_change_in_progress() = 0; virtual std::set active_nodes() = 0; diff --git a/src/kv/store.h b/src/kv/store.h index 27fdc7d50c..b1803a6caa 100644 --- a/src/kv/store.h +++ b/src/kv/store.h @@ -125,12 +125,16 @@ namespace kv Version next_version_internal() { - // Get the next global version. If the version becomes negative, wrap to - // 0. + // Get the next global version ++version; - if (version < 0) + // If the version becomes too large to represent in a DeletableVersion, + // wrap to 0 + if (version > std::numeric_limits::max()) + { + LOG_FAIL_FMT("KV version too large - wrapping to 0"); version = 0; + } return version; } @@ -936,7 +940,7 @@ namespace kv Version previous_last_replicated = 0; Version next_last_replicated = 0; Version previous_rollback_count = 0; - kv::Consensus::View replication_view = 0; + ccf::View replication_view = 0; { std::lock_guard vguard(version_lock); diff --git a/src/kv/test/kv_test.cpp b/src/kv/test/kv_test.cpp index e59afd8a15..1e67c91734 100644 --- a/src/kv/test/kv_test.cpp +++ b/src/kv/test/kv_test.cpp @@ -1471,169 +1471,202 @@ TEST_CASE("Conflict resolution") REQUIRE_THROWS(tx2.commit()); } -TEST_CASE("Primary can create correct execution order") +std::string rand_string(size_t i) { - struct TxInfo - { - uint32_t id; - kv::Version replicated_max_conflict_version; - }; - std::vector txs; - - // Execute on primary - { - kv::Store kv_store_primary; - MapTypes::StringString map("public:map"); - - for (uint32_t i = 0; i < 5; ++i) - { - TxInfo info = {i, kv::NoVersion}; - auto tx = kv_store_primary.create_tx(); - auto handle = tx.rw(map); - handle->get(std::to_string(info.id)); - handle->put(std::to_string(info.id), std::to_string(info.id)); - REQUIRE(tx.commit(true) == kv::CommitResult::SUCCESS); - info.replicated_max_conflict_version = tx.get_max_conflict_version(); - txs.push_back(info); - } - } - - // Execute on backup - { - kv::Store kv_store_backup; - MapTypes::NumNum map("public:map"); - - // create the map on the backup - { - TxInfo& info = txs[0]; - auto tx = kv_store_backup.create_tx(); - auto handle = tx.rw(map); - handle->get(info.id); - handle->put(info.id, info.id); - auto version_resolver = [&](bool) { - kv_store_backup.next_version(); - return std::make_tuple(info.id, kv::NoVersion); - }; - REQUIRE( - tx.commit( - true, version_resolver, info.replicated_max_conflict_version) == - kv::CommitResult::SUCCESS); - } - - // Verify that transactions can be execute in a random (reverse order) as - // there is no dependency - for (uint32_t i = 4; i > 0; --i) - { - TxInfo& info = txs[i]; - auto tx = kv_store_backup.create_tx(); - auto handle = tx.rw(map); - handle->get(info.id); - handle->put(info.id, info.id); - auto version_resolver = [&](bool) { - kv_store_backup.next_version(); - return std::make_tuple(info.id, 0); - }; - REQUIRE( - tx.commit( - true, version_resolver, info.replicated_max_conflict_version) == - kv::CommitResult::SUCCESS); - } - - // Verify that the values can be read back - for (uint32_t i = 4; i > 1; --i) - { - TxInfo& info = txs[2]; - auto tx = kv_store_backup.create_tx(); - auto handle = tx.rw(map); - auto ret_value = handle->get(info.id); - REQUIRE(ret_value.has_value()); - size_t value = ret_value.value(); - REQUIRE(value == info.id); - } - } + return fmt::format("{}: {}", i, rand()); } -TEST_CASE("Backup can detect byzantine execution order") +TEST_CASE("Max conflict version tracks execution order") { struct TxInfo { - uint32_t id; + std::string id; + std::string value; + kv::Version primary_committed_version; kv::Version replicated_max_conflict_version; }; - std::vector txs; + MapTypes::StringString map("public:map"); + size_t tx_count = 5; + const auto fixed_key = rand_string(0); - // Execute on primary + for (bool dependencies_between_transactions : {false, true}) { - kv::Store kv_store_primary; - MapTypes::StringString map("public:map"); + std::vector txs; - for (uint32_t i = 0; i < 5; ++i) + // Execute on primary { - TxInfo info = {i, 0}; - auto tx = kv_store_primary.create_tx(); - auto handle = tx.rw(map); - handle->get("key"); - handle->put("key", std::to_string(info.id)); - REQUIRE(tx.commit(true) == kv::CommitResult::SUCCESS); - txs.push_back(info); - } - } - - // Execute on backup - { - kv::Store kv_store_backup; - MapTypes::StringString map("public:map"); - - // Run the transaction that creates the map - { - TxInfo& info = txs[0]; - auto tx = kv_store_backup.create_tx(); - auto handle = tx.rw(map); - handle->get("key"); - handle->put("key", std::to_string(info.id)); - auto version_resolver = [&](bool) { - kv_store_backup.next_version(); - return std::make_tuple(info.id, kv::NoVersion); - }; - REQUIRE( - tx.commit( - true, version_resolver, info.replicated_max_conflict_version) == - kv::CommitResult::SUCCESS); + kv::Store kv_store_primary; + for (uint32_t i = 0; i < tx_count; ++i) + { + TxInfo info; + auto tx = kv_store_primary.create_tx(); + auto handle = tx.rw(map); + if (!dependencies_between_transactions) + { + // Each transaction reads and writes independent keys - there is no + // dependency between transactions + info.id = rand_string(i); + info.value = rand_string(i); + REQUIRE(!handle->has(info.id)); + } + else + { + // Each transaction reads the same key, and tries to write (at the + // same key) a value derived from the previous value + info.id = fixed_key; + const auto prev_value = handle->get(info.id); + info.value = + fmt::format("{} | {}", info.id, prev_value.value_or("NONE")); + } + handle->put(info.id, info.value); + REQUIRE(tx.commit(true) == kv::CommitResult::SUCCESS); + info.primary_committed_version = tx.commit_version(); + info.replicated_max_conflict_version = tx.get_max_conflict_version(); + txs.push_back(info); + } } - // Run the transaction the final transaction so any transaction with a - // version before this one will result a linearlizability exception - { - TxInfo& info = txs[4]; - auto tx = kv_store_backup.create_tx(); - auto handle = tx.rw(map); - handle->get("key"); - handle->put("key", std::to_string(info.id)); - auto version_resolver = [&](bool) { - kv_store_backup.next_version(); - return std::make_tuple(info.id, kv::NoVersion); - }; - REQUIRE( - tx.commit( - true, version_resolver, info.replicated_max_conflict_version) == - kv::CommitResult::SUCCESS); - } + REQUIRE(tx_count == txs.size()); - // Validate the incorrectly created tx order cannot commit - for (uint32_t i = 1; i < 4; ++i) + // Execute on backup { - TxInfo& info = txs[i]; - auto tx = kv_store_backup.create_tx(); - auto handle = tx.rw(map); - handle->put("key", std::to_string(info.id)); - auto version_resolver = [&](bool) { - kv_store_backup.next_version(); - return std::make_tuple(info.id, kv::NoVersion); - }; - REQUIRE( - tx.commit( - true, version_resolver, info.replicated_max_conflict_version) == - kv::CommitResult::FAIL_CONFLICT); + kv::Store kv_store_backup; + kv::Version map_creation_version; + + // create the map on the backup + { + TxInfo& info = txs[0]; + auto tx = kv_store_backup.create_tx(); + auto handle = tx.rw(map); + REQUIRE(!handle->has(info.id)); + handle->put(info.id, info.value); + auto version_resolver = [&](bool) { + kv_store_backup.next_version(); + return std::make_tuple(info.primary_committed_version, kv::NoVersion); + }; + REQUIRE( + tx.commit( + true, version_resolver, info.replicated_max_conflict_version) == + kv::CommitResult::SUCCESS); + map_creation_version = tx.commit_version(); + } + + SUBCASE("Primary can construct correct execution order") + { + for (uint32_t i = 1; i < txs.size(); ++i) + { + TxInfo& info = txs[i]; + auto tx = kv_store_backup.create_tx(); + auto handle = tx.rw(map); + REQUIRE(!handle->has(info.id)); + handle->put(info.id, info.value); + auto version_resolver = [&](bool) { + kv_store_backup.next_version(); + return std::make_tuple( + info.primary_committed_version, map_creation_version); + }; + REQUIRE( + tx.commit( + true, version_resolver, info.replicated_max_conflict_version) == + kv::CommitResult::SUCCESS); + } + + // Verify that the values can be read back + for (const TxInfo& info : txs) + { + auto tx = kv_store_backup.create_tx(); + auto handle = tx.rw(map); + auto ret_value = handle->get(info.id); + REQUIRE(ret_value.has_value()); + const auto value = ret_value.value(); + REQUIRE(value == info.value); + } + } + + SUBCASE("Byzantine execution order is refused by backup") + { + { + INFO( + "Reverse remaining transactions to produce different execution " + "order"); + std::reverse(txs.begin() + 1, txs.end()); + } + + if (!dependencies_between_transactions) + { + // If there are no dependencies, the re-ordering doesn't matter - + // these transactions can still be executed successfully out-of-order + for (auto it = txs.begin() + 1; it != txs.end(); ++it) + { + TxInfo& info = *it; + auto tx = kv_store_backup.create_tx(); + auto handle = tx.rw(map); + REQUIRE(!handle->has(info.id)); + handle->put(info.id, info.value); + auto version_resolver = [&](bool) { + kv_store_backup.next_version(); + return std::make_tuple( + info.primary_committed_version, map_creation_version); + }; + REQUIRE( + tx.commit( + true, version_resolver, info.replicated_max_conflict_version) == + kv::CommitResult::SUCCESS); + } + + // Verify that the values can be read back + for (const TxInfo& info : txs) + { + auto tx = kv_store_backup.create_tx(); + auto handle = tx.rw(map); + auto ret_value = handle->get(info.id); + REQUIRE(ret_value.has_value()); + const auto value = ret_value.value(); + REQUIRE(value == info.value); + } + } + else + { + { + // Run the final transaction first, so any of the other transactions + // (whith a version before this one) will produce a + // linearilizability violation + TxInfo& info = txs[1]; + auto tx = kv_store_backup.create_tx(); + auto handle = tx.rw(map); + handle->get(info.id); + handle->put(info.id, info.value); + auto version_resolver = [&](bool) { + kv_store_backup.next_version(); + return std::make_tuple( + info.primary_committed_version, map_creation_version); + }; + REQUIRE( + tx.commit( + true, version_resolver, info.replicated_max_conflict_version) == + kv::CommitResult::SUCCESS); + } + + // Validate the incorrectly created tx order cannot commit + for (auto it = txs.begin() + 2; it != txs.end(); ++it) + { + TxInfo& info = *it; + auto tx = kv_store_backup.create_tx(); + auto handle = tx.rw(map); + handle->get(info.id); + handle->put(info.id, info.value); + auto version_resolver = [&](bool) { + kv_store_backup.next_version(); + return std::make_tuple( + info.primary_committed_version, map_creation_version); + }; + REQUIRE( + tx.commit( + true, version_resolver, info.replicated_max_conflict_version) == + kv::CommitResult::FAIL_CONFLICT); + } + } + } } } } diff --git a/src/kv/test/stub_consensus.h b/src/kv/test/stub_consensus.h index 5497aabd99..9a008e50de 100644 --- a/src/kv/test/stub_consensus.h +++ b/src/kv/test/stub_consensus.h @@ -31,7 +31,7 @@ namespace kv::test consensus_type(consensus_type_) {} - bool replicate(const BatchVector& entries, View view) override + bool replicate(const BatchVector& entries, ccf::View view) override { for (const auto& entry : entries) { @@ -79,7 +79,7 @@ namespace kv::test replica.clear(); } - std::pair get_committed_txid() override + std::pair get_committed_txid() override { return {2, 0}; } @@ -94,7 +94,7 @@ namespace kv::test return r; } - SeqNo get_committed_seqno() override + ccf::SeqNo get_committed_seqno() override { return 0; } @@ -119,23 +119,23 @@ namespace kv::test return PrimaryNodeId; } - View get_view(SeqNo seqno) override + ccf::View get_view(ccf::SeqNo seqno) override { return 2; } - View get_view() override + ccf::View get_view() override { return 2; } - std::vector get_view_history(SeqNo seqno) override + std::vector get_view_history(ccf::SeqNo seqno) override { return view_history.get_history_until(seqno); } void initialise_view_history( - const std::vector& view_history_) override + const std::vector& view_history_) override { view_history.initialise(view_history_); } @@ -143,7 +143,7 @@ namespace kv::test void recv_message(const NodeId& from, OArray&& oa) override {} void add_configuration( - SeqNo seqno, const Configuration::Nodes& conf) override + ccf::SeqNo seqno, const Configuration::Nodes& conf) override {} Configuration::Nodes get_latest_configuration_unsafe() const override @@ -184,7 +184,7 @@ namespace kv::test return false; } - bool replicate(const BatchVector& entries, View view) override + bool replicate(const BatchVector& entries, ccf::View view) override { return false; } diff --git a/src/kv/tx.h b/src/kv/tx.h index 75a4e1597b..5f2edbad06 100644 --- a/src/kv/tx.h +++ b/src/kv/tx.h @@ -66,7 +66,15 @@ namespace kv bool committed = false; bool success = false; - Version read_version = NoVersion; + + // In most places we use NoVersion to indicate an invalid version. In this + // case, NoVersion is a valid value - it is the version that the first + // transaction in the service will read from, before anything has been + // applied to the KV. So we need an additional special value to distinguish + // "haven't yet fetched a read_version" from "have fetched a read_version, + // and it is NoVersion", and we get that by wrapping this in a + // std::optional with nullopt representing "not yet fetched". + std::optional read_version = std::nullopt; Version version = NoVersion; Version max_conflict_version = NoVersion; Term term = 0; @@ -117,7 +125,7 @@ namespace kv throw CompactedVersionConflict(fmt::format( "Unable to retrieve state over map {} at {}", map_name, - read_version)); + read_version.value())); } auto typed_handle = get_or_insert_handle(*change_set, map_name); @@ -136,7 +144,7 @@ namespace kv return handle; } - if (read_version == NoVersion) + if (!read_version.has_value()) { // Grab opacity version that all Maps should be queried at. auto txid = store->current_txid(); @@ -144,7 +152,7 @@ namespace kv read_version = txid.version; } - auto abstract_map = store->get_map(read_version, map_name); + auto abstract_map = store->get_map(read_version.value(), map_name); if (abstract_map == nullptr) { // Store doesn't know this map yet - create it dynamically @@ -178,7 +186,7 @@ namespace kv fmt::format("Map {} has unexpected type", map_name)); } - auto change_set = untyped_map->create_change_set(read_version); + auto change_set = untyped_map->create_change_set(read_version.value()); return check_and_store_change_set( std::move(change_set), map_name, abstract_map); } @@ -229,7 +237,7 @@ namespace kv Version get_read_version() { - return read_version; + return read_version.value_or(NoVersion); } Version get_max_conflict_version() @@ -244,7 +252,7 @@ namespace kv void set_read_version_and_term(Version v, Term t) { - if (read_version == NoVersion) + if (!read_version.has_value()) { read_version = v; term = t; @@ -494,7 +502,7 @@ namespace kv created_maps.clear(); committed = false; success = false; - read_version = NoVersion; + read_version = std::nullopt; version = NoVersion; term = 0; root_at_read_version = std::nullopt; diff --git a/src/kv/untyped_map.h b/src/kv/untyped_map.h index a12e63d7e4..e640ad6b57 100644 --- a/src/kv/untyped_map.h +++ b/src/kv/untyped_map.h @@ -127,8 +127,9 @@ namespace kv::untyped auto search = state.get(it->first); if (search.has_value()) { - max_conflict_version = - std::max(max_conflict_version, search->version); + max_conflict_version = std::max( + max_conflict_version, + static_cast(abs(search->version))); } else { @@ -195,8 +196,9 @@ namespace kv::untyped { if (search.has_value() && max_conflict_version != kv::NoVersion) { - max_conflict_version = - std::max(max_conflict_version, search->version); + max_conflict_version = std::max( + max_conflict_version, + static_cast(abs(search->version))); } else { @@ -214,8 +216,9 @@ namespace kv::untyped auto search = current->state.get(it->first); if (search.has_value() && max_conflict_version != kv::NoVersion) { - max_conflict_version = - std::max(max_conflict_version, search->version); + max_conflict_version = std::max( + max_conflict_version, + static_cast(abs(search->version))); max_conflict_version = std::max(max_conflict_version, search->read_version); } @@ -233,7 +236,7 @@ namespace kv::untyped return true; } - void commit(Version v, bool track_read_versions) override + void commit(Version v_, bool track_read_versions) override { if (change_set.writes.empty() && !track_read_versions) { @@ -244,6 +247,8 @@ namespace kv::untyped auto& roll = map.get_roll(); auto state = roll.commits->get_tail()->state; + DeletableVersion v = static_cast(v_); + // To track conflicts the read version of all keys that are read or // written within a transaction must be updated. if (track_read_versions) @@ -256,8 +261,8 @@ namespace kv::untyped { continue; } - state = - state.put(it->first, VersionV{search->version, v, search->value}); + state = state.put( + it->first, VersionV{search->version, v_, search->value}); } if (change_set.writes.empty()) { @@ -279,7 +284,7 @@ namespace kv::untyped { // Write the new value with the global version. changes = true; - state = state.put(it->first, VersionV{v, v, it->second.value()}); + state = state.put(it->first, VersionV{v, v_, it->second.value()}); } else { @@ -289,7 +294,7 @@ namespace kv::untyped if (search.has_value()) { changes = true; - state = state.put(it->first, VersionV{-v, -v, {}}); + state = state.put(it->first, VersionV{-v, v_, {}}); } } } diff --git a/src/node/backup_signatures.h b/src/node/backup_signatures.h index fe8dbce89f..c3499a5703 100644 --- a/src/node/backup_signatures.h +++ b/src/node/backup_signatures.h @@ -12,17 +12,15 @@ namespace ccf { struct BackupSignatures { - kv::Consensus::View view = 0; - kv::Consensus::SeqNo seqno = 0; + ccf::View view = 0; + ccf::SeqNo seqno = 0; crypto::Sha256Hash root; std::vector signatures; BackupSignatures() = default; BackupSignatures( - kv::Consensus::View view_, - kv::Consensus::SeqNo seqno_, - const crypto::Sha256Hash root_) : + ccf::View view_, ccf::SeqNo seqno_, const crypto::Sha256Hash root_) : view(view_), seqno(seqno_), root(root_) diff --git a/src/node/channels.h b/src/node/channels.h index 6fde8e85db..d55636e61c 100644 --- a/src/node/channels.h +++ b/src/node/channels.h @@ -20,13 +20,13 @@ namespace ccf { - using SeqNo = uint64_t; - using GcmHdr = crypto::GcmHeader; + using SendNonce = uint64_t; + using GcmHdr = crypto::GcmHeader; struct RecvNonce { uint8_t tid; - uint64_t nonce : (sizeof(uint64_t) - sizeof(uint8_t)) * CHAR_BIT; + uint64_t nonce : (sizeof(SendNonce) - sizeof(tid)) * CHAR_BIT; RecvNonce(uint64_t nonce_, uint8_t tid_) : tid(tid_), nonce(nonce_) {} RecvNonce(const uint64_t header) @@ -40,7 +40,7 @@ namespace ccf } }; static_assert( - sizeof(RecvNonce) == sizeof(SeqNo), "RecvNonce is the wrong size"); + sizeof(RecvNonce) == sizeof(SendNonce), "RecvNonce is the wrong size"); static inline RecvNonce get_nonce(const GcmHdr& header) { @@ -111,7 +111,7 @@ namespace ccf std::unique_ptr next_key; // Incremented for each tagged/encrypted message - std::atomic send_nonce{1}; + std::atomic send_nonce{1}; // Used to buffer at most one message sent on the channel before it is // established @@ -121,8 +121,8 @@ namespace ccf // Set to the latest successfully received nonce. struct ChannelSeqno { - SeqNo main_thread_seqno; - SeqNo tid_seqno; + SendNonce main_thread_seqno; + SendNonce tid_seqno; }; std::array local_recv_nonce = {{}}; @@ -147,7 +147,7 @@ namespace ccf current_tid == threading::ThreadMessaging::main_thread || current_tid % threading::ThreadMessaging::thread_count == tid); - SeqNo* local_nonce; + SendNonce* local_nonce; if (current_tid == threading::ThreadMessaging::main_thread) { local_nonce = &local_recv_nonce[tid].main_thread_seqno; diff --git a/src/node/entities.h b/src/node/entities.h index e1c6b4c1a3..eabbe9d179 100644 --- a/src/node/entities.h +++ b/src/node/entities.h @@ -12,7 +12,6 @@ namespace ccf { - using Index = int64_t; using Node2NodeMsg = uint64_t; using Cert = std::vector; diff --git a/src/node/historical_queries.h b/src/node/historical_queries.h index d4289baf2f..514272e209 100644 --- a/src/node/historical_queries.h +++ b/src/node/historical_queries.h @@ -56,11 +56,11 @@ namespace ccf::historical struct LedgerSecretRecoveryInfo { - kv::SeqNo target_seqno = 0; + ccf::SeqNo target_seqno = 0; LedgerSecretPtr last_ledger_secret; LedgerSecretRecoveryInfo( - kv::SeqNo target_seqno_, LedgerSecretPtr last_ledger_secret_) : + ccf::SeqNo target_seqno_, LedgerSecretPtr last_ledger_secret_) : target_seqno(target_seqno_), last_ledger_secret(last_ledger_secret_) {} @@ -89,21 +89,22 @@ namespace ccf::historical StorePtr store = nullptr; bool is_signature = false; TxReceiptPtr receipt = nullptr; - kv::TxID transaction_id; + ccf::TxID transaction_id; }; using StoreDetailsPtr = std::shared_ptr; struct Request { - kv::SeqNo first_requested_seqno = 0; - kv::SeqNo last_requested_seqno = 0; + ccf::SeqNo first_requested_seqno = 0; + ccf::SeqNo last_requested_seqno = 0; std::vector requested_stores; std::chrono::milliseconds time_to_expiry; // Entries from outside the requested range (such as the next signature) // may be needed to trust this range. They are stored here, distinct from // user-requested stores. - std::optional> supporting_signature; + std::optional> + supporting_signature; // Only set when recovering ledger secrets std::unique_ptr ledger_secret_recovery_info = @@ -111,7 +112,7 @@ namespace ccf::historical Request() {} - StoreDetailsPtr get_store_details(kv::SeqNo seqno) const + StoreDetailsPtr get_store_details(ccf::SeqNo seqno) const { if (seqno >= first_requested_seqno && seqno <= last_requested_seqno) { @@ -143,8 +144,8 @@ namespace ccf::historical // adjust to: // 0 1 2 3 4 5 6 // we need to shift _and_ start fetching 0, 1, and 6. - std::set adjust_range( - kv::SeqNo start_seqno, size_t num_following_indices) + std::set adjust_range( + ccf::SeqNo start_seqno, size_t num_following_indices) { if ( start_seqno == first_requested_seqno && @@ -154,10 +155,10 @@ namespace ccf::historical return {}; } - std::set ret; + std::set ret; std::vector new_stores(num_following_indices + 1); for (auto seqno = start_seqno; seqno <= - static_cast(start_seqno + num_following_indices); + static_cast(start_seqno + num_following_indices); ++seqno) { auto existing_details = get_store_details(seqno); @@ -216,7 +217,7 @@ namespace ccf::historical Invalidated, }; - UpdateTrustedResult update_trusted(kv::SeqNo new_seqno) + UpdateTrustedResult update_trusted(ccf::SeqNo new_seqno) { auto new_details = get_store_details(new_seqno); if (new_details->is_signature) @@ -355,11 +356,11 @@ namespace ccf::historical // Track all things currently requested by external callers std::map requests; - std::set pending_fetches; + std::set pending_fetches; ExpiryDuration default_expiry_duration = std::chrono::seconds(1800); - void fetch_entry_at(kv::SeqNo seqno) + void fetch_entry_at(ccf::SeqNo seqno) { const auto ib = pending_fetches.insert(seqno); if (ib.second) @@ -386,7 +387,7 @@ namespace ccf::historical // Returns true if this is a valid signature that passes our verification // checks - bool verify_signature(const StorePtr& sig_store, kv::SeqNo sig_seqno) + bool verify_signature(const StorePtr& sig_store, ccf::SeqNo sig_seqno) { const auto sig = get_signature(sig_store); if (!sig.has_value()) @@ -432,7 +433,7 @@ namespace ccf::historical } std::unique_ptr fetch_supporting_secret_if_needed( - kv::SeqNo seqno) + ccf::SeqNo seqno) { auto [earliest_ledger_secret_seqno, earliest_ledger_secret] = get_earliest_known_ledger_secret(); @@ -467,7 +468,7 @@ namespace ccf::historical void process_deserialised_store( const StorePtr& store, const crypto::Sha256Hash& entry_digest, - kv::SeqNo seqno, + ccf::SeqNo seqno, bool is_signature) { auto request_it = requests.begin(); @@ -607,7 +608,7 @@ namespace ccf::historical std::vector get_store_range_internal( RequestHandle handle, - kv::SeqNo start_seqno, + ccf::SeqNo start_seqno, size_t num_following_indices, ExpiryDuration seconds_until_expiry) { @@ -662,8 +663,8 @@ namespace ccf::historical std::vector trusted_states; - for (kv::SeqNo seqno = start_seqno; - seqno <= static_cast(start_seqno + num_following_indices); + for (ccf::SeqNo seqno = start_seqno; seqno <= + static_cast(start_seqno + num_following_indices); ++seqno) { auto target_details = request.get_store_details(seqno); @@ -690,7 +691,7 @@ namespace ccf::historical // Used when we received an invalid entry, to drop any requests which were // asking for it - void delete_all_interested_requests(kv::SeqNo seqno) + void delete_all_interested_requests(ccf::SeqNo seqno) { auto request_it = requests.begin(); while (request_it != requests.end()) @@ -721,7 +722,7 @@ namespace ccf::historical StorePtr get_store_at( RequestHandle handle, - kv::SeqNo seqno, + ccf::SeqNo seqno, ExpiryDuration seconds_until_expiry) override { auto range = get_store_range(handle, seqno, seqno, seconds_until_expiry); @@ -733,12 +734,12 @@ namespace ccf::historical return range[0]; } - StorePtr get_store_at(RequestHandle handle, kv::SeqNo seqno) override + StorePtr get_store_at(RequestHandle handle, ccf::SeqNo seqno) override { return get_store_at(handle, seqno, default_expiry_duration); } - StatePtr get_state_at(RequestHandle handle, kv::SeqNo seqno) override + StatePtr get_state_at(RequestHandle handle, ccf::SeqNo seqno) override { auto range = get_store_range_internal(handle, seqno, 1, default_expiry_duration); @@ -753,8 +754,8 @@ namespace ccf::historical std::vector get_store_range( RequestHandle handle, - kv::SeqNo start_seqno, - kv::SeqNo end_seqno, + ccf::SeqNo start_seqno, + ccf::SeqNo end_seqno, ExpiryDuration seconds_until_expiry) override { if (end_seqno < start_seqno) @@ -777,7 +778,9 @@ namespace ccf::historical } std::vector get_store_range( - RequestHandle handle, kv::SeqNo start_seqno, kv::SeqNo end_seqno) override + RequestHandle handle, + ccf::SeqNo start_seqno, + ccf::SeqNo end_seqno) override { return get_store_range( handle, start_seqno, end_seqno, default_expiry_duration); @@ -795,7 +798,7 @@ namespace ccf::historical return erased_count > 0; } - bool handle_ledger_entry(kv::SeqNo seqno, const LedgerEntry& data) + bool handle_ledger_entry(ccf::SeqNo seqno, const LedgerEntry& data) { std::lock_guard guard(requests_lock); const auto it = pending_fetches.find(seqno); @@ -883,7 +886,7 @@ namespace ccf::historical return true; } - void handle_no_entry(kv::SeqNo seqno) + void handle_no_entry(ccf::SeqNo seqno) { std::lock_guard guard(requests_lock); diff --git a/src/node/progress_tracker.h b/src/node/progress_tracker.h index 489a6239cf..76eb016422 100644 --- a/src/node/progress_tracker.h +++ b/src/node/progress_tracker.h @@ -30,7 +30,7 @@ namespace ccf std::shared_ptr store; kv::TxHistory::Result add_signature( - kv::TxID tx_id, + ccf::TxID tx_id, const NodeId& node_id, uint32_t signature_size, std::array& sig, @@ -50,7 +50,7 @@ namespace ccf } kv::TxHistory::Result record_primary( - kv::TxID tx_id, + ccf::TxID tx_id, NodeId node_id, crypto::Sha256Hash& root, std::vector& sig, @@ -69,12 +69,12 @@ namespace ccf LOG_TRACE_FMT( "record_primary node_id:{}, seqno:{}, hashed_nonce:{}, root:{}, sig:{}", node_id, - tx_id.version, + tx_id.seqno, hashed_nonce, root, sig); - auto it = certificates.find(tx_id.version); + auto it = certificates.find(tx_id.seqno); if (it == certificates.end()) { CommitCert cert(root, my_nonce); @@ -82,15 +82,15 @@ namespace ccf BftNodeSignature bft_node_sig(sig, node_id, hashed_nonce); bft_node_sig.is_primary = true; try_match_unmatched_nonces( - cert, bft_node_sig, tx_id.term, tx_id.version, node_id); + cert, bft_node_sig, tx_id.view, tx_id.seqno, node_id); cert.sigs.insert( std::pair(node_id, bft_node_sig)); certificates.insert( - std::pair(tx_id.version, cert)); + std::pair(tx_id.seqno, cert)); LOG_TRACE_FMT( - "Adding new root for view:{}, seqno:{}", tx_id.term, tx_id.version); + "Adding new root for view:{}, seqno:{}", tx_id.view, tx_id.seqno); return kv::TxHistory::Result::OK; } else @@ -102,7 +102,7 @@ namespace ccf BftNodeSignature bft_node_sig({}, node_id, hashed_nonce); bft_node_sig.is_primary = true; try_match_unmatched_nonces( - cert, bft_node_sig, tx_id.term, tx_id.version, node_id); + cert, bft_node_sig, tx_id.view, tx_id.seqno, node_id); cert.my_nonce = my_nonce; cert.have_primary_signature = true; for (auto& sig : cert.sigs) @@ -121,14 +121,14 @@ namespace ccf "record_primary: Signature verification from {} FAILED, view:{}, " "seqno:{}", sig.first, - tx_id.term, - tx_id.version)); + tx_id.view, + tx_id.seqno)); } LOG_TRACE_FMT( "Signature verification from {} passed, view:{}, seqno:{}", sig.second.node, - tx_id.term, - tx_id.version); + tx_id.view, + tx_id.seqno); } cert.sigs.insert( std::pair(node_id, bft_node_sig)); @@ -150,16 +150,16 @@ namespace ccf } kv::TxHistory::Result record_primary_signature( - kv::TxID tx_id, std::vector& sig) + ccf::TxID tx_id, std::vector& sig) { std::unique_lock guard(lock); - auto it = certificates.find(tx_id.version); + auto it = certificates.find(tx_id.seqno); if (it == certificates.end()) { LOG_FAIL_FMT( "Adding signature to primary that does not exist view:{}, seqno:{}", - tx_id.term, - tx_id.version); + tx_id.view, + tx_id.seqno); return kv::TxHistory::Result::FAIL; } @@ -178,7 +178,7 @@ namespace ccf } kv::TxHistory::Result receive_backup_signatures( - kv::TxID& tx_id, uint32_t node_count, bool is_primary) + ccf::TxID& tx_id, uint32_t node_count, bool is_primary) { std::unique_lock guard(lock); std::optional sigs = @@ -256,8 +256,8 @@ namespace ccf } } - tx_id.term = sigs_value.view; - tx_id.version = sigs_value.seqno; + tx_id.view = sigs_value.view; + tx_id.seqno = sigs_value.seqno; return success; } @@ -269,14 +269,14 @@ namespace ccf CCF_ASSERT(nonces.has_value(), "nonces does not have a value"); aft::RevealedNonces& nonces_value = nonces.value(); - auto it = certificates.find(nonces_value.tx_id.version); + auto it = certificates.find(nonces_value.tx_id.seqno); if (it == certificates.end()) { LOG_FAIL_FMT( "Primary send backup signatures before sending the primary " "signature view:{}, seqno:{}", - nonces_value.tx_id.term, - nonces_value.tx_id.version); + nonces_value.tx_id.view, + nonces_value.tx_id.seqno); return kv::TxHistory::Result::FAIL; } @@ -290,8 +290,8 @@ namespace ccf "Node {} sent revealed nonce before sending a signature view:{}, " "seqno:{}", revealed_nonce.node_id, - nonces_value.tx_id.term, - nonces_value.tx_id.version); + nonces_value.tx_id.view, + nonces_value.tx_id.seqno); return kv::TxHistory::Result::FAIL; } @@ -302,8 +302,8 @@ namespace ccf LOG_FAIL_FMT( "Hashed nonces does not match with nonce view:{}, seqno:{}, " "node_id:{}", - nonces_value.tx_id.term, - nonces_value.tx_id.version, + nonces_value.tx_id.view, + nonces_value.tx_id.seqno, revealed_nonce.node_id); return kv::TxHistory::Result::FAIL; } @@ -315,31 +315,30 @@ namespace ccf } cert.nonces_committed_to_ledger = true; - try_update_watermark(cert, nonces_value.tx_id.version, true); + try_update_watermark(cert, nonces_value.tx_id.seqno, true); return kv::TxHistory::Result::OK; } kv::TxHistory::Result add_signature_ack( - kv::TxID tx_id, const NodeId& node_id, uint32_t node_count = 0) + ccf::TxID tx_id, const NodeId& node_id, uint32_t node_count = 0) { std::unique_lock guard(lock); - auto it = certificates.find(tx_id.version); + auto it = certificates.find(tx_id.seqno); if (it == certificates.end()) { // We currently do not know what the root is, so lets save this // signature and and we will verify the root when we get it from the // primary - auto r = - certificates.insert(std::pair( - tx_id.version, CommitCert())); + auto r = certificates.insert( + std::pair(tx_id.seqno, CommitCert())); it = r.first; } LOG_TRACE_FMT( "processing recv_signature_received_ack, from:{} view:{}, seqno:{}", node_id, - tx_id.term, - tx_id.version); + tx_id.view, + tx_id.seqno); auto& cert = it->second; cert.sig_acks.insert(node_id); @@ -352,7 +351,7 @@ namespace ccf } void add_nonce_reveal( - kv::TxID tx_id, + ccf::TxID tx_id, Nonce nonce, const NodeId& node_id, uint32_t node_count, @@ -360,15 +359,14 @@ namespace ccf { std::unique_lock guard(lock); bool did_add = false; - auto it = certificates.find(tx_id.version); + auto it = certificates.find(tx_id.seqno); if (it == certificates.end()) { // We currently do not know what the root is, so lets save this // signature and and we will verify the root when we get it from the // primary - auto r = - certificates.insert(std::pair( - tx_id.version, CommitCert())); + auto r = certificates.insert( + std::pair(tx_id.seqno, CommitCert())); it = r.first; did_add = true; } @@ -385,8 +383,8 @@ namespace ccf LOG_TRACE_FMT( "add_nonce_reveal view:{}, seqno:{}, node_id:{}, sig.hashed_nonce:{}, " " received.nonce:{}, hash(received.nonce):{} did_add:{}", - tx_id.term, - tx_id.version, + tx_id.view, + tx_id.seqno, node_id, sig.hashed_nonce, nonce, @@ -401,8 +399,8 @@ namespace ccf "Nonces do not match add_nonce_reveal view:{}, seqno:{}, node_id:{}, " "sig.hashed_nonce:{}, " " received.nonce:{}, hash(received.nonce):{} did_add:{}", - tx_id.term, - tx_id.version, + tx_id.view, + tx_id.seqno, node_id, sig.hashed_nonce, nonce, @@ -411,8 +409,8 @@ namespace ccf throw ccf::ccf_logic_error(fmt::format( "nonces do not match verification from {} FAILED, view:{}, seqno:{}", node_id, - tx_id.term, - tx_id.version)); + tx_id.view, + tx_id.seqno)); } sig.nonce = nonce; cert.nonce_set.insert(node_id); @@ -435,16 +433,16 @@ namespace ccf store->write_nonces(revealed_nonces); } - try_update_watermark(cert, tx_id.version, is_primary); + try_update_watermark(cert, tx_id.seqno, is_primary); } - crypto::Sha256Hash get_node_hashed_nonce(kv::TxID tx_id) + crypto::Sha256Hash get_node_hashed_nonce(ccf::TxID tx_id) { std::unique_lock guard(lock); return get_node_hashed_nonce_internal(tx_id); } - void get_node_hashed_nonce(kv::TxID tx_id, crypto::Sha256Hash& hash) + void get_node_hashed_nonce(ccf::TxID tx_id, crypto::Sha256Hash& hash) { Nonce nonce = get_node_nonce(tx_id); hash_data(nonce, hash); @@ -467,22 +465,22 @@ namespace ccf hash = crypto::Sha256Hash({data.h.data(), data.h.size()}); } - kv::Consensus::SeqNo get_highest_committed_nonce() + ccf::SeqNo get_highest_committed_nonce() { return highest_commit_level; } - std::tuple, kv::Consensus::SeqNo> - get_view_change_message(kv::Consensus::View view) + std::tuple, ccf::SeqNo> + get_view_change_message(ccf::View view) { std::unique_lock guard(lock); - auto it = certificates.find(highest_prepared_level.version); + auto it = certificates.find(highest_prepared_level.seqno); if (it == certificates.end()) { throw ccf::ccf_logic_error(fmt::format( "Invalid prepared level, view:{}, seqno:{}", - highest_prepared_level.term, - highest_prepared_level.version)); + highest_prepared_level.view, + highest_prepared_level.seqno)); } auto& cert = it->second; @@ -493,15 +491,15 @@ namespace ccf m->signatures.push_back(sig.second); } - store->sign_view_change_request(*m, view, highest_prepared_level.version); - return std::make_tuple(std::move(m), highest_prepared_level.version); + store->sign_view_change_request(*m, view, highest_prepared_level.seqno); + return std::make_tuple(std::move(m), highest_prepared_level.seqno); } bool apply_view_change_message( ViewChangeRequest& view_change, const NodeId& from, - kv::Consensus::View view, - kv::Consensus::SeqNo seqno) + ccf::View view, + ccf::SeqNo seqno) { std::unique_lock guard(lock); if (!store->verify_view_change_request(view_change, from, view, seqno)) @@ -559,25 +557,25 @@ namespace ccf bool apply_new_view( const NodeId& from, uint32_t node_count, - kv::Consensus::View& view_, - kv::Consensus::SeqNo& seqno_) const + ccf::View& view_, + ccf::SeqNo& seqno_) const { std::unique_lock guard(lock); auto new_view = store->get_new_view(); CCF_ASSERT(new_view.has_value(), "new view does not have a value"); - kv::Consensus::View view = new_view->view; - kv::Consensus::SeqNo seqno = new_view->seqno; + ccf::View view = new_view->view; + ccf::SeqNo seqno = new_view->seqno; if ( - seqno < highest_prepared_level.version || - view < highest_prepared_level.term) + seqno < highest_prepared_level.seqno || + view < highest_prepared_level.view) { LOG_FAIL_FMT( "Invalid view and seqno in the new view highest prepared from:{}, " "view:{},seqno:{}, new_view view:{}, seqno:{}", from, - highest_prepared_level.term, - highest_prepared_level.version, + highest_prepared_level.view, + highest_prepared_level.seqno, view, seqno); return false; @@ -625,7 +623,7 @@ namespace ccf return true; } - Nonce get_node_nonce(kv::TxID tx_id) + Nonce get_node_nonce(ccf::TxID tx_id) { std::unique_lock guard(lock); return get_node_nonce_(tx_id); @@ -634,14 +632,14 @@ namespace ccf private: NodeId id; std::shared_ptr entropy; - kv::Consensus::SeqNo highest_commit_level = 0; - kv::TxID highest_prepared_level = {0, 0}; + ccf::SeqNo highest_commit_level = 0; + ccf::TxID highest_prepared_level = {0, 0}; - std::map certificates; + std::map certificates; mutable SpinLock lock; kv::TxHistory::Result add_signature_internal( - kv::TxID tx_id, + ccf::TxID tx_id, const NodeId& node_id, uint32_t signature_size, std::array& sig, @@ -652,17 +650,16 @@ namespace ccf LOG_TRACE_FMT( "add_signature node_id:{}, seqno:{}, hashed_nonce:{}", node_id, - tx_id.version, + tx_id.seqno, hashed_nonce); - auto it = certificates.find(tx_id.version); + auto it = certificates.find(tx_id.seqno); if (it == certificates.end()) { // At this point the appropriate Merkle root is not known. The signature // will be recorded and verified when the primary sends the apporiate // Merkle root. - auto r = - certificates.insert(std::pair( - tx_id.version, CommitCert())); + auto r = certificates.insert( + std::pair(tx_id.seqno, CommitCert())); it = r.first; } else @@ -676,15 +673,15 @@ namespace ccf "add_signatures: Signature verification from {} FAILED, view:{}, " "seqno:{}", node_id, - tx_id.term, - tx_id.version)); + tx_id.view, + tx_id.seqno)); return kv::TxHistory::Result::FAIL; } LOG_TRACE_FMT( "Signature verification from {} passed, view:{}, seqno:{}", node_id, - tx_id.term, - tx_id.version); + tx_id.view, + tx_id.seqno); } auto& cert = it->second; @@ -692,8 +689,8 @@ namespace ccf { LOG_TRACE_FMT( "Already wrote append entry view:{}, seqno:{}, ignoring", - tx_id.term, - tx_id.version); + tx_id.view, + tx_id.seqno); return kv::TxHistory::Result::OK; } @@ -715,7 +712,7 @@ namespace ccf BftNodeSignature bft_node_sig(std::move(sig_vec), node_id, hashed_nonce); try_match_unmatched_nonces( - cert, bft_node_sig, tx_id.term, tx_id.version, node_id); + cert, bft_node_sig, tx_id.view, tx_id.seqno, node_id); cert.sigs.insert( std::pair(node_id, std::move(bft_node_sig))); @@ -723,7 +720,7 @@ namespace ccf { if (is_primary) { - ccf::BackupSignatures sig_value(tx_id.term, tx_id.version, cert.root); + ccf::BackupSignatures sig_value(tx_id.view, tx_id.seqno, cert.root); for (const auto& sig : cert.sigs) { @@ -734,7 +731,7 @@ namespace ccf } } - LOG_TRACE_FMT("Adding signatures to ledger seqno:{}", tx_id.version); + LOG_TRACE_FMT("Adding signatures to ledger seqno:{}", tx_id.seqno); store->write_backup_signatures(sig_value); cert.wrote_sig_to_ledger = true; } @@ -743,20 +740,20 @@ namespace ccf return kv::TxHistory::Result::OK; } - Nonce get_node_nonce_(kv::TxID tx_id) + Nonce get_node_nonce_(ccf::TxID tx_id) { - auto it = certificates.find(tx_id.version); + auto it = certificates.find(tx_id.seqno); if (it == certificates.end()) { throw ccf::ccf_logic_error(fmt::format( "Attempting to access unknown nonce, view:{}, seqno:{}", - tx_id.term, - tx_id.version)); + tx_id.view, + tx_id.seqno)); } return it->second.my_nonce; } - crypto::Sha256Hash get_node_hashed_nonce_internal(kv::TxID tx_id) + crypto::Sha256Hash get_node_hashed_nonce_internal(ccf::TxID tx_id) { Nonce nonce = get_node_nonce_(tx_id); return hash_data(nonce); @@ -765,8 +762,8 @@ namespace ccf void try_match_unmatched_nonces( CommitCert& cert, BftNodeSignature& bft_node_sig, - kv::Consensus::View view, - kv::Consensus::SeqNo seqno, + ccf::View view, + ccf::SeqNo seqno, const NodeId& node_id) { auto it_unmatched_nonces = cert.unmatched_nonces.find(node_id); @@ -813,19 +810,19 @@ namespace ccf } bool can_send_sig_ack( - CommitCert& cert, const kv::TxID& tx_id, uint32_t node_count) + CommitCert& cert, const ccf::TxID& tx_id, uint32_t node_count) { if ( cert.sigs.size() >= get_message_threshold(node_count) && !cert.ack_sent && cert.have_primary_signature) { - if (tx_id.version > highest_prepared_level.version) + if (tx_id.seqno > highest_prepared_level.seqno) { CCF_ASSERT_FMT( - tx_id.term >= highest_prepared_level.term, + tx_id.view >= highest_prepared_level.view, "Prepared terms are moving backwards new_term:{}, current_term:{}", - tx_id.term, - highest_prepared_level.term); + tx_id.view, + highest_prepared_level.view); highest_prepared_level = tx_id; } @@ -848,9 +845,7 @@ namespace ccf } void try_update_watermark( - CommitCert& cert, - kv::Consensus::SeqNo seqno, - bool should_clear_old_entries) + CommitCert& cert, ccf::SeqNo seqno, bool should_clear_old_entries) { if (cert.nonces_committed_to_ledger && seqno > highest_commit_level) { diff --git a/src/node/progress_tracker_types.h b/src/node/progress_tracker_types.h index 05a3ef3493..f700f7ef24 100644 --- a/src/node/progress_tracker_types.h +++ b/src/node/progress_tracker_types.h @@ -70,15 +70,13 @@ namespace ccf uint32_t sig_size, uint8_t* sig) = 0; virtual void sign_view_change_request( - ViewChangeRequest& view_change, - kv::Consensus::View view, - kv::Consensus::SeqNo seqno) = 0; + ViewChangeRequest& view_change, ccf::View view, ccf::SeqNo seqno) = 0; virtual bool verify_view_change_request( ViewChangeRequest& view_change, const NodeId& from, - kv::Consensus::View view, - kv::Consensus::SeqNo seqno) = 0; - virtual kv::Consensus::SeqNo write_view_change_confirmation( + ccf::View view, + ccf::SeqNo seqno) = 0; + virtual ccf::SeqNo write_view_change_confirmation( ViewChangeConfirmation& new_view) = 0; virtual bool verify_view_change_request_confirmation( ViewChangeConfirmation& new_view, const NodeId& from) = 0; @@ -148,12 +146,12 @@ namespace ccf { LOG_FAIL_FMT( "Failed to write nonces, view:{}, seqno:{}", - nonces.tx_id.term, - nonces.tx_id.version); + nonces.tx_id.view, + nonces.tx_id.seqno); throw ccf_logic_error(fmt::format( "Failed to write nonces, view:{}, seqno:{}", - nonces.tx_id.term, - nonces.tx_id.version)); + nonces.tx_id.view, + nonces.tx_id.seqno)); } } @@ -192,9 +190,7 @@ namespace ccf } void sign_view_change_request( - ViewChangeRequest& view_change, - kv::Consensus::View view, - kv::Consensus::SeqNo seqno) override + ViewChangeRequest& view_change, ccf::View view, ccf::SeqNo seqno) override { crypto::Sha256Hash h = hash_view_change(view_change, view, seqno); view_change.signature = kp.sign_hash(h.h.data(), h.h.size()); @@ -203,8 +199,8 @@ namespace ccf bool verify_view_change_request( ViewChangeRequest& view_change, const NodeId& from, - kv::Consensus::View view, - kv::Consensus::SeqNo seqno) override + ccf::View view, + ccf::SeqNo seqno) override { crypto::Sha256Hash h = hash_view_change(view_change, view, seqno); @@ -240,7 +236,7 @@ namespace ccf h.h, new_view.signature, crypto::MDType::SHA256); } - kv::Consensus::SeqNo write_view_change_confirmation( + ccf::SeqNo write_view_change_confirmation( ViewChangeConfirmation& new_view) override { kv::Tx tx(&store); @@ -290,9 +286,7 @@ namespace ccf NewViewsMap new_views; crypto::Sha256Hash hash_view_change( - const ViewChangeRequest& v, - kv::Consensus::View view, - kv::Consensus::SeqNo seqno) const + const ViewChangeRequest& v, ccf::View view, ccf::SeqNo seqno) const { auto ch = crypto::make_incremental_sha256(); diff --git a/src/node/request_tracker.h b/src/node/request_tracker.h index 7b3d32dfb5..bc3dfe1b35 100644 --- a/src/node/request_tracker.h +++ b/src/node/request_tracker.h @@ -123,8 +123,7 @@ namespace aft hashes_without_requests_list.is_empty(); } - void insert_signed_request( - kv::Consensus::SeqNo seqno, std::chrono::milliseconds time) + void insert_signed_request(ccf::SeqNo seqno, std::chrono::milliseconds time) { std::unique_lock guard(lock); if (seqno > seqno_last_signature) @@ -134,7 +133,7 @@ namespace aft } } - std::tuple + std::tuple get_seqno_time_last_request() const { std::unique_lock guard(lock); @@ -159,7 +158,7 @@ namespace aft snmalloc::DLList hashes_without_requests_list; - kv::Consensus::SeqNo seqno_last_signature = -1; + ccf::SeqNo seqno_last_signature = ccf::SEQNO_UNKNOWN; std::chrono::milliseconds time_last_signature = std::chrono::milliseconds(0); mutable SpinLock lock; diff --git a/src/node/rpc/call_types.h b/src/node/rpc/call_types.h index de0dcc1f4d..bd07c09833 100644 --- a/src/node/rpc/call_types.h +++ b/src/node/rpc/call_types.h @@ -54,7 +54,7 @@ namespace ccf struct Out { ServiceStatus service_status; - std::optional current_view; + std::optional current_view; std::optional primary_id; }; }; diff --git a/src/node/rpc/frontend.h b/src/node/rpc/frontend.h index 7f86c8e41a..d19474403a 100644 --- a/src/node/rpc/frontend.h +++ b/src/node/rpc/frontend.h @@ -151,7 +151,7 @@ namespace ccf kv::Tx& tx, const PreExec& pre_exec = {}, kv::Version prescribed_commit_version = kv::NoVersion, - kv::Consensus::SeqNo max_conflict_version = kv::NoVersion) + ccf::SeqNo max_conflict_version = kv::NoVersion) { const auto endpoint = endpoints.find_endpoint(tx, *ctx); if (endpoint == nullptr) @@ -584,8 +584,8 @@ namespace ccf ProcessBftResp process_bft( std::shared_ptr ctx, - kv::Consensus::SeqNo prescribed_commit_version, - kv::Consensus::SeqNo max_conflict_version) override + ccf::SeqNo prescribed_commit_version, + ccf::SeqNo max_conflict_version) override { auto tx = tables.create_tx(); return process_bft( @@ -602,8 +602,8 @@ namespace ccf ProcessBftResp process_bft( std::shared_ptr ctx, kv::Tx& tx, - kv::Consensus::SeqNo prescribed_commit_version = kv::NoVersion, - kv::Consensus::SeqNo max_conflict_version = kv::NoVersion) override + ccf::SeqNo prescribed_commit_version = kv::NoVersion, + ccf::SeqNo max_conflict_version = kv::NoVersion) override { // Note: this can only happen if the primary is malicious, // and has executed a user transaction when the service wasn't diff --git a/src/node/rpc/test/node_stub.h b/src/node/rpc/test/node_stub.h index bc4a815d9d..3e4fc1ade5 100644 --- a/src/node/rpc/test/node_stub.h +++ b/src/node/rpc/test/node_stub.h @@ -100,28 +100,28 @@ namespace ccf historical::StorePtr get_store_at( historical::RequestHandle handle, - kv::SeqNo seqno, + ccf::SeqNo seqno, historical::ExpiryDuration seconds_until_expiry) { return nullptr; } historical::StorePtr get_store_at( - historical::RequestHandle handle, kv::SeqNo seqno) + historical::RequestHandle handle, ccf::SeqNo seqno) { return nullptr; } historical::StatePtr get_state_at( - historical::RequestHandle handle, kv::SeqNo seqno) + historical::RequestHandle handle, ccf::SeqNo seqno) { return nullptr; } std::vector get_store_range( historical::RequestHandle handle, - kv::SeqNo start_seqno, - kv::SeqNo end_seqno, + ccf::SeqNo start_seqno, + ccf::SeqNo end_seqno, historical::ExpiryDuration seconds_until_expiry) { return {}; @@ -129,8 +129,8 @@ namespace ccf std::vector get_store_range( historical::RequestHandle handle, - kv::SeqNo start_seqno, - kv::SeqNo end_seqno) + ccf::SeqNo start_seqno, + ccf::SeqNo end_seqno) { return {}; } diff --git a/src/node/rpc/tx_status.h b/src/node/rpc/tx_status.h index 01d94eefbd..97296c28f6 100644 --- a/src/node/rpc/tx_status.h +++ b/src/node/rpc/tx_status.h @@ -2,6 +2,7 @@ // Licensed under the Apache 2.0 License. #pragma once +#include "ccf/tx_id.h" #include "ds/json.h" namespace ccf @@ -64,14 +65,12 @@ namespace ccf {TxStatus::Committed, tx_status_to_str(TxStatus::Committed)}, {TxStatus::Invalid, tx_status_to_str(TxStatus::Invalid)}}); - constexpr int64_t VIEW_UNKNOWN = std::numeric_limits::min(); - - inline TxStatus evaluate_tx_status( - int64_t target_view, - int64_t target_seqno, - int64_t local_view, - int64_t committed_view, - int64_t committed_seqno) + [[maybe_unused]] static TxStatus evaluate_tx_status( + View target_view, + SeqNo target_seqno, + View local_view, + View committed_view, + SeqNo committed_seqno) { const bool is_committed = committed_seqno >= target_seqno; const bool views_match = local_view == target_view; diff --git a/src/node/signatures.h b/src/node/signatures.h index 7636b7a92e..1a4c34383e 100644 --- a/src/node/signatures.h +++ b/src/node/signatures.h @@ -12,15 +12,15 @@ namespace ccf { struct PrimarySignature : public NodeSignature { - kv::Consensus::SeqNo seqno = 0; - kv::Consensus::View view = 0; - kv::Consensus::SeqNo commit_seqno = 0; - kv::Consensus::View commit_view = 0; + ccf::SeqNo seqno = 0; + ccf::View view = 0; + ccf::SeqNo commit_seqno = 0; + ccf::View commit_view = 0; crypto::Sha256Hash root; PrimarySignature() {} - PrimarySignature(const ccf::NodeId& node_, kv::Consensus::SeqNo seqno_) : + PrimarySignature(const ccf::NodeId& node_, ccf::SeqNo seqno_) : NodeSignature(node_), seqno(seqno_) {} @@ -29,10 +29,10 @@ namespace ccf PrimarySignature( const ccf::NodeId& node_, - kv::Consensus::SeqNo seqno_, - kv::Consensus::View view_, - kv::Consensus::SeqNo commit_seqno_, - kv::Consensus::View commit_view_, + ccf::SeqNo seqno_, + ccf::View view_, + ccf::SeqNo commit_seqno_, + ccf::View commit_view_, const crypto::Sha256Hash root_, Nonce hashed_nonce_, const std::vector& sig_) : diff --git a/src/node/test/historical_queries.cpp b/src/node/test/historical_queries.cpp index b3786eb71f..88e90712d5 100644 --- a/src/node/test/historical_queries.cpp +++ b/src/node/test/historical_queries.cpp @@ -195,7 +195,7 @@ kv::Version rekey( } void validate_business_transaction( - ccf::historical::StorePtr store, kv::SeqNo seqno) + ccf::historical::StorePtr store, ccf::SeqNo seqno) { REQUIRE(store != nullptr); @@ -227,14 +227,14 @@ void validate_business_transaction( }); } -std::map> construct_host_ledger( +std::map> construct_host_ledger( std::shared_ptr c) { auto consensus = dynamic_cast(c.get()); REQUIRE(consensus != nullptr); INFO("Rebuild ledger as seen by host"); - std::map> ledger; + std::map> ledger; auto next_ledger_entry = consensus->pop_oldest_entry(); while (next_ledger_entry.has_value()) @@ -296,8 +296,8 @@ TEST_CASE("StateCache point queries") { INFO("The host sees requests for these indices"); REQUIRE(!stub_writer->writes.empty()); - std::set expected{low_seqno, high_seqno, unsigned_seqno}; - std::set actual; + std::set expected{low_seqno, high_seqno, unsigned_seqno}; + std::set actual; for (const auto& write : stub_writer->writes) { const uint8_t* data = write.contents.data(); diff --git a/src/node/test/history.cpp b/src/node/test/history.cpp index 3ca9841b83..dd6e30532b 100644 --- a/src/node/test/history.cpp +++ b/src/node/test/history.cpp @@ -26,7 +26,7 @@ public: DummyConsensus(kv::Store* store_) : store(store_) {} - bool replicate(const kv::BatchVector& entries, View view) override + bool replicate(const kv::BatchVector& entries, ccf::View view) override { if (store) { @@ -37,12 +37,12 @@ public: return true; } - std::pair get_committed_txid() override + std::pair get_committed_txid() override { return {2, 0}; } - SeqNo get_committed_seqno() override + ccf::SeqNo get_committed_seqno() override { return 0; } @@ -215,7 +215,7 @@ public: CompactingConsensus(kv::Store* store_) : store(store_) {} - bool replicate(const kv::BatchVector& entries, View view) override + bool replicate(const kv::BatchVector& entries, ccf::View view) override { for (auto& [version, data, committable, hooks] : entries) { @@ -226,12 +226,12 @@ public: return true; } - std::pair get_committed_txid() override + std::pair get_committed_txid() override { return {2, 0}; } - SeqNo get_committed_seqno() override + ccf::SeqNo get_committed_seqno() override { return 0; } @@ -246,7 +246,7 @@ public: return kv::test::PrimaryNodeId; } - View get_view(kv::Version version) override + ccf::View get_view(kv::Version version) override { return 2; } @@ -254,12 +254,12 @@ public: class TestPendingTx : public kv::PendingTx { - kv::TxID txid; + ccf::TxID txid; kv::Store& store; MapT& other_table; public: - TestPendingTx(kv::TxID txid_, kv::Store& store_, MapT& other_table_) : + TestPendingTx(ccf::TxID txid_, kv::Store& store_, MapT& other_table_) : txid(txid_), store(store_), other_table(other_table_) @@ -267,7 +267,7 @@ public: kv::PendingTxInfo call() override { - auto txr = store.create_reserved_tx(txid.version); + auto txr = store.create_reserved_tx(txid.seqno); auto txrv = txr.rw(other_table); txrv->put(0, 1); return txr.commit_reserved(); @@ -335,7 +335,7 @@ public: rollback_to(rollback_to_) {} - bool replicate(const kv::BatchVector& entries, View view) override + bool replicate(const kv::BatchVector& entries, ccf::View view) override { for (auto& [version, data, committable, hook] : entries) { @@ -346,12 +346,12 @@ public: return true; } - std::pair get_committed_txid() override + std::pair get_committed_txid() override { return {2, 0}; } - SeqNo get_committed_seqno() override + ccf::SeqNo get_committed_seqno() override { return 0; } @@ -366,12 +366,12 @@ public: return kv::test::PrimaryNodeId; } - View get_view(SeqNo seqno) override + ccf::View get_view(ccf::SeqNo seqno) override { return 2; } - View get_view() override + ccf::View get_view() override { return 2; } diff --git a/src/node/test/progress_tracker.cpp b/src/node/test/progress_tracker.cpp index 477c39bf65..19abfbc715 100644 --- a/src/node/test/progress_tracker.cpp +++ b/src/node/test/progress_tracker.cpp @@ -36,18 +36,15 @@ public: override); MAKE_MOCK3( sign_view_change_request, - void( - ccf::ViewChangeRequest& view_change, - kv::Consensus::View view, - kv::Consensus::SeqNo seqno), + void(ccf::ViewChangeRequest& view_change, ccf::View view, ccf::SeqNo seqno), override); MAKE_MOCK4( verify_view_change_request, bool( ccf::ViewChangeRequest& view_change, const kv::NodeId& from, - kv::Consensus::View view, - kv::Consensus::SeqNo seqno), + ccf::View view, + ccf::SeqNo seqno), override); MAKE_MOCK2( verify_view_change_request_confirmation, @@ -55,15 +52,15 @@ public: override); MAKE_MOCK1( write_view_change_confirmation, - kv::Consensus::SeqNo(ccf::ViewChangeConfirmation& new_view), + ccf::SeqNo(ccf::ViewChangeConfirmation& new_view), override); }; void ordered_execution( kv::NodeId my_node_id, std::unique_ptr& pt) { - kv::Consensus::View view = 0; - kv::Consensus::SeqNo seqno = 42; + ccf::View view = 0; + ccf::SeqNo seqno = 42; uint32_t node_count = 4; uint32_t node_count_quorum = 2; // Takes into account that counting starts at 0 @@ -311,7 +308,7 @@ TEST_CASE("Request tracker") aft::RequestTracker t; auto r = t.get_seqno_time_last_request(); - REQUIRE(std::get<0>(r) == -1); + REQUIRE(std::get<0>(r) == ccf::SEQNO_UNKNOWN); REQUIRE(std::get<1>(r) == std::chrono::milliseconds(0)); t.insert_signed_request(2, std::chrono::milliseconds(2)); @@ -329,8 +326,8 @@ TEST_CASE("Request tracker") TEST_CASE("Record primary signature") { kv::NodeId my_node_id = kv::test::PrimaryNodeId; - kv::Consensus::View view = 0; - kv::Consensus::SeqNo seqno = 42; + ccf::View view = 0; + ccf::SeqNo seqno = 42; crypto::Sha256Hash root; ccf::Nonce nonce; std::vector primary_sig; @@ -357,8 +354,8 @@ TEST_CASE("View Changes") StoreMock& store_mock = *store.get(); ccf::ProgressTracker pt(std::move(store), my_node_id); - kv::Consensus::View view = 0; - kv::Consensus::SeqNo seqno = 42; + ccf::View view = 0; + ccf::SeqNo seqno = 42; uint32_t node_count = 4; uint32_t node_count_quorum = 2; // Takes into account that counting starts at 0 @@ -423,7 +420,7 @@ TEST_CASE("View Changes") INFO("Update latest prepared"); { - kv::Consensus::SeqNo new_seqno = 84; + ccf::SeqNo new_seqno = 84; REQUIRE_CALL(store_mock, verify_signature(_, _, _, _)) .RETURN(true) @@ -476,7 +473,7 @@ TEST_CASE("View Changes") INFO("Update older prepared"); { - kv::Consensus::SeqNo new_seqno = 21; + ccf::SeqNo new_seqno = 21; REQUIRE_CALL(store_mock, verify_signature(_, _, _, _)) .RETURN(true) @@ -587,8 +584,8 @@ TEST_CASE("view-change-tracker timeout tests") TEST_CASE("view-change-tracker statemachine tests") { ccf::ViewChangeRequest v; - kv::Consensus::View view = 3; - kv::Consensus::SeqNo seqno = 1; + ccf::View view = 3; + ccf::SeqNo seqno = 1; uint32_t node_count = 4; INFO("Can trigger view change"); @@ -699,8 +696,8 @@ TEST_CASE("Sending evidence out of band") using trompeloeil::_; ccf::ViewChangeRequest v; - kv::Consensus::View view = 3; - kv::Consensus::SeqNo seqno = 1; + ccf::View view = 3; + ccf::SeqNo seqno = 1; constexpr uint32_t node_count = 4; INFO("Can trigger view change"); diff --git a/src/node/view_change.h b/src/node/view_change.h index 0ef5dc2236..7f39cc03b2 100644 --- a/src/node/view_change.h +++ b/src/node/view_change.h @@ -65,15 +65,14 @@ namespace ccf struct ViewChangeConfirmation { - kv::Consensus::View view = 0; - kv::Consensus::SeqNo seqno = 0; + ccf::View view = 0; + ccf::SeqNo seqno = 0; std::vector signature; std::map view_change_messages; ViewChangeConfirmation() = default; - ViewChangeConfirmation( - kv::Consensus::View view_, kv::Consensus::SeqNo seqno_) : + ViewChangeConfirmation(ccf::View view_, ccf::SeqNo seqno_) : view(view_), seqno(seqno_) {}