-
Notifications
You must be signed in to change notification settings - Fork 217
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Update snapshot commit rules #1972
Merged
Merged
Changes from 8 commits
Commits
Show all changes
19 commits
Select commit
Hold shift + click to select a range
04c6865
Snapshot is committed only when evidence proof is committed
ea3500d
Include evidence commit idx on snapshot file name
549b2cb
Host only picks snapshot with committed evidence
d222aa9
Merge remote-tracking branch 'upstream/master' into snapshot_commit_a…
f682c0a
Docs
cffaf59
from_chars
5306c04
Revert change to infra
d0d1acd
Cleanup before PR
9e04000
Merge branch 'master' into snapshot_commit_audit
achamayou 8207787
Fix build
d7368a4
Merge branch 'snapshot_commit_audit' of github.com:jumaffre/CCF into …
7a0d102
Merge branch 'master' into snapshot_commit_audit
jumaffre 7954426
WIP: infra handling of new snapshot commit scheme
c0e84d8
Reconfiguration test works
8f691c8
Update docs
e306f35
Merge branch 'master' into snapshot_commit_audit
jumaffre 1b12644
Oops
163545b
Merge branch 'snapshot_commit_audit' of github.com:jumaffre/CCF into …
71b2fc6
Import
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,7 +3,9 @@ | |
#pragma once | ||
|
||
#include "consensus/ledger_enclave_types.h" | ||
#include "host/ledger.h" | ||
|
||
#include <charconv> | ||
#include <filesystem> | ||
#include <fstream> | ||
#include <iostream> | ||
|
@@ -17,23 +19,12 @@ namespace asynchost | |
{ | ||
private: | ||
const std::string snapshot_dir; | ||
const Ledger& ledger; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The host snapshot manager now takes a reference to the ledger so that it can verify that the latest committed snapshot has a proof of evidence in the ledger. |
||
|
||
static constexpr auto snapshot_file_prefix = "snapshot"; | ||
static constexpr auto snapshot_idx_delimiter = "_"; | ||
static constexpr auto snapshot_committed_suffix = "committed"; | ||
|
||
bool is_committed_snapshot_file(const std::string& file_name) | ||
{ | ||
// Snapshot file should start with known prefix and end with committed | ||
// suffix | ||
auto pos = file_name.find(snapshot_file_prefix); | ||
if (pos == std::string::npos || pos != 0) | ||
{ | ||
return false; | ||
} | ||
return ( | ||
file_name.find(snapshot_committed_suffix, pos) != std::string::npos); | ||
} | ||
|
||
size_t get_snapshot_idx_from_file_name(const std::string& file_name) | ||
{ | ||
auto pos = file_name.find(snapshot_idx_delimiter); | ||
|
@@ -46,6 +37,81 @@ namespace asynchost | |
return std::stol(file_name.substr(pos + 1)); | ||
} | ||
|
||
std::optional<std::pair<size_t, size_t>> | ||
get_snapshot_evidence_idx_from_file_name(const std::string& file_name) | ||
{ | ||
auto pos = file_name.find( | ||
fmt::format("{}{}", snapshot_committed_suffix, snapshot_idx_delimiter)); | ||
if (pos == std::string::npos) | ||
{ | ||
// Snapshot is not yet committed | ||
return std::nullopt; | ||
} | ||
|
||
auto committed_suffix = file_name.substr(pos); | ||
auto committed_separator_pos = | ||
committed_suffix.find(snapshot_idx_delimiter); | ||
if (committed_separator_pos == std::string::npos) | ||
{ | ||
// Committed snapshot does not contain committed indices separator | ||
return std::nullopt; | ||
} | ||
|
||
auto evidence_indices = | ||
committed_suffix.substr(committed_separator_pos + 1); | ||
auto evidence_indices_separator_pos = | ||
evidence_indices.find(snapshot_idx_delimiter); | ||
if (evidence_indices_separator_pos == std::string::npos) | ||
{ | ||
// Committed snapshot does not contain evidence indices separator | ||
return std::nullopt; | ||
} | ||
|
||
size_t evidence_idx; | ||
std::string_view str_evidence_idx = | ||
evidence_indices.substr(0, evidence_indices_separator_pos); | ||
if ( | ||
std::from_chars( | ||
str_evidence_idx.data(), | ||
str_evidence_idx.data() + str_evidence_idx.size(), | ||
evidence_idx) | ||
.ec != std::errc()) | ||
{ | ||
return std::nullopt; | ||
} | ||
|
||
size_t evidence_commit_idx; | ||
std::string_view str_evidence_commit_idx = | ||
evidence_indices.substr(evidence_indices_separator_pos + 1); | ||
if ( | ||
std::from_chars( | ||
str_evidence_commit_idx.data(), | ||
str_evidence_commit_idx.data() + str_evidence_commit_idx.size(), | ||
evidence_commit_idx) | ||
.ec != std::errc()) | ||
{ | ||
return std::nullopt; | ||
} | ||
return std::make_pair(evidence_idx, evidence_commit_idx); | ||
} | ||
|
||
public: | ||
SnapshotManager(const std::string& snapshot_dir_, const Ledger& ledger_) : | ||
snapshot_dir(snapshot_dir_), | ||
ledger(ledger_) | ||
{ | ||
if (fs::is_directory(snapshot_dir)) | ||
{ | ||
LOG_INFO_FMT( | ||
"Snapshots will be stored in existing directory: {}", snapshot_dir); | ||
} | ||
else if (!fs::create_directory(snapshot_dir)) | ||
{ | ||
throw std::logic_error(fmt::format( | ||
"Error: Could not create snapshot directory: {}", snapshot_dir)); | ||
} | ||
} | ||
|
||
void write_snapshot( | ||
consensus::Index idx, const uint8_t* snapshot_data, size_t snapshot_size) | ||
{ | ||
|
@@ -72,28 +138,34 @@ namespace asynchost | |
} | ||
|
||
void commit_snapshot( | ||
consensus::Index snapshot_idx, consensus::Index evidence_idx) | ||
consensus::Index snapshot_idx, | ||
consensus::Index evidence_idx, | ||
consensus::Index evidence_commit_idx) | ||
{ | ||
// Find previously-generated snapshot for snapshot_idx and rename file, | ||
// including evidence_idx in name too | ||
// including evidence_idx and evidence_commit_idx in name too | ||
for (auto const& f : fs::directory_iterator(snapshot_dir)) | ||
{ | ||
auto file_name = f.path().filename().string(); | ||
if ( | ||
!is_committed_snapshot_file(file_name) && | ||
!get_snapshot_evidence_idx_from_file_name(file_name).has_value() && | ||
get_snapshot_idx_from_file_name(file_name) == snapshot_idx) | ||
{ | ||
LOG_INFO_FMT( | ||
"Committing snapshot file \"{}\" with evidence at {}", | ||
"Committing snapshot file \"{}\" with evidence at {} and evidence " | ||
"proof committed at {}", | ||
file_name, | ||
evidence_idx); | ||
evidence_idx, | ||
evidence_commit_idx); | ||
|
||
const auto committed_file_name = fmt::format( | ||
"{}.{}{}{}", | ||
"{}.{}{}{}{}{}", | ||
file_name, | ||
snapshot_committed_suffix, | ||
snapshot_idx_delimiter, | ||
evidence_idx); | ||
evidence_idx, | ||
snapshot_idx_delimiter, | ||
evidence_commit_idx); | ||
|
||
fs::rename( | ||
fs::path(snapshot_dir) / fs::path(file_name), | ||
|
@@ -106,41 +178,45 @@ namespace asynchost | |
LOG_FAIL_FMT("Could not find snapshot to commit at {}", snapshot_idx); | ||
} | ||
|
||
public: | ||
SnapshotManager(const std::string& snapshot_dir_) : | ||
snapshot_dir(snapshot_dir_) | ||
{ | ||
if (fs::is_directory(snapshot_dir)) | ||
{ | ||
LOG_INFO_FMT( | ||
"Snapshots will be stored in existing directory: {}", snapshot_dir); | ||
} | ||
else if (!fs::create_directory(snapshot_dir)) | ||
{ | ||
throw std::logic_error(fmt::format( | ||
"Error: Could not create snapshot directory: {}", snapshot_dir)); | ||
} | ||
} | ||
|
||
std::optional<std::string> find_latest_committed_snapshot() | ||
{ | ||
std::optional<std::string> snapshot_file = std::nullopt; | ||
size_t latest_idx = 0; | ||
|
||
size_t ledger_last_idx = ledger.get_last_idx(); | ||
|
||
for (auto& f : fs::directory_iterator(snapshot_dir)) | ||
{ | ||
auto file_name = f.path().filename().string(); | ||
auto pos = file_name.find( | ||
fmt::format("{}{}", snapshot_file_prefix, snapshot_idx_delimiter)); | ||
if (pos == std::string::npos || !is_committed_snapshot_file(file_name)) | ||
if ( | ||
file_name.find(fmt::format( | ||
"{}{}", snapshot_file_prefix, snapshot_idx_delimiter)) == | ||
std::string::npos) | ||
{ | ||
LOG_INFO_FMT("Ignoring non-snapshot file \"{}\"", file_name); | ||
continue; | ||
} | ||
|
||
auto evidence_indices = | ||
get_snapshot_evidence_idx_from_file_name(file_name); | ||
if (!evidence_indices.has_value()) | ||
{ | ||
LOG_INFO_FMT("Ignoring uncommitted snapshot file \"{}\"", file_name); | ||
continue; | ||
} | ||
|
||
if (evidence_indices->second > ledger.get_last_idx()) | ||
{ | ||
LOG_INFO_FMT( | ||
"Ignoring \"{}\" because it is not a committed snapshot file", | ||
file_name); | ||
"Ignoring \"{}\" because ledger does not contain evidence commit " | ||
"seqno: evidence commit seqno {} > last ledger seqno {}", | ||
file_name, | ||
evidence_indices->second, | ||
ledger_last_idx); | ||
continue; | ||
} | ||
|
||
pos = file_name.find(snapshot_idx_delimiter); | ||
auto pos = file_name.find(snapshot_idx_delimiter); | ||
size_t snapshot_idx = std::stol(file_name.substr(pos + 1)); | ||
if (snapshot_idx > latest_idx) | ||
{ | ||
|
@@ -167,7 +243,9 @@ namespace asynchost | |
[this](const uint8_t* data, size_t size) { | ||
auto snapshot_idx = serialized::read<consensus::Index>(data, size); | ||
auto evidence_idx = serialized::read<consensus::Index>(data, size); | ||
commit_snapshot(snapshot_idx, evidence_idx); | ||
auto evidence_commit_idx = | ||
serialized::read<consensus::Index>(data, size); | ||
commit_snapshot(snapshot_idx, evidence_idx, evidence_commit_idx); | ||
}); | ||
} | ||
}; | ||
|
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note the new
_<evidence_commit_seqno>
suffix at the end of the snapshot file name.