diff --git a/libraries/chain/block_state.cpp b/libraries/chain/block_state.cpp index b750e68292..c2c7ed92f7 100644 --- a/libraries/chain/block_state.cpp +++ b/libraries/chain/block_state.cpp @@ -53,5 +53,33 @@ void block_state::set_trxs_metas( deque&& trxs_metas, cached_trxs = std::move( trxs_metas ); } - +std::optional block_state::get_best_qc() const { + auto block_number = block_num(); + + // if pending_qc does not have a valid QC, consider valid_qc only + if( !pending_qc.is_quorum_met() ) { + if( valid_qc ) { + return quorum_certificate{ block_number, *valid_qc }; + } else { + return std::nullopt;; + } + } + +#warning TODO valid_quorum_certificate constructor can assert. Implement an extract method in pending_quorum_certificate for this. + // extract valid QC from pending_qc + valid_quorum_certificate valid_qc_from_pending(pending_qc); + + // if valid_qc does not have value, consider valid_qc_from_pending only + if( !valid_qc ) { + return quorum_certificate{ block_number, valid_qc_from_pending }; + } + + // Both valid_qc and valid_qc_from_pending have value. Compare them and select a better one. + // Strong beats weak. Tie break by valid_qc. + const auto& best_qc = + valid_qc->is_strong() == valid_qc_from_pending.is_strong() ? + *valid_qc : // tie broke by valid_qc + valid_qc->is_strong() ? *valid_qc : valid_qc_from_pending; // strong beats weak + return quorum_certificate{ block_number, best_qc }; +} } /// eosio::chain diff --git a/libraries/chain/hotstuff/hotstuff.cpp b/libraries/chain/hotstuff/hotstuff.cpp index 91dc48ff67..c9a498c9ad 100644 --- a/libraries/chain/hotstuff/hotstuff.cpp +++ b/libraries/chain/hotstuff/hotstuff.cpp @@ -192,4 +192,4 @@ quorum_certificate_message valid_quorum_certificate::to_msg() const { }; } -} // namespace eosio::chain \ No newline at end of file +} // namespace eosio::chain diff --git a/libraries/chain/include/eosio/chain/block_state.hpp b/libraries/chain/include/eosio/chain/block_state.hpp index ff48e4fb5e..26c3883ff7 100644 --- a/libraries/chain/include/eosio/chain/block_state.hpp +++ b/libraries/chain/include/eosio/chain/block_state.hpp @@ -17,8 +17,7 @@ struct block_state : public block_header_state { // block_header_state provi digest_type weak_digest; // finalizer_digest (weak, cached so we can quickly validate votes) pending_quorum_certificate pending_qc; // where we accumulate votes we receive std::optional valid_qc; // best qc received from the network inside block extension - - + // ------ data members caching information available elsewhere ---------------------- bool pub_keys_recovered = false; deque cached_trxs; @@ -32,6 +31,7 @@ struct block_state : public block_header_state { // block_header_state provi bool is_valid() const { return validated; } void set_valid(bool b) { validated = b; } uint32_t irreversible_blocknum() const { return 0; } // [greg todo] equivalent of dpos_irreversible_blocknum + std::optional get_best_qc() const; protocol_feature_activation_set_ptr get_activated_protocol_features() const { return block_header_state::activated_protocol_features; } bool is_pub_keys_recovered() const { return pub_keys_recovered; }