diff --git a/libraries/chain/finality/finalizer.cpp b/libraries/chain/finality/finalizer.cpp index 9e39fc82d1..5a2ec84004 100644 --- a/libraries/chain/finality/finalizer.cpp +++ b/libraries/chain/finality/finalizer.cpp @@ -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(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(bsp->id(), decision == vote_decision::strong_vote, pub_key, sig); + } FC_LOG_AND_DROP() // bls_signature can throw if invalid signature } return {}; } @@ -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); @@ -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; } // ---------------------------------------------------------------------------------------- @@ -268,7 +269,9 @@ 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; } @@ -276,16 +279,10 @@ my_finalizers_t::fsi_map my_finalizers_t::load_finalizer_safety_info() { 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); @@ -373,6 +370,8 @@ void my_finalizers_t::set_keys(const std::map& 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()) diff --git a/libraries/chain/include/eosio/chain/finality/finalizer.hpp b/libraries/chain/include/eosio/chain/finality/finalizer.hpp index e43139dca3..5c4e8fff96 100644 --- a/libraries/chain/include/eosio/chain/finality/finalizer.hpp +++ b/libraries/chain/include/eosio/chain/finality/finalizer.hpp @@ -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(process_vote)(vote); + if (save_finalizer_safety_info()) { + g.unlock(); + for (const auto& vote : votes) + std::forward(process_vote)(vote); + } } } @@ -172,12 +173,13 @@ namespace eosio::chain { return std::ranges::any_of(std::views::keys(finalizers), std::forward(f)); } + void set_default_safety_information(const fsi_t& fsi); + /// only call on startup void set_keys(const std::map& 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 @@ -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); - }; }