From f3ff3e86866caa71e16fbfdaac9218facbcec3c6 Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Thu, 11 Apr 2024 20:02:09 -0500 Subject: [PATCH] GH-3 Avoid vote_message copies by using shared_ptr --- libraries/chain/controller.cpp | 6 +- libraries/chain/hotstuff/finalizer.cpp | 8 +-- .../chain/include/eosio/chain/controller.hpp | 4 +- .../eosio/chain/hotstuff/finalizer.hpp | 9 ++- .../include/eosio/chain/hotstuff/hotstuff.hpp | 2 + .../include/eosio/chain/vote_processor.hpp | 49 +++++++------ plugins/net_plugin/net_plugin.cpp | 68 ++++++++++++------- unittests/finality_test_cluster.cpp | 24 +++---- unittests/finality_test_cluster.hpp | 4 +- 9 files changed, 96 insertions(+), 78 deletions(-) diff --git a/libraries/chain/controller.cpp b/libraries/chain/controller.cpp index 18a197ac51..0ef3788a9b 100644 --- a/libraries/chain/controller.cpp +++ b/libraries/chain/controller.cpp @@ -3567,7 +3567,7 @@ struct controller_impl { // called from net threads and controller's thread pool - void process_vote_message( uint32_t connection_id, const vote_message& vote ) { + void process_vote_message( uint32_t connection_id, const vote_message_ptr& vote ) { if (conf.vote_thread_pool_size > 0) { vote_processor.process_vote_message(connection_id, vote); } @@ -3597,7 +3597,7 @@ struct controller_impl { // Each finalizer configured on the node which is present in the active finalizer policy may create and sign a vote. my_finalizers.maybe_vote( - *bsp->active_finalizer_policy, bsp, bsp->strong_digest, [&](const vote_message& vote) { + *bsp->active_finalizer_policy, bsp, bsp->strong_digest, [&](const vote_message_ptr& vote) { // net plugin subscribed to this signal. it will broadcast the vote message on receiving the signal emit(voted_block, std::tuple{uint32_t{0}, vote_status::success, std::cref(vote)}); @@ -5259,7 +5259,7 @@ void controller::set_proposed_finalizers( finalizer_policy&& fin_pol ) { } // called from net threads -void controller::process_vote_message( uint32_t connection_id, const vote_message& vote ) { +void controller::process_vote_message( uint32_t connection_id, const vote_message_ptr& vote ) { my->process_vote_message( connection_id, vote ); }; diff --git a/libraries/chain/hotstuff/finalizer.cpp b/libraries/chain/hotstuff/finalizer.cpp index af0d3028c2..69f6e10feb 100644 --- a/libraries/chain/hotstuff/finalizer.cpp +++ b/libraries/chain/hotstuff/finalizer.cpp @@ -86,9 +86,9 @@ finalizer::vote_result finalizer::decide_vote(const block_state_ptr& bsp) { } // ---------------------------------------------------------------------------------------- -std::optional finalizer::maybe_vote(const bls_public_key& pub_key, - const block_state_ptr& bsp, - const digest_type& digest) { +vote_message_ptr finalizer::maybe_vote(const bls_public_key& pub_key, + const block_state_ptr& bsp, + 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; @@ -99,7 +99,7 @@ std::optional finalizer::maybe_vote(const bls_public_key& pub_key, } else { sig = priv_key.sign({(uint8_t*)digest.data(), (uint8_t*)digest.data() + digest.data_size()}); } - return std::optional{vote_message{ bsp->id(), decision == vote_decision::strong_vote, pub_key, sig }}; + return std::make_shared(bsp->id(), decision == vote_decision::strong_vote, pub_key, sig); } return {}; } diff --git a/libraries/chain/include/eosio/chain/controller.hpp b/libraries/chain/include/eosio/chain/controller.hpp index e4d4285b08..dcd1a18303 100644 --- a/libraries/chain/include/eosio/chain/controller.hpp +++ b/libraries/chain/include/eosio/chain/controller.hpp @@ -58,7 +58,7 @@ namespace eosio::chain { using trx_meta_cache_lookup = std::function; using block_signal_params = std::tuple; - using vote_signal_params = std::tuple; + using vote_signal_params = std::tuple; enum class db_read_mode { HEAD, @@ -328,7 +328,7 @@ namespace eosio::chain { // called by host function set_finalizers void set_proposed_finalizers( finalizer_policy&& fin_pol ); // called from net threads - void process_vote_message( uint32_t connection_id, const vote_message& msg ); + void process_vote_message( uint32_t connection_id, const vote_message_ptr& msg ); // thread safe, for testing bool node_has_voted_if_finalizer(const block_id_type& id) const; diff --git a/libraries/chain/include/eosio/chain/hotstuff/finalizer.hpp b/libraries/chain/include/eosio/chain/hotstuff/finalizer.hpp index 762524a46b..296e11eae0 100644 --- a/libraries/chain/include/eosio/chain/hotstuff/finalizer.hpp +++ b/libraries/chain/include/eosio/chain/hotstuff/finalizer.hpp @@ -61,8 +61,7 @@ namespace eosio::chain { finalizer_safety_information fsi; vote_result decide_vote(const block_state_ptr& bsp); - std::optional maybe_vote(const bls_public_key& pub_key, const block_state_ptr& bsp, - const digest_type& digest); + vote_message_ptr maybe_vote(const bls_public_key& pub_key, const block_state_ptr& bsp, const digest_type& digest); }; // ---------------------------------------------------------------------------------------- @@ -95,7 +94,7 @@ namespace eosio::chain { if (finalizers.empty()) return; - std::vector votes; + std::vector votes; votes.reserve(finalizers.size()); // Possible improvement in the future, look at locking only individual finalizers and releasing the lock for writing the file. @@ -105,9 +104,9 @@ namespace eosio::chain { // first accumulate all the votes for (const auto& f : fin_pol.finalizers) { if (auto it = finalizers.find(f.public_key); it != finalizers.end()) { - std::optional vote_msg = it->second.maybe_vote(it->first, bsp, digest); + vote_message_ptr vote_msg = it->second.maybe_vote(it->first, bsp, digest); if (vote_msg) - votes.push_back(std::move(*vote_msg)); + votes.push_back(std::move(vote_msg)); } } // then save the safety info and, if successful, gossip the votes diff --git a/libraries/chain/include/eosio/chain/hotstuff/hotstuff.hpp b/libraries/chain/include/eosio/chain/hotstuff/hotstuff.hpp index f6e2d4297f..9e8682b905 100644 --- a/libraries/chain/include/eosio/chain/hotstuff/hotstuff.hpp +++ b/libraries/chain/include/eosio/chain/hotstuff/hotstuff.hpp @@ -30,6 +30,8 @@ namespace eosio::chain { bool operator==(const vote_message&) const = default; }; + using vote_message_ptr = std::shared_ptr; + enum class vote_status { success, duplicate, // duplicate vote, expected as votes arrive on multiple connections diff --git a/libraries/chain/include/eosio/chain/vote_processor.hpp b/libraries/chain/include/eosio/chain/vote_processor.hpp index 8e529edaa6..793705acbc 100644 --- a/libraries/chain/include/eosio/chain/vote_processor.hpp +++ b/libraries/chain/include/eosio/chain/vote_processor.hpp @@ -23,17 +23,16 @@ class vote_processor_t { struct by_vote; struct vote { - uint32_t connection_id; - vote_message msg; + uint32_t connection_id; + vote_message_ptr msg; - const block_id_type& id() const { return msg.block_id; } - block_num_type block_num() const { return block_header::num_from_id(msg.block_id); } + const block_id_type& id() const { return msg->block_id; } + block_num_type block_num() const { return block_header::num_from_id(msg->block_id); } }; - using vote_ptr = std::shared_ptr; using vote_signal_type = decltype(controller({},chain_id_type::empty_chain_id()).voted_block()); - using vote_index_type = boost::multi_index_container< vote_ptr, + using vote_index_type = boost::multi_index_container< vote, indexed_by< ordered_non_unique, composite_key >, composite_key_compare< std::greater<>, sha256_less > // greater for block_num >, - ordered_non_unique< tag, member >, - ordered_unique< tag, member > + ordered_non_unique< tag, member > > >; @@ -84,7 +82,7 @@ class vote_processor_t { } } - void emit(uint32_t connection_id, vote_status status, const vote_message& msg) { + void emit(uint32_t connection_id, vote_status status, const vote_message_ptr& msg) { if (connection_id != 0) { // this nodes vote was already signaled emit( vote_signal, std::tuple{connection_id, status, std::cref(msg)} ); } @@ -102,8 +100,8 @@ class vote_processor_t { } bool remove_all_for_block(auto& idx, auto& it, const block_id_type& id) { - while (it != idx.end() && (*it)->id() == id) { - if (auto& num = num_messages[(*it)->connection_id]; num != 0) + while (it != idx.end() && it->id() == id) { + if (auto& num = num_messages[it->connection_id]; num != 0) --num; it = idx.erase(it); @@ -112,7 +110,7 @@ class vote_processor_t { } bool skip_all_for_block(auto& idx, auto& it, const block_id_type& id) { - while (it != idx.end() && (*it)->id() == id) { + while (it != idx.end() && it->id() == id) { ++it; } return it == idx.end(); @@ -157,14 +155,14 @@ class vote_processor_t { continue; } auto& idx = index.get(); - if (auto i = idx.begin(); i != idx.end() && not_in_forkdb_id == (*i)->id()) { // same block as last while loop + if (auto i = idx.begin(); i != idx.end() && not_in_forkdb_id == i->id()) { // same block as last while loop g.unlock(); std::this_thread::sleep_for(block_wait_time); g.lock(); } for (auto i = idx.begin(); i != idx.end();) { auto& vt = *i; - block_state_ptr bsp = fetch_block_func(vt->id()); + block_state_ptr bsp = fetch_block_func(vt.id()); if (bsp) { if (!bsp->is_proper_svnn_block()) { if (remove_all_for_block(idx, i, bsp->id())) @@ -172,20 +170,20 @@ class vote_processor_t { continue; } auto iter_of_bsp = i; - std::vector to_process; + std::vector to_process; to_process.reserve(std::min(21u, idx.size())); // increase if we increase # of finalizers from 21 - for(; i != idx.end() && bsp->id() == (*i)->id(); ++i) { + for(; i != idx.end() && bsp->id() == i->id(); ++i) { // although it is the highest contention on block state pending mutex posting all of the same bsp, // the highest priority is processing votes for this block state. to_process.push_back(*i); } bool should_break = remove_all_for_block(idx, iter_of_bsp, bsp->id()); g.unlock(); // do not hold lock when posting - for (auto& vptr : to_process) { - boost::asio::post(thread_pool.get_executor(), [this, bsp, vptr=std::move(vptr)]() { - vote_status s = bsp->aggregate_vote(vptr->msg); + for (auto& v : to_process) { + boost::asio::post(thread_pool.get_executor(), [this, bsp, v=std::move(v)]() { + vote_status s = bsp->aggregate_vote(*v.msg); if (s != vote_status::duplicate) { // don't bother emitting duplicates - emit(vptr->connection_id, s, vptr->msg); + emit(v.connection_id, s, v.msg); } }); } @@ -194,8 +192,8 @@ class vote_processor_t { g.lock(); i = idx.begin(); } else { - not_in_forkdb_id = vt->id(); - if (skip_all_for_block(idx, i, (*i)->id())) + not_in_forkdb_id = vt.id(); + if (skip_all_for_block(idx, i, i->id())) break; } } @@ -208,8 +206,7 @@ class vote_processor_t { lib = block_num; } - void process_vote_message(uint32_t connection_id, const vote_message& msg) { - vote_ptr vptr = std::make_shared(vote{.connection_id = connection_id, .msg = msg}); + void process_vote_message(uint32_t connection_id, const vote_message_ptr& msg) { boost::asio::post(thread_pool.get_executor(), [this, connection_id, msg] { std::unique_lock g(mtx); if (++num_messages[connection_id] > max_votes_per_connection) { @@ -220,10 +217,10 @@ class vote_processor_t { elog("Exceeded max votes per connection for ${c}", ("c", connection_id)); emit(connection_id, vote_status::max_exceeded, msg); - } else if (block_header::num_from_id(msg.block_id) < lib.load(std::memory_order_relaxed)) { + } else if (block_header::num_from_id(msg->block_id) < lib.load(std::memory_order_relaxed)) { // ignore } else { - index.insert(std::make_shared(vote{.connection_id = connection_id, .msg = msg})); + index.insert(vote{.connection_id = connection_id, .msg = msg}); cv.notify_one(); } }); diff --git a/plugins/net_plugin/net_plugin.cpp b/plugins/net_plugin/net_plugin.cpp index 4bdf231f61..e574153967 100644 --- a/plugins/net_plugin/net_plugin.cpp +++ b/plugins/net_plugin/net_plugin.cpp @@ -339,6 +339,7 @@ namespace eosio { constexpr uint32_t signed_block_which = fc::get_index(); // see protocol net_message constexpr uint32_t packed_transaction_which = fc::get_index(); // see protocol net_message + constexpr uint32_t vote_message_which = fc::get_index(); // see protocol net_message class connections_manager { public: @@ -476,6 +477,7 @@ namespace eosio { uint32_t max_nodes_per_host = 1; bool p2p_accept_transactions = true; + bool p2p_accept_votes = true; fc::microseconds p2p_dedup_cache_expire_time_us{}; chain_id_type chain_id; @@ -529,12 +531,12 @@ namespace eosio { void on_accepted_block_header( const signed_block_ptr& block, const block_id_type& id ); void on_accepted_block(); - void on_voted_block ( uint32_t connection_id, vote_status stauts, const vote_message& vote ); + void on_voted_block ( uint32_t connection_id, vote_status stauts, const vote_message_ptr& vote ); void transaction_ack(const std::pair&); void on_irreversible_block( const block_id_type& id, uint32_t block_num ); - void bcast_vote_message( uint32_t exclude_peer, const chain::vote_message& msg ); + void bcast_vote_message( uint32_t exclude_peer, const chain::vote_message_ptr& msg ); void warn_message( uint32_t sender_peer, const chain::hs_message_warning& code ); void start_conn_timer(boost::asio::steady_timer::duration du, std::weak_ptr from_connection); @@ -1005,6 +1007,7 @@ namespace eosio { bool process_next_block_message(uint32_t message_length); bool process_next_trx_message(uint32_t message_length); + bool process_next_vote_message(uint32_t message_length); void update_endpoints(const tcp::endpoint& endpoint = tcp::endpoint()); public: @@ -1105,8 +1108,9 @@ namespace eosio { void handle_message( const signed_block& msg ) = delete; // signed_block_ptr overload used instead void handle_message( const block_id_type& id, signed_block_ptr ptr ); void handle_message( const packed_transaction& msg ) = delete; // packed_transaction_ptr overload used instead - void handle_message( packed_transaction_ptr trx ); - void handle_message( const vote_message& msg ); + void handle_message( const packed_transaction_ptr& trx ); + void handle_message( const vote_message_ptr& msg ); + void handle_message( const vote_message& msg ) = delete; // vote_message_ptr overload used instead // returns calculated number of blocks combined latency uint32_t calc_block_latency(); @@ -1187,12 +1191,6 @@ namespace eosio { peer_dlog( c, "handle sync_request_message" ); c->handle_message( msg ); } - - void operator()( const chain::vote_message& msg ) const { - // continue call to handle_message on connection strand - peer_dlog( c, "handle vote_message" ); - c->handle_message( msg ); - } }; @@ -3077,6 +3075,8 @@ namespace eosio { return process_next_block_message( message_length ); } else if( which == packed_transaction_which ) { return process_next_trx_message( message_length ); + } else if( which == vote_message_which ) { + return process_next_vote_message( message_length ); } else { auto ds = pending_message_buffer.create_datastream(); net_message msg; @@ -3189,7 +3189,7 @@ namespace eosio { auto ds = pending_message_buffer.create_datastream(); unsigned_int which{}; fc::raw::unpack( ds, which ); - shared_ptr ptr = std::make_shared(); + packed_transaction_ptr ptr = std::make_shared(); fc::raw::unpack( ds, *ptr ); if( trx_in_progress_sz > def_max_trx_in_progress_size) { char reason[72]; @@ -3212,7 +3212,26 @@ namespace eosio { return true; } - handle_message( std::move( ptr ) ); + handle_message( ptr ); + return true; + } + + // called from connection strand + bool connection::process_next_vote_message(uint32_t message_length) { + if( !my_impl->p2p_accept_votes ) { + peer_dlog( this, "p2p_accept_votes=false - dropping vote" ); + pending_message_buffer.advance_read_ptr( message_length ); + return true; + } + + auto ds = pending_message_buffer.create_datastream(); + unsigned_int which{}; + fc::raw::unpack( ds, which ); + assert(which == vote_message_which); + vote_message_ptr ptr = std::make_shared(); + fc::raw::unpack( ds, *ptr ); + + handle_message( ptr ); return true; } @@ -3708,10 +3727,10 @@ namespace eosio { } } - void connection::handle_message( const vote_message& msg ) { + void connection::handle_message( const vote_message_ptr& msg ) { peer_dlog(this, "received vote: block #${bn}:${id}.., ${v}, key ${k}..", - ("bn", block_header::num_from_id(msg.block_id))("id", msg.block_id.str().substr(8,16)) - ("v", msg.strong ? "strong" : "weak")("k", msg.finalizer_key.to_string().substr(8, 16))); + ("bn", block_header::num_from_id(msg->block_id))("id", msg->block_id.str().substr(8,16)) + ("v", msg->strong ? "strong" : "weak")("k", msg->finalizer_key.to_string().substr(8, 16))); controller& cc = my_impl->chain_plug->chain(); cc.process_vote_message(connection_id, msg); } @@ -3721,7 +3740,7 @@ namespace eosio { } // called from connection strand - void connection::handle_message( packed_transaction_ptr trx ) { + void connection::handle_message( const packed_transaction_ptr& trx ) { const auto& tid = trx->id(); peer_dlog( this, "received packed_transaction ${id}", ("id", tid) ); @@ -3979,10 +3998,10 @@ namespace eosio { } // called from other threads including net threads - void net_plugin_impl::on_voted_block(uint32_t connection_id, vote_status status, const vote_message& msg) { + void net_plugin_impl::on_voted_block(uint32_t connection_id, vote_status status, const vote_message_ptr& msg) { fc_dlog(logger, "connection - ${c} on voted signal: ${s} block #${bn} ${id}.., ${t}, key ${k}..", - ("c", connection_id)("s", status)("bn", block_header::num_from_id(msg.block_id))("id", msg.block_id.str().substr(8,16)) - ("t", msg.strong ? "strong" : "weak")("k", msg.finalizer_key.to_string().substr(8, 16))); + ("c", connection_id)("s", status)("bn", block_header::num_from_id(msg->block_id))("id", msg->block_id.str().substr(8,16)) + ("t", msg->strong ? "strong" : "weak")("k", msg->finalizer_key.to_string().substr(8, 16))); switch( status ) { case vote_status::success: @@ -3999,7 +4018,7 @@ namespace eosio { break; case vote_status::unknown_block: // track the failure fc_dlog(logger, "connection - ${c} vote unknown block #${bn}:${id}..", - ("c", connection_id)("bn", block_header::num_from_id(msg.block_id))("id", msg.block_id.str().substr(8,16))); + ("c", connection_id)("bn", block_header::num_from_id(msg->block_id))("id", msg->block_id.str().substr(8,16))); my_impl->connections.for_each_connection([connection_id](const connection_ptr& c) { if (c->connection_id == connection_id) { c->block_status_monitor_.rejected(); @@ -4013,13 +4032,13 @@ namespace eosio { } } - void net_plugin_impl::bcast_vote_message( uint32_t exclude_peer, const chain::vote_message& msg ) { + void net_plugin_impl::bcast_vote_message( uint32_t exclude_peer, const chain::vote_message_ptr& msg ) { buffer_factory buff_factory; - auto send_buffer = buff_factory.get_send_buffer( msg ); + auto send_buffer = buff_factory.get_send_buffer( *msg ); fc_dlog(logger, "bcast ${t} vote: block #${bn} ${id}.., ${v}, key ${k}..", - ("t", exclude_peer ? "received" : "our")("bn", block_header::num_from_id(msg.block_id))("id", msg.block_id.str().substr(8,16)) - ("v", msg.strong ? "strong" : "weak")("k", msg.finalizer_key.to_string().substr(8,16))); + ("t", exclude_peer ? "received" : "our")("bn", block_header::num_from_id(msg->block_id))("id", msg->block_id.str().substr(8,16)) + ("v", msg->strong ? "strong" : "weak")("k", msg->finalizer_key.to_string().substr(8,16))); dispatcher.strand.post( [this, exclude_peer, msg{std::move(send_buffer)}]() mutable { dispatcher.bcast_vote_msg( exclude_peer, std::move(msg) ); @@ -4244,6 +4263,7 @@ namespace eosio { resp_expected_period = def_resp_expected_wait; max_nodes_per_host = options.at( "p2p-max-nodes-per-host" ).as(); p2p_accept_transactions = options.at( "p2p-accept-transactions" ).as(); + p2p_accept_votes = options.at("vote-threads").as() != 0; use_socket_read_watermark = options.at( "use-socket-read-watermark" ).as(); keepalive_interval = std::chrono::milliseconds( options.at( "p2p-keepalive-interval-ms" ).as() ); diff --git a/unittests/finality_test_cluster.cpp b/unittests/finality_test_cluster.cpp index e84340cb44..42d65a2221 100644 --- a/unittests/finality_test_cluster.cpp +++ b/unittests/finality_test_cluster.cpp @@ -129,10 +129,10 @@ void finality_test_cluster::node1_corrupt_vote_proposal_id() { std::lock_guard g(node1.votes_mtx); node1_orig_vote = node1.votes[0]; - if( node1.votes[0].block_id.data()[0] == 'a' ) { - node1.votes[0].block_id.data()[0] = 'b'; + if( node1.votes[0]->block_id.data()[0] == 'a' ) { + node1.votes[0]->block_id.data()[0] = 'b'; } else { - node1.votes[0].block_id.data()[0] = 'a'; + node1.votes[0]->block_id.data()[0] = 'a'; } } @@ -141,10 +141,10 @@ void finality_test_cluster::node1_corrupt_vote_finalizer_key() { node1_orig_vote = node1.votes[0]; // corrupt the finalizer_key (manipulate so it is different) - auto g1 = node1.votes[0].finalizer_key.jacobian_montgomery_le(); + auto g1 = node1.votes[0]->finalizer_key.jacobian_montgomery_le(); g1 = bls12_381::aggregate_public_keys(std::array{g1, g1}); auto affine = g1.toAffineBytesLE(bls12_381::from_mont::yes); - node1.votes[0].finalizer_key = fc::crypto::blslib::bls_public_key(affine); + node1.votes[0]->finalizer_key = fc::crypto::blslib::bls_public_key(affine); } void finality_test_cluster::node1_corrupt_vote_signature() { @@ -152,10 +152,10 @@ void finality_test_cluster::node1_corrupt_vote_signature() { node1_orig_vote = node1.votes[0]; // corrupt the signature - auto g2 = node1.votes[0].sig.jacobian_montgomery_le(); + auto g2 = node1.votes[0]->sig.jacobian_montgomery_le(); g2 = bls12_381::aggregate_signatures(std::array{g2, g2}); auto affine = g2.toAffineBytesLE(bls12_381::from_mont::yes); - node1.votes[0].sig = fc::crypto::blslib::bls_signature(affine); + node1.votes[0]->sig = fc::crypto::blslib::bls_signature(affine); } void finality_test_cluster::node1_restore_to_original_vote() { @@ -208,20 +208,20 @@ eosio::chain::vote_status finality_test_cluster::process_vote(node_info& node, s FC_ASSERT( vote_index < node.votes.size(), "out of bound index in process_vote" ); auto& vote = node.votes[vote_index]; if( mode == vote_mode::strong ) { - vote.strong = true; + vote->strong = true; } else { - vote.strong = false; + vote->strong = false; // fetch the strong digest - auto strong_digest = node.node.control->get_strong_digest_by_id(vote.block_id); + auto strong_digest = node.node.control->get_strong_digest_by_id(vote->block_id); // convert the strong digest to weak and sign it - vote.sig = node.priv_key.sign(eosio::chain::create_weak_digest(strong_digest)); + vote->sig = node.priv_key.sign(eosio::chain::create_weak_digest(strong_digest)); } g.unlock(); static uint32_t connection_id = 0; node0.node.control->process_vote_message( ++connection_id, vote ); - if (eosio::chain::block_header::num_from_id(vote.block_id) > node0.node.control->last_irreversible_block_num()) + if (eosio::chain::block_header::num_from_id(vote->block_id) > node0.node.control->last_irreversible_block_num()) return wait_on_vote(connection_id); return eosio::chain::vote_status::unknown_block; } diff --git a/unittests/finality_test_cluster.hpp b/unittests/finality_test_cluster.hpp index a84b86bb46..0c965e6d99 100644 --- a/unittests/finality_test_cluster.hpp +++ b/unittests/finality_test_cluster.hpp @@ -79,7 +79,7 @@ class finality_test_cluster { eosio::testing::tester node; uint32_t prev_lib_num{0}; std::mutex votes_mtx; - std::vector votes; + std::vector votes; fc::crypto::blslib::bls_private_key priv_key; }; @@ -91,7 +91,7 @@ class finality_test_cluster { node_info& node1 = nodes[1]; node_info& node2 = nodes[2]; - eosio::chain::vote_message node1_orig_vote; + eosio::chain::vote_message_ptr node1_orig_vote; // sets up "node_index" node void setup_node(node_info& node, eosio::chain::account_name local_finalizer);