Skip to content

Commit

Permalink
Merge pull request #663 from AntelopeIO/GH-646-safety-file-exceptions…
Browse files Browse the repository at this point in the history
…-main

[1.0 -> main] Improve finalizer safety file exception handling
  • Loading branch information
heifner authored Aug 28, 2024
2 parents 9d65146 + 3b0dce3 commit 4b76e91
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 37 deletions.
59 changes: 29 additions & 30 deletions libraries/chain/finality/finalizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,15 +119,17 @@ vote_message_ptr finalizer::maybe_vote(const bls_public_key& pub_key,
const digest_type& digest) {
finalizer::vote_decision decision = decide_vote(bsp).decision;
if (decision == vote_decision::strong_vote || decision == vote_decision::weak_vote) {
bls_signature sig;
if (decision == vote_decision::weak_vote) {
// if voting weak, the digest to sign should be a hash of the concatenation of the finalizer_digest
// and the string "WEAK"
sig = priv_key.sign(create_weak_digest(digest));
} else {
sig = priv_key.sign({(uint8_t*)digest.data(), (uint8_t*)digest.data() + digest.data_size()});
}
return std::make_shared<vote_message>(bsp->id(), decision == vote_decision::strong_vote, pub_key, sig);
try {
bls_signature sig;
if (decision == vote_decision::weak_vote) {
// if voting weak, the digest to sign should be a hash of the concatenation of the finalizer_digest
// and the string "WEAK"
sig = priv_key.sign(create_weak_digest(digest));
} else {
sig = priv_key.sign({(uint8_t*)digest.data(), (uint8_t*)digest.data() + digest.data_size()});
}
return std::make_shared<vote_message>(bsp->id(), decision == vote_decision::strong_vote, pub_key, sig);
} FC_LOG_AND_DROP() // bls_signature can throw if invalid signature
}
return {};
}
Expand Down Expand Up @@ -175,17 +177,14 @@ void my_finalizers_t::maybe_update_fsi(const block_state_ptr& bsp, const qc_t& r
}
}

void my_finalizers_t::save_finalizer_safety_info() const {

if (!cfile_ds.is_open()) {
EOS_ASSERT(!persist_file_path.empty(), finalizer_safety_exception,
"path for storing finalizer safety information file not specified");
if (!std::filesystem::exists(persist_file_path.parent_path()))
std::filesystem::create_directories(persist_file_path.parent_path());
cfile_ds.set_file_path(persist_file_path);
cfile_ds.open(fc::cfile::truncate_rw_mode);
}
bool my_finalizers_t::save_finalizer_safety_info() const {
try {
if (!cfile_ds.is_open()) {
EOS_ASSERT(!persist_file_path.empty(), finalizer_safety_exception,
"path for storing finalizer safety information file not specified");
cfile_ds.set_file_path(persist_file_path);
cfile_ds.open(fc::cfile::truncate_rw_mode);
}
// optimize by only calculating crc for inactive once
if (inactive_safety_info_written_pos == 0) {
persist_file.seekp(0);
Expand Down Expand Up @@ -216,7 +215,9 @@ void my_finalizers_t::save_finalizer_safety_info() const {
fc::raw::pack(persist_file, cs);

cfile_ds.flush();
} FC_LOG_AND_RETHROW()
return true;
} FC_LOG_AND_DROP()
return false;
}

// ----------------------------------------------------------------------------------------
Expand Down Expand Up @@ -268,24 +269,20 @@ my_finalizers_t::fsi_map my_finalizers_t::load_finalizer_safety_info() {
("p", persist_file_path));

if (!std::filesystem::exists(persist_file_path)) {
fc_ilog(vote_logger, "unable to open finalizer safety persistence file ${p}, file doesn't exist (which is expected on the first use of a BLS finalizer key)",
if (!std::filesystem::exists(persist_file_path.parent_path()))
std::filesystem::create_directories(persist_file_path.parent_path());
fc_ilog(vote_logger, "finalizer safety persistence file ${p} does not exist (which is expected on the first use of a BLS finalizer key)",
("p", persist_file_path));
return res;
}

cfile_ds.set_file_path(persist_file_path);

try {
// if we can't open the finalizer safety file, we return an empty map.
// if we can't open the finalizer safety file on startup, throw exception so producer_plugin startup fails
cfile_ds.open(fc::cfile::update_rw_mode);
} catch(std::exception& e) {
fc_elog(vote_logger, "unable to open finalizer safety persistence file ${p}, using defaults. Exception: ${e}",
("p", persist_file_path)("e", e.what()));
return res;
} catch(...) {
fc_elog(vote_logger, "unable to open finalizer safety persistence file ${p}, using defaults", ("p", persist_file_path));
return res;
}
} FC_RETHROW_EXCEPTIONS(log_level::error, "unable to open finalizer safety persistence file ${p}", ("p", persist_file_path))

try {
persist_file.seekp(0);

Expand Down Expand Up @@ -373,6 +370,8 @@ void my_finalizers_t::set_keys(const std::map<std::string, std::string>& finaliz
// possible, and allow for liveness which will allow the finalizers to eventually vote.
// --------------------------------------------------------------------------------------------
void my_finalizers_t::set_default_safety_information(const fsi_t& fsi) {
std::lock_guard g(mtx);

for (auto& [pub_key, f] : finalizers) {
// update only finalizers which are uninitialized
if (!f.fsi.last_vote.empty() || !f.fsi.lock.empty())
Expand Down
15 changes: 8 additions & 7 deletions libraries/chain/include/eosio/chain/finality/finalizer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -148,11 +148,12 @@ namespace eosio::chain {

// then save the safety info and, if successful, gossip the votes
if (!votes.empty()) {
save_finalizer_safety_info();
g.unlock();
has_voted.store(true, std::memory_order::relaxed);
for (const auto& vote : votes)
std::forward<F>(process_vote)(vote);
if (save_finalizer_safety_info()) {
g.unlock();
for (const auto& vote : votes)
std::forward<F>(process_vote)(vote);
}
}
}

Expand All @@ -172,12 +173,13 @@ namespace eosio::chain {
return std::ranges::any_of(std::views::keys(finalizers), std::forward<F>(f));
}

void set_default_safety_information(const fsi_t& fsi);

/// only call on startup
void set_keys(const std::map<std::string, std::string>& finalizer_keys);
void set_default_safety_information(const fsi_t& fsi);

// following two member functions could be private, but are used in testing, not thread safe
void save_finalizer_safety_info() const;
bool save_finalizer_safety_info() const;
fsi_map load_finalizer_safety_info();

// for testing purposes only, not thread safe
Expand All @@ -187,7 +189,6 @@ namespace eosio::chain {
private:
void load_finalizer_safety_info_v0(fsi_map& res);
void load_finalizer_safety_info_v1(fsi_map& res);

};

}
Expand Down

0 comments on commit 4b76e91

Please sign in to comment.