Skip to content

Commit

Permalink
Merge branch 'hotstuff_integration' into GH-2189-trx-finality-fork-test
Browse files Browse the repository at this point in the history
  • Loading branch information
heifner authored Feb 7, 2024
2 parents e7a5b19 + 47cbaf2 commit 63e8b62
Show file tree
Hide file tree
Showing 18 changed files with 371 additions and 95 deletions.
3 changes: 3 additions & 0 deletions libraries/chain/block_state.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ block_state::block_state(const block_state_legacy& bsp) {
const auto& if_extension = std::get<instant_finality_extension>(*ext);
assert(if_extension.new_finalizer_policy); // required by current transition mechanism
active_finalizer_policy = std::make_shared<finalizer_policy>(*if_extension.new_finalizer_policy);
// TODO: https://github.com/AntelopeIO/leap/issues/2057
// TODO: Do not aggregate votes on blocks created from block_state_legacy. This can be removed when #2057 complete.
pending_qc = pending_quorum_certificate{active_finalizer_policy->finalizers.size(), active_finalizer_policy->threshold, active_finalizer_policy->max_weak_sum_before_weak_final()};
active_proposer_policy = std::make_shared<proposer_policy>();
active_proposer_policy->active_time = bsp.timestamp();
active_proposer_policy->proposer_schedule = bsp.active_schedule;
Expand Down
7 changes: 6 additions & 1 deletion libraries/chain/controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3006,7 +3006,12 @@ struct controller_impl {
return bsp->aggregate_vote(vote);
return {vote_status::unknown_block, {}};
};
auto [status, new_lib] = fork_db.apply_if<std::pair<vote_status, std::optional<uint32_t>>>(do_vote);
// TODO: https://github.com/AntelopeIO/leap/issues/2057
// TODO: Do not aggregate votes on block_state if in legacy block fork_db
auto do_vote_legacy = [](auto&) -> std::pair<vote_status, std::optional<uint32_t>> {
return {vote_status::unknown_block, {}};
};
auto [status, new_lib] = fork_db.apply<std::pair<vote_status, std::optional<uint32_t>>>(do_vote_legacy, do_vote);
if (new_lib) {
set_if_irreversible_block_num(*new_lib);
}
Expand Down
30 changes: 1 addition & 29 deletions libraries/chain/hotstuff/hotstuff.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,6 @@ valid_quorum_certificate pending_quorum_certificate::to_valid_quorum_certificate

valid_quorum_certificate valid_qc;

valid_qc._proposal_id = _proposal_id;
valid_qc._proposal_digest = _proposal_digest;
if( _state == state_t::strong ) {
valid_qc._strong_votes = _strong_votes._bitset;
valid_qc._sig = _strong_votes._sig;
Expand All @@ -155,41 +153,15 @@ valid_quorum_certificate pending_quorum_certificate::to_valid_quorum_certificate
return valid_qc;
}

// ================== begin compatibility functions =======================
// these are present just to make the tests still work. will be removed.
// these assume *only* strong votes.
quorum_certificate_message pending_quorum_certificate::to_msg() const {
return {.proposal_id = _proposal_id,
.strong_votes = bitset_to_vector(_strong_votes._bitset),
.active_agg_sig = _strong_votes._sig};
}

std::string pending_quorum_certificate::get_votes_string() const {
return std::string("strong(\"") + bitset_to_string(_strong_votes._bitset) + "\", weak(\"" +
bitset_to_string(_weak_votes._bitset) + "\"";
}
// ================== end compatibility functions =======================

valid_quorum_certificate::valid_quorum_certificate(
const fc::sha256& proposal_id, const std::vector<uint8_t>& proposal_digest,
const std::vector<uint32_t>& strong_votes, // bitset encoding, following canonical order
const std::vector<uint32_t>& weak_votes, // bitset encoding, following canonical order
const bls_signature& sig)
: _proposal_id(proposal_id)
, _proposal_digest(proposal_digest)
, _sig(sig) {
: _sig(sig) {
if (!strong_votes.empty())
_strong_votes = vector_to_bitset(strong_votes);
if (!weak_votes.empty())
_weak_votes = vector_to_bitset(weak_votes);
}

quorum_certificate_message valid_quorum_certificate::to_msg() const {
return {
.proposal_id = _proposal_id,
.strong_votes = _strong_votes ? bitset_to_vector(*_strong_votes) : std::vector<uint32_t>{1, 0},
.active_agg_sig = _sig
};
}

} // namespace eosio::chain
2 changes: 1 addition & 1 deletion libraries/chain/include/eosio/chain/block_state.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,4 @@ using block_state_ptr = std::shared_ptr<block_state>;
} // namespace eosio::chain

// not exporting pending_qc or valid_qc
FC_REFLECT_DERIVED( eosio::chain::block_state, (eosio::chain::block_header_state), (block)(validated)(strong_digest)(weak_digest) )
FC_REFLECT_DERIVED( eosio::chain::block_state, (eosio::chain::block_header_state), (block)(validated)(strong_digest)(weak_digest)(pending_qc)(valid_qc) )
33 changes: 7 additions & 26 deletions libraries/chain/include/eosio/chain/hotstuff/hotstuff.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,9 +107,7 @@ namespace eosio::chain {
// -------------------- valid_quorum_certificate -------------------------------------------------
class valid_quorum_certificate {
public:
valid_quorum_certificate(const fc::sha256& proposal_id,
const std::vector<uint8_t>& proposal_digest,
const std::vector<uint32_t>& strong_votes, //bitset encoding, following canonical order
valid_quorum_certificate(const std::vector<uint32_t>& strong_votes, //bitset encoding, following canonical order
const std::vector<uint32_t>& weak_votes, //bitset encoding, following canonical order
const bls_signature& sig);

Expand All @@ -119,16 +117,7 @@ namespace eosio::chain {
bool is_weak() const { return !!_weak_votes; }
bool is_strong() const { return !_weak_votes; }

// ================== begin compatibility functions =======================
// these are present just to make the tests still work. will be removed.
// these assume *only* strong votes.
quorum_certificate_message to_msg() const;
const fc::sha256& get_proposal_id() const { return _proposal_id; }
// ================== end compatibility functions =======================

friend struct fc::reflector<valid_quorum_certificate>;
fc::sha256 _proposal_id; // [todo] remove
std::vector<uint8_t> _proposal_digest; // [todo] remove
std::optional<hs_bitset> _strong_votes;
std::optional<hs_bitset> _weak_votes;
bls_signature _sig;
Expand Down Expand Up @@ -174,28 +163,18 @@ namespace eosio::chain {

// thread safe
std::pair<vote_status, bool> add_vote(bool strong,
const std::vector<uint8_t>&proposal_digest,
const std::vector<uint8_t>& proposal_digest,
size_t index,
const bls_public_key&pubkey,
const bls_signature&sig,
const bls_public_key& pubkey,
const bls_signature& sig,
uint64_t weight);

state_t state() const { std::lock_guard g(*_mtx); return _state; };
valid_quorum_certificate to_valid_quorum_certificate() const;

// ================== begin compatibility functions =======================
// these are present just to make the tests still work. will be removed.
// these assume *only* strong votes.
quorum_certificate_message to_msg() const;
const fc::sha256& get_proposal_id() const { return _proposal_id; }
std::string get_votes_string() const;
// ================== end compatibility functions =======================

private:
friend struct fc::reflector<pending_quorum_certificate>;
friend class qc_chain;
fc::sha256 _proposal_id; // only used in to_msg(). Remove eventually
std::vector<uint8_t> _proposal_digest;
std::unique_ptr<std::mutex> _mtx;
uint64_t _quorum {0};
uint64_t _max_weak_sum_before_weak_final {0}; // max weak sum before becoming weak_final
Expand Down Expand Up @@ -228,5 +207,7 @@ FC_REFLECT(eosio::chain::vote_message, (proposal_id)(strong)(finalizer_key)(sig)
FC_REFLECT(eosio::chain::hs_proposal_message, (proposal_id)(block_id)(parent_id)(final_on_qc)(justify)(phase_counter));
FC_REFLECT(eosio::chain::hs_new_view_message, (high_qc));
FC_REFLECT(eosio::chain::hs_message, (msg));
FC_REFLECT(eosio::chain::valid_quorum_certificate, (_proposal_id)(_proposal_digest)(_strong_votes)(_weak_votes)(_sig));
FC_REFLECT(eosio::chain::valid_quorum_certificate, (_strong_votes)(_weak_votes)(_sig));
FC_REFLECT(eosio::chain::pending_quorum_certificate, (_quorum)(_max_weak_sum_before_weak_final)(_state)(_strong_sum)(_weak_sum)(_weak_votes)(_strong_votes));
FC_REFLECT(eosio::chain::pending_quorum_certificate::votes_t, (_bitset)(_sig));
FC_REFLECT(eosio::chain::quorum_certificate, (block_num)(qc));
2 changes: 1 addition & 1 deletion libraries/chainbase
4 changes: 2 additions & 2 deletions plugins/http_plugin/http_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -357,9 +357,9 @@ namespace eosio {
("max-body-size", bpo::value<uint32_t>()->default_value(my->plugin_state->max_body_size),
"The maximum body size in bytes allowed for incoming RPC requests")
("http-max-bytes-in-flight-mb", bpo::value<int64_t>()->default_value(500),
"Maximum size in megabytes http_plugin should use for processing http requests. -1 for unlimited. 429 error response when exceeded." )
"Maximum size in megabytes http_plugin should use for processing http requests. -1 for unlimited. 503 error response when exceeded." )
("http-max-in-flight-requests", bpo::value<int32_t>()->default_value(-1),
"Maximum number of requests http_plugin should use for processing http requests. 429 error response when exceeded." )
"Maximum number of requests http_plugin should use for processing http requests. 503 error response when exceeded." )
("http-max-response-time-ms", bpo::value<int64_t>()->default_value(15),
"Maximum time on main thread for processing a request, -1 for unlimited")
("verbose-http-errors", bpo::bool_switch()->default_value(false),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -219,18 +219,18 @@ class beast_http_session : public detail::abstract_conn,

virtual void send_busy_response(std::string&& what) final {
error_results::error_info ei;
ei.code = static_cast<int64_t>(http::status::too_many_requests);
ei.code = static_cast<int64_t>(http::status::service_unavailable);
ei.name = "Busy";
ei.what = std::move(what);
error_results results{static_cast<uint16_t>(http::status::too_many_requests), "Busy", ei};
error_results results{static_cast<uint16_t>(http::status::service_unavailable), "Busy", ei};
send_response(fc::json::to_string(results, fc::time_point::maximum()),
static_cast<unsigned int>(http::status::too_many_requests) );
static_cast<unsigned int>(http::status::service_unavailable) );
}

virtual std::string verify_max_bytes_in_flight(size_t extra_bytes) final {
auto bytes_in_flight_size = plugin_state_->bytes_in_flight.load() + extra_bytes;
if(bytes_in_flight_size > plugin_state_->max_bytes_in_flight) {
fc_dlog(plugin_state_->get_logger(), "429 - too many bytes in flight: ${bytes}", ("bytes", bytes_in_flight_size));
fc_dlog(plugin_state_->get_logger(), "503 - too many bytes in flight: ${bytes}", ("bytes", bytes_in_flight_size));
return "Too many bytes in flight: " + std::to_string( bytes_in_flight_size );
}
return {};
Expand All @@ -242,7 +242,7 @@ class beast_http_session : public detail::abstract_conn,

auto requests_in_flight_num = plugin_state_->requests_in_flight.load();
if(requests_in_flight_num > plugin_state_->max_requests_in_flight) {
fc_dlog(plugin_state_->get_logger(), "429 - too many requests in flight: ${requests}", ("requests", requests_in_flight_num));
fc_dlog(plugin_state_->get_logger(), "503 - too many requests in flight: ${requests}", ("requests", requests_in_flight_num));
return "Too many requests in flight: " + std::to_string( requests_in_flight_num );
}
return {};
Expand Down Expand Up @@ -492,8 +492,9 @@ class beast_http_session : public detail::abstract_conn,

void run_session() {
if(auto error_str = verify_max_requests_in_flight(); !error_str.empty()) {
res_->keep_alive(false);
send_busy_response(std::move(error_str));
return do_eof();
return;
}

do_read_header();
Expand Down
3 changes: 2 additions & 1 deletion plugins/http_plugin/include/eosio/http_plugin/common.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -161,13 +161,14 @@ inline auto make_http_response_handler(http_plugin_state& plugin_state, detail::
// post back to an HTTP thread to allow the response handler to be called from any thread
boost::asio::dispatch(plugin_state.thread_pool.get_executor(),
[&plugin_state, session_ptr{std::move(session_ptr)}, code, payload_size, response = std::move(response), content_type]() {
auto on_exit = fc::scoped_exit<std::function<void()>>([&](){plugin_state.bytes_in_flight -= payload_size;});

if(auto error_str = session_ptr->verify_max_bytes_in_flight(0); !error_str.empty()) {
session_ptr->send_busy_response(std::move(error_str));
return;
}

try {
plugin_state.bytes_in_flight -= payload_size;
if (response.has_value()) {
std::string json = (content_type == http_content_type::plaintext) ? response->as_string() : fc::json::to_string(*response, fc::time_point::maximum());
if (auto error_str = session_ptr->verify_max_bytes_in_flight(json.size()); error_str.empty())
Expand Down
1 change: 1 addition & 0 deletions plugins/http_plugin/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ target_include_directories( http_plugin_unit_tests PUBLIC
${CMAKE_SOURCE_DIR}/plugins/http_plugin/include )

add_test( NAME http_plugin_unit_tests COMMAND http_plugin_unit_tests )
set_property(TEST http_plugin_unit_tests PROPERTY LABELS nonparallelizable_tests)
Loading

0 comments on commit 63e8b62

Please sign in to comment.