зеркало из https://github.com/microsoft/CCF.git
Consolidate View and SeqNo typedefs (#2367)
This commit is contained in:
Родитель
70ceb39931
Коммит
aa9e82279d
|
@ -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(
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
namespace ccf::historical
|
||||
{
|
||||
using CheckAvailability = std::function<bool(
|
||||
kv::Consensus::View view, kv::SeqNo seqno, std::string& error_reason)>;
|
||||
ccf::View view, ccf::SeqNo seqno, std::string& error_reason)>;
|
||||
|
||||
using HandleHistoricalQuery =
|
||||
std::function<void(ccf::endpoints::EndpointContext& args, StatePtr state)>;
|
||||
|
@ -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)
|
||||
|
|
|
@ -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<StorePtr> 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<StorePtr> 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.
|
||||
*
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -19,8 +19,8 @@ namespace nobuiltins
|
|||
std::vector<uint8_t> quote;
|
||||
std::vector<uint8_t> 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)
|
||||
{
|
||||
|
|
|
@ -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<kv::TxID>& transaction_id,
|
||||
const std::optional<ccf::TxID>& transaction_id,
|
||||
ccf::historical::TxReceiptPtr receipt)
|
||||
{
|
||||
const auto local_method = method.substr(method.find_first_not_of('/'));
|
||||
|
|
|
@ -52,9 +52,9 @@ namespace aft
|
|||
kv::Version ExecutorImpl::execute_request(
|
||||
std::unique_ptr<RequestMessage> request,
|
||||
bool is_create_request,
|
||||
kv::Consensus::SeqNo prescribed_commit_version,
|
||||
ccf::SeqNo prescribed_commit_version,
|
||||
std::shared_ptr<aft::RequestTracker> request_tracker,
|
||||
kv::Consensus::SeqNo max_conflict_version)
|
||||
ccf::SeqNo max_conflict_version)
|
||||
{
|
||||
std::shared_ptr<enclave::RpcContext>& ctx = request->get_request_ctx().ctx;
|
||||
std::shared_ptr<enclave::RpcHandler>& frontend =
|
||||
|
@ -92,8 +92,7 @@ namespace aft
|
|||
}
|
||||
|
||||
std::unique_ptr<aft::RequestMessage> 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<aft::RequestTracker> 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);
|
||||
|
||||
|
|
|
@ -37,19 +37,19 @@ namespace aft
|
|||
virtual kv::Version execute_request(
|
||||
std::unique_ptr<RequestMessage> request,
|
||||
bool is_create_request,
|
||||
kv::Consensus::SeqNo prescribed_commit_version = kv::NoVersion,
|
||||
ccf::SeqNo prescribed_commit_version = kv::NoVersion,
|
||||
std::shared_ptr<aft::RequestTracker> request_tracker = nullptr,
|
||||
kv::Consensus::SeqNo max_conflict_version = kv::NoVersion) = 0;
|
||||
ccf::SeqNo max_conflict_version = kv::NoVersion) = 0;
|
||||
|
||||
virtual std::unique_ptr<aft::RequestMessage> 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<aft::RequestTracker> 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<RequestMessage> request,
|
||||
bool is_create_request,
|
||||
kv::Consensus::SeqNo prescribed_commit_version = kv::NoVersion,
|
||||
ccf::SeqNo prescribed_commit_version = kv::NoVersion,
|
||||
std::shared_ptr<aft::RequestTracker> request_tracker = nullptr,
|
||||
kv::Consensus::SeqNo max_conflict_version = kv::NoVersion) override;
|
||||
ccf::SeqNo max_conflict_version = kv::NoVersion) override;
|
||||
|
||||
std::unique_ptr<aft::RequestMessage> 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<aft::RequestTracker> 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> state;
|
||||
|
|
|
@ -21,7 +21,7 @@ namespace aft
|
|||
std::vector<kv::Version> views;
|
||||
|
||||
public:
|
||||
static constexpr kv::Consensus::View InvalidView = ccf::VIEW_UNKNOWN;
|
||||
static constexpr ccf::View InvalidView = ccf::VIEW_UNKNOWN;
|
||||
|
||||
void initialise(const std::vector<kv::Version>& 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<ccf::NodeId, std::shared_ptr<Replica>> configuration;
|
||||
|
||||
ccf::NodeId my_node_id;
|
||||
kv::Consensus::View current_view;
|
||||
ccf::View current_view;
|
||||
kv::Version last_idx;
|
||||
kv::Version commit_idx;
|
||||
|
||||
|
|
|
@ -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<ccf::NodeId, ccf::ViewChangeRequest> 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<uint8_t> get_serialized_view_change_confirmation(
|
||||
kv::Consensus::View view)
|
||||
std::vector<uint8_t> 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<ccf::ViewChangeConfirmation>();
|
||||
|
@ -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<ccf::ProgressTrackerStore> store;
|
||||
std::map<kv::Consensus::View, ViewChange> view_changes;
|
||||
std::map<ccf::View, ViewChange> 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())
|
||||
|
|
|
@ -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<ccf::ViewChangeRequest> 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)
|
||||
{
|
||||
|
|
|
@ -44,28 +44,28 @@ namespace aft
|
|||
}
|
||||
|
||||
void force_become_primary(
|
||||
SeqNo seqno,
|
||||
View view,
|
||||
ccf::SeqNo seqno,
|
||||
ccf::View view,
|
||||
const std::vector<kv::Version>& 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<kv::Version>& 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<View, SeqNo> get_committed_txid() override
|
||||
std::pair<ccf::View, ccf::SeqNo> 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<SeqNo> get_view_history(SeqNo seqno) override
|
||||
std::vector<ccf::SeqNo> get_view_history(ccf::SeqNo seqno) override
|
||||
{
|
||||
return aft->get_term_history(seqno);
|
||||
}
|
||||
|
||||
void initialise_view_history(
|
||||
const std::vector<SeqNo>& view_history) override
|
||||
const std::vector<ccf::SeqNo>& 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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -29,12 +29,12 @@ namespace aft
|
|||
|
||||
struct RevealedNonces
|
||||
{
|
||||
kv::TxID tx_id;
|
||||
ccf::TxID tx_id;
|
||||
std::vector<RevealedNonce> 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)
|
||||
|
|
|
@ -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)
|
||||
}
|
|
@ -7,20 +7,21 @@
|
|||
|
||||
namespace champ
|
||||
{
|
||||
using Version = int64_t;
|
||||
using Version = uint64_t;
|
||||
using DeletableVersion = int64_t;
|
||||
|
||||
template <typename V>
|
||||
struct VersionV
|
||||
{
|
||||
Version version;
|
||||
DeletableVersion version;
|
||||
Version read_version;
|
||||
V value;
|
||||
|
||||
VersionV() :
|
||||
version(std::numeric_limits<Version>::min()),
|
||||
read_version(std::numeric_limits<Version>::min())
|
||||
version(std::numeric_limits<decltype(version)>::min()),
|
||||
read_version(std::numeric_limits<decltype(read_version)>::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)
|
||||
|
|
|
@ -43,12 +43,12 @@ namespace enclave
|
|||
|
||||
virtual ProcessBftResp process_bft(
|
||||
std::shared_ptr<enclave::RpcContext> 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<enclave::RpcContext> 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;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -65,7 +65,7 @@ namespace ws
|
|||
static std::vector<uint8_t> make_out_frame(
|
||||
size_t code,
|
||||
kv::Version seqno,
|
||||
kv::Consensus::View view,
|
||||
ccf::View view,
|
||||
const std::vector<uint8_t>& body)
|
||||
{
|
||||
size_t out_frame_size = ws::OUT_CCF_HEADER_SIZE + body.size();
|
||||
|
|
|
@ -16,7 +16,7 @@ namespace ws
|
|||
size_t code,
|
||||
const std::vector<uint8_t>& 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);
|
||||
};
|
||||
|
|
|
@ -483,7 +483,7 @@ namespace js
|
|||
|
||||
JSValue create_ccf_obj(
|
||||
TxContext* txctx,
|
||||
const std::optional<kv::TxID>& transaction_id,
|
||||
const std::optional<ccf::TxID>& 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<ccf::SeqNo>(transaction_id.value().version);
|
||||
tx_id.view = static_cast<ccf::View>(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<kv::TxID>& transaction_id,
|
||||
const std::optional<ccf::TxID>& transaction_id,
|
||||
ccf::historical::TxReceiptPtr receipt,
|
||||
JSContext* ctx)
|
||||
{
|
||||
|
|
|
@ -43,7 +43,7 @@ namespace js
|
|||
void populate_global_console(JSContext* ctx);
|
||||
void populate_global_ccf(
|
||||
TxContext* txctx,
|
||||
const std::optional<kv::TxID>& transaction_id,
|
||||
const std::optional<ccf::TxID>& transaction_id,
|
||||
ccf::historical::TxReceiptPtr receipt,
|
||||
JSContext* ctx);
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ namespace kv
|
|||
// version of last transaction which read the key and committed successfully
|
||||
using LastReadVersion = Version;
|
||||
template <typename K>
|
||||
using Read = std::map<K, std::tuple<Version, LastReadVersion>>;
|
||||
using Read = std::map<K, std::tuple<DeletableVersion, LastReadVersion>>;
|
||||
|
||||
// nullopt values represent deletions
|
||||
template <typename K, typename V>
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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<Version>::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<NodeId, NodeInfo>;
|
||||
|
||||
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>&, SeqNo)
|
||||
ccf::SeqNo, ccf::View, const std::vector<ccf::SeqNo>&, ccf::SeqNo)
|
||||
{
|
||||
state = Primary;
|
||||
}
|
||||
|
||||
virtual void init_as_backup(SeqNo, View, const std::vector<SeqNo>&)
|
||||
virtual void init_as_backup(
|
||||
ccf::SeqNo, ccf::View, const std::vector<ccf::SeqNo>&)
|
||||
{
|
||||
state = Backup;
|
||||
}
|
||||
|
||||
virtual bool replicate(const BatchVector& entries, View view) = 0;
|
||||
virtual std::pair<View, SeqNo> get_committed_txid() = 0;
|
||||
virtual bool replicate(const BatchVector& entries, ccf::View view) = 0;
|
||||
virtual std::pair<ccf::View, ccf::SeqNo> get_committed_txid() = 0;
|
||||
|
||||
struct SignableTxIndices
|
||||
{
|
||||
Term term;
|
||||
SeqNo version, previous_version;
|
||||
ccf::SeqNo version, previous_version;
|
||||
};
|
||||
|
||||
virtual std::optional<SignableTxIndices> get_signable_txid() = 0;
|
||||
|
||||
virtual View get_view(SeqNo seqno) = 0;
|
||||
virtual View get_view() = 0;
|
||||
virtual std::vector<SeqNo> get_view_history(SeqNo) = 0;
|
||||
virtual void initialise_view_history(const std::vector<SeqNo>&) = 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<ccf::SeqNo> get_view_history(ccf::SeqNo) = 0;
|
||||
virtual void initialise_view_history(const std::vector<ccf::SeqNo>&) = 0;
|
||||
virtual ccf::SeqNo get_committed_seqno() = 0;
|
||||
virtual std::optional<NodeId> primary() = 0;
|
||||
virtual bool view_change_in_progress() = 0;
|
||||
virtual std::set<NodeId> active_nodes() = 0;
|
||||
|
|
|
@ -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<DeletableVersion>::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<SpinLock> vguard(version_lock);
|
||||
|
|
|
@ -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<TxInfo> 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<TxInfo> 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<TxInfo> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<View, SeqNo> get_committed_txid() override
|
||||
std::pair<ccf::View, ccf::SeqNo> 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<SeqNo> get_view_history(SeqNo seqno) override
|
||||
std::vector<ccf::SeqNo> get_view_history(ccf::SeqNo seqno) override
|
||||
{
|
||||
return view_history.get_history_until(seqno);
|
||||
}
|
||||
|
||||
void initialise_view_history(
|
||||
const std::vector<SeqNo>& view_history_) override
|
||||
const std::vector<ccf::SeqNo>& 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;
|
||||
}
|
||||
|
|
24
src/kv/tx.h
24
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<Version> 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<THandle>(*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<THandle>(
|
||||
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;
|
||||
|
|
|
@ -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<kv::Version>(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<kv::Version>(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<kv::Version>(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<DeletableVersion>(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_, {}});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<NodeSignature> 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_)
|
||||
|
|
|
@ -20,13 +20,13 @@
|
|||
|
||||
namespace ccf
|
||||
{
|
||||
using SeqNo = uint64_t;
|
||||
using GcmHdr = crypto::GcmHeader<sizeof(SeqNo)>;
|
||||
using SendNonce = uint64_t;
|
||||
using GcmHdr = crypto::GcmHeader<sizeof(SendNonce)>;
|
||||
|
||||
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<crypto::KeyAesGcm> next_key;
|
||||
|
||||
// Incremented for each tagged/encrypted message
|
||||
std::atomic<SeqNo> send_nonce{1};
|
||||
std::atomic<SendNonce> 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<ChannelSeqno, threading::ThreadMessaging::max_num_threads>
|
||||
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;
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
|
||||
namespace ccf
|
||||
{
|
||||
using Index = int64_t;
|
||||
using Node2NodeMsg = uint64_t;
|
||||
|
||||
using Cert = std::vector<uint8_t>;
|
||||
|
|
|
@ -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<StoreDetails>;
|
||||
|
||||
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<StoreDetailsPtr> 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<std::pair<kv::SeqNo, StoreDetailsPtr>> supporting_signature;
|
||||
std::optional<std::pair<ccf::SeqNo, StoreDetailsPtr>>
|
||||
supporting_signature;
|
||||
|
||||
// Only set when recovering ledger secrets
|
||||
std::unique_ptr<LedgerSecretRecoveryInfo> 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<kv::SeqNo> adjust_range(
|
||||
kv::SeqNo start_seqno, size_t num_following_indices)
|
||||
std::set<ccf::SeqNo> 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<kv::SeqNo> ret;
|
||||
std::set<ccf::SeqNo> ret;
|
||||
std::vector<StoreDetailsPtr> new_stores(num_following_indices + 1);
|
||||
for (auto seqno = start_seqno; seqno <=
|
||||
static_cast<kv::SeqNo>(start_seqno + num_following_indices);
|
||||
static_cast<ccf::SeqNo>(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<RequestHandle, Request> requests;
|
||||
|
||||
std::set<kv::SeqNo> pending_fetches;
|
||||
std::set<ccf::SeqNo> 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<LedgerSecretRecoveryInfo> 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<StatePtr> 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<StatePtr> trusted_states;
|
||||
|
||||
for (kv::SeqNo seqno = start_seqno;
|
||||
seqno <= static_cast<kv::SeqNo>(start_seqno + num_following_indices);
|
||||
for (ccf::SeqNo seqno = start_seqno; seqno <=
|
||||
static_cast<ccf::SeqNo>(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<StorePtr> 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<StorePtr> 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<SpinLock> 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<SpinLock> guard(requests_lock);
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ namespace ccf
|
|||
std::shared_ptr<ProgressTrackerStore> store;
|
||||
|
||||
kv::TxHistory::Result add_signature(
|
||||
kv::TxID tx_id,
|
||||
ccf::TxID tx_id,
|
||||
const NodeId& node_id,
|
||||
uint32_t signature_size,
|
||||
std::array<uint8_t, MBEDTLS_ECDSA_MAX_LEN>& 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<uint8_t>& 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<NodeId, BftNodeSignature>(node_id, bft_node_sig));
|
||||
|
||||
certificates.insert(
|
||||
std::pair<kv::Consensus::SeqNo, CommitCert>(tx_id.version, cert));
|
||||
std::pair<ccf::SeqNo, CommitCert>(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<NodeId, BftNodeSignature>(node_id, bft_node_sig));
|
||||
|
@ -150,16 +150,16 @@ namespace ccf
|
|||
}
|
||||
|
||||
kv::TxHistory::Result record_primary_signature(
|
||||
kv::TxID tx_id, std::vector<uint8_t>& sig)
|
||||
ccf::TxID tx_id, std::vector<uint8_t>& sig)
|
||||
{
|
||||
std::unique_lock<SpinLock> 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<SpinLock> guard(lock);
|
||||
std::optional<ccf::BackupSignatures> 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<SpinLock> 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<kv::Consensus::SeqNo, CommitCert>(
|
||||
tx_id.version, CommitCert()));
|
||||
auto r = certificates.insert(
|
||||
std::pair<ccf::SeqNo, CommitCert>(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<SpinLock> 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<kv::Consensus::SeqNo, CommitCert>(
|
||||
tx_id.version, CommitCert()));
|
||||
auto r = certificates.insert(
|
||||
std::pair<ccf::SeqNo, CommitCert>(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<SpinLock> 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<std::unique_ptr<ViewChangeRequest>, kv::Consensus::SeqNo>
|
||||
get_view_change_message(kv::Consensus::View view)
|
||||
std::tuple<std::unique_ptr<ViewChangeRequest>, ccf::SeqNo>
|
||||
get_view_change_message(ccf::View view)
|
||||
{
|
||||
std::unique_lock<SpinLock> 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<SpinLock> 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<SpinLock> 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<SpinLock> guard(lock);
|
||||
return get_node_nonce_(tx_id);
|
||||
|
@ -634,14 +632,14 @@ namespace ccf
|
|||
private:
|
||||
NodeId id;
|
||||
std::shared_ptr<crypto::Entropy> 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<kv::Consensus::SeqNo, CommitCert> certificates;
|
||||
std::map<ccf::SeqNo, CommitCert> 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<uint8_t, MBEDTLS_ECDSA_MAX_LEN>& 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<kv::Consensus::SeqNo, CommitCert>(
|
||||
tx_id.version, CommitCert()));
|
||||
auto r = certificates.insert(
|
||||
std::pair<ccf::SeqNo, CommitCert>(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<NodeId, BftNodeSignature>(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)
|
||||
{
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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<SpinLock> guard(lock);
|
||||
if (seqno > seqno_last_signature)
|
||||
|
@ -134,7 +133,7 @@ namespace aft
|
|||
}
|
||||
}
|
||||
|
||||
std::tuple<kv::Consensus::SeqNo, std::chrono::milliseconds>
|
||||
std::tuple<ccf::SeqNo, std::chrono::milliseconds>
|
||||
get_seqno_time_last_request() const
|
||||
{
|
||||
std::unique_lock<SpinLock> guard(lock);
|
||||
|
@ -159,7 +158,7 @@ namespace aft
|
|||
snmalloc::DLList<Request, std::nullptr_t, true>
|
||||
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;
|
||||
|
|
|
@ -54,7 +54,7 @@ namespace ccf
|
|||
struct Out
|
||||
{
|
||||
ServiceStatus service_status;
|
||||
std::optional<kv::Consensus::View> current_view;
|
||||
std::optional<ccf::View> current_view;
|
||||
std::optional<NodeId> primary_id;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -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<enclave::RpcContext> 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<enclave::RpcContext> 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
|
||||
|
|
|
@ -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<historical::StorePtr> 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<historical::StorePtr> get_store_range(
|
||||
historical::RequestHandle handle,
|
||||
kv::SeqNo start_seqno,
|
||||
kv::SeqNo end_seqno)
|
||||
ccf::SeqNo start_seqno,
|
||||
ccf::SeqNo end_seqno)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
|
|
@ -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<int64_t>::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;
|
||||
|
|
|
@ -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<uint8_t>& sig_) :
|
||||
|
|
|
@ -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<kv::SeqNo, std::vector<uint8_t>> construct_host_ledger(
|
||||
std::map<ccf::SeqNo, std::vector<uint8_t>> construct_host_ledger(
|
||||
std::shared_ptr<kv::Consensus> c)
|
||||
{
|
||||
auto consensus = dynamic_cast<kv::test::StubConsensus*>(c.get());
|
||||
REQUIRE(consensus != nullptr);
|
||||
|
||||
INFO("Rebuild ledger as seen by host");
|
||||
std::map<kv::SeqNo, std::vector<uint8_t>> ledger;
|
||||
std::map<ccf::SeqNo, std::vector<uint8_t>> 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<kv::SeqNo> expected{low_seqno, high_seqno, unsigned_seqno};
|
||||
std::set<kv::SeqNo> actual;
|
||||
std::set<ccf::SeqNo> expected{low_seqno, high_seqno, unsigned_seqno};
|
||||
std::set<ccf::SeqNo> actual;
|
||||
for (const auto& write : stub_writer->writes)
|
||||
{
|
||||
const uint8_t* data = write.contents.data();
|
||||
|
|
|
@ -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<View, SeqNo> get_committed_txid() override
|
||||
std::pair<ccf::View, ccf::SeqNo> 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<View, SeqNo> get_committed_txid() override
|
||||
std::pair<ccf::View, ccf::SeqNo> 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<View, SeqNo> get_committed_txid() override
|
||||
std::pair<ccf::View, ccf::SeqNo> 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;
|
||||
}
|
||||
|
|
|
@ -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<ccf::ProgressTracker>& 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<uint8_t> 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");
|
||||
|
|
|
@ -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<uint8_t> signature;
|
||||
|
||||
std::map<NodeId, ViewChangeRequest> 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_)
|
||||
{}
|
||||
|
|
Загрузка…
Ссылка в новой задаче