Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IF: reenable weak vote related tests #2240

Merged
merged 2 commits into from
Feb 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions libraries/chain/controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1860,6 +1860,18 @@ struct controller_impl {
);
}

digest_type get_strong_digest_by_id( const block_id_type& id ) const {
return fork_db.apply<digest_type>(
overloaded{
[](const fork_database_legacy_t&) -> digest_type { return digest_type{}; },
[&](const fork_database_if_t& forkdb) -> digest_type {
auto bsp = forkdb.get_block(id);
return bsp ? bsp->strong_digest : digest_type{};
}
}
);
}

fc::sha256 calculate_integrity_hash() {
fc::sha256::encoder enc;
auto hash_writer = std::make_shared<integrity_hash_snapshot_writer>(enc);
Expand Down Expand Up @@ -4463,6 +4475,10 @@ block_id_type controller::get_block_id_for_num( uint32_t block_num )const { try
return id;
} FC_CAPTURE_AND_RETHROW( (block_num) ) }

digest_type controller::get_strong_digest_by_id( const block_id_type& id ) const {
return my->get_strong_digest_by_id(id);
}

fc::sha256 controller::calculate_integrity_hash() { try {
return my->calculate_integrity_hash();
} FC_LOG_AND_RETHROW() }
Expand Down
2 changes: 2 additions & 0 deletions libraries/chain/include/eosio/chain/controller.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,8 @@ namespace eosio::chain {
std::optional<signed_block_header> fetch_block_header_by_id( const block_id_type& id )const;
// thread-safe
block_id_type get_block_id_for_num( uint32_t block_num )const;
// thread-safe
digest_type get_strong_digest_by_id( const block_id_type& id ) const; // used in unittests

fc::sha256 calculate_integrity_hash();
void write_snapshot( const snapshot_writer_ptr& snapshot );
Expand Down
4 changes: 2 additions & 2 deletions libraries/testing/include/eosio/testing/tester.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ namespace eosio { namespace testing {

// libtester uses 1 as weight of each of the finalizer, sets (2/3 finalizers + 1)
// as threshold, and makes all finalizers vote QC
transaction_trace_ptr set_finalizers(const vector<account_name>& finalizer_names);
std::pair<transaction_trace_ptr, std::vector<fc::crypto::blslib::bls_private_key>> set_finalizers(const vector<account_name>& finalizer_names);

// Finalizer policy input to set up a test: weights, threshold and local finalizers
// which participate voting.
Expand All @@ -269,7 +269,7 @@ namespace eosio { namespace testing {
uint64_t threshold {0};
std::vector<account_name> local_finalizers;
};
transaction_trace_ptr set_finalizers(const finalizer_policy_input& input);
std::pair<transaction_trace_ptr, std::vector<fc::crypto::blslib::bls_private_key>> set_finalizers(const finalizer_policy_input& input);

void link_authority( account_name account, account_name code, permission_name req, action_name type = {} );
void unlink_authority( account_name account, account_name code, action_name type = {} );
Expand Down
11 changes: 7 additions & 4 deletions libraries/testing/tester.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1174,7 +1174,7 @@ namespace eosio { namespace testing {

}

transaction_trace_ptr base_tester::set_finalizers(const vector<account_name>& finalizer_names) {
std::pair<transaction_trace_ptr, std::vector<fc::crypto::blslib::bls_private_key>> base_tester::set_finalizers(const vector<account_name>& finalizer_names) {
auto num_finalizers = finalizer_names.size();
std::vector<finalizer_policy_input::finalizer_info> finalizers_info;
finalizers_info.reserve(num_finalizers);
Expand All @@ -1191,16 +1191,18 @@ namespace eosio { namespace testing {
return set_finalizers(policy_input);
}

transaction_trace_ptr base_tester::set_finalizers(const finalizer_policy_input& input) {
std::pair<transaction_trace_ptr, std::vector<fc::crypto::blslib::bls_private_key>> base_tester::set_finalizers(const finalizer_policy_input& input) {
chain::bls_pub_priv_key_map_t local_finalizer_keys;
fc::variants finalizer_auths;
std::vector<fc::crypto::blslib::bls_private_key> priv_keys;

for (const auto& f: input.finalizers) {
auto [privkey, pubkey, pop] = get_bls_key( f.name );

// if it is a local finalizer, set up public to private key mapping for voting
if( auto it = std::ranges::find_if(input.local_finalizers, [&](const auto& name) { return name == f.name; }); it != input.local_finalizers.end()) {
local_finalizer_keys[pubkey.to_string()] = privkey.to_string();
priv_keys.emplace_back(privkey);
};

finalizer_auths.emplace_back(
Expand All @@ -1217,8 +1219,9 @@ namespace eosio { namespace testing {
fin_policy_variant("threshold", input.threshold);
fin_policy_variant("finalizers", std::move(finalizer_auths));

return push_action( config::system_account_name, "setfinalizer"_n, config::system_account_name,
fc::mutable_variant_object()("finalizer_policy", std::move(fin_policy_variant)));
return { push_action( config::system_account_name, "setfinalizer"_n, config::system_account_name,
fc::mutable_variant_object()("finalizer_policy", std::move(fin_policy_variant))),
priv_keys };
}

const table_id_object* base_tester::find_table( name code, name scope, name table ) {
Expand Down
12 changes: 11 additions & 1 deletion unittests/finality_test_cluster.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,11 @@ void finality_test_cluster::setup_node(node_info& node, eosio::chain::account_na
.threshold = 2,
.local_finalizers = {local_finalizer}
};
node.node.set_finalizers(policy_input);

auto [trace_ptr, priv_keys] = node.node.set_finalizers(policy_input);
FC_ASSERT( priv_keys.size() == 1, "number of private keys should be 1" );
node.priv_key = priv_keys[0]; // we only have one private key

auto block = node.node.produce_block();

// this block contains the header extension for the instant finality
Expand All @@ -178,7 +182,13 @@ eosio::chain::vote_status finality_test_cluster::process_vote(node_info& node, s
vote.strong = true;
} else {
vote.strong = false;

// fetch the strong digest
auto strong_digest = node.node.control->get_strong_digest_by_id(vote.proposal_id);
// convert the strong digest to weak and sign it
vote.sig = node.priv_key.sign(eosio::chain::create_weak_digest(strong_digest));
}

return node0.node.control->process_vote_message( vote );
}

Expand Down
2 changes: 2 additions & 0 deletions unittests/finality_test_cluster.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once

#include <eosio/chain/hotstuff/finalizer_authority.hpp>
#include <fc/crypto/bls_private_key.hpp>

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wsign-compare"
Expand Down Expand Up @@ -78,6 +79,7 @@ class finality_test_cluster {
eosio::testing::tester node;
uint32_t prev_lib_num{0};
std::vector<eosio::chain::vote_message> votes;
fc::crypto::blslib::bls_private_key priv_key;
};

std::array<node_info, 3> nodes;
Expand Down
25 changes: 5 additions & 20 deletions unittests/finality_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,6 @@ BOOST_AUTO_TEST_CASE(long_delayed_votes) { try {
cluster.process_node1_vote();
// the vote makes a strong QC for the current block, prompting LIB advance on node0
BOOST_REQUIRE(cluster.node0_lib_advancing());
// the block does not has a QC extension as prior block was not a strong block
BOOST_REQUIRE(!cluster.node1_lib_advancing());

for (auto i = 2; i < 100; ++i) {
Expand Down Expand Up @@ -221,22 +220,18 @@ BOOST_AUTO_TEST_CASE(lost_votes) { try {

// the vote makes a strong QC for the current block, prompting LIB advance on node0
BOOST_REQUIRE(cluster.node0_lib_advancing());
// the block does not has a QC extension as prior block was not a strong block
BOOST_REQUIRE(!cluster.node1_lib_advancing());

BOOST_REQUIRE(cluster.produce_blocks_and_verify_lib_advancing());
} FC_LOG_AND_RETHROW() }

#warning "Re-enable these tests"
#if 0
BOOST_AUTO_TEST_CASE(one_weak_vote) { try {
finality_test_cluster cluster;

// Produce and push a block
cluster.produce_and_push_block();
// Change the vote to a weak vote and process it
cluster.process_node1_vote(0, finality_test_cluster::vote_mode::weak);

// A weak QC is created and LIB does not advance on node0
BOOST_REQUIRE(!cluster.node0_lib_advancing());
// The strong QC extension for prior block makes LIB advance on node1
Expand All @@ -248,21 +243,19 @@ BOOST_AUTO_TEST_CASE(one_weak_vote) { try {
// its final_on_strong_qc_block_num is nullopt due to previous QC was weak.
// Cannot advance LIB.
BOOST_REQUIRE(!cluster.node0_lib_advancing());
// the block does not has a QC extension as prior block was not a strong block
// no 2-chain was formed as prior block was not a strong block
BOOST_REQUIRE(!cluster.node1_lib_advancing());

cluster.produce_and_push_block();
cluster.process_node1_vote();
BOOST_REQUIRE(cluster.node0_lib_advancing());
// the block does not has a QC extension as prior block was not a strong block
BOOST_REQUIRE(!cluster.node1_lib_advancing());

cluster.produce_and_push_block();
cluster.process_node1_vote();
// the vote makes a strong QC and a higher final_on_strong_qc,
// prompting LIB advance on node0
BOOST_REQUIRE(cluster.node0_lib_advancing());
// the block does not has a QC extension as prior block was not a strong block
BOOST_REQUIRE(cluster.node1_lib_advancing());

// now a 3 chain has formed.
Expand All @@ -285,28 +278,26 @@ BOOST_AUTO_TEST_CASE(two_weak_votes) { try {
cluster.process_node1_vote(finality_test_cluster::vote_mode::weak);
// A weak QC cannot advance LIB on node0
BOOST_REQUIRE(!cluster.node0_lib_advancing());
// the block does not has a QC extension as prior block was not a strong block
// no 2-chain was formed as prior block was not a strong block
BOOST_REQUIRE(!cluster.node1_lib_advancing());

cluster.produce_and_push_block();
cluster.process_node1_vote();
// the vote makes a strong QC for the current block, prompting LIB advance on node0
BOOST_REQUIRE(!cluster.node0_lib_advancing());
// the block does not has a QC extension as prior block was not a strong block
BOOST_REQUIRE(!cluster.node1_lib_advancing());

cluster.produce_and_push_block();
cluster.process_node1_vote();
// the vote makes a strong QC for the current block, prompting LIB advance on node0
BOOST_REQUIRE(cluster.node0_lib_advancing());
// the block does not has a QC extension as prior block was not a strong block
BOOST_REQUIRE(!cluster.node1_lib_advancing());

// now a 3 chain has formed.
BOOST_REQUIRE(cluster.produce_blocks_and_verify_lib_advancing());
} FC_LOG_AND_RETHROW() }

BOOST_AUTO_TEST_CASE(interwined_weak_votes) { try {
BOOST_AUTO_TEST_CASE(intertwined_weak_votes) { try {
finality_test_cluster cluster;

// Weak vote
Expand All @@ -324,23 +315,22 @@ BOOST_AUTO_TEST_CASE(interwined_weak_votes) { try {
// its final_on_strong_qc_block_num is nullopt due to previous QC was weak.
// Cannot advance LIB.
BOOST_REQUIRE(!cluster.node0_lib_advancing());
// the block does not has a QC extension as prior block was not a strong block
// no 2-chain was formed as prior block was not a strong block
BOOST_REQUIRE(!cluster.node1_lib_advancing());

// Weak vote
cluster.produce_and_push_block();
cluster.process_node1_vote(finality_test_cluster::vote_mode::weak);
// A weak QC cannot advance LIB on node0
BOOST_REQUIRE(!cluster.node0_lib_advancing());
// the block does not has a QC extension as prior block was not a strong block
BOOST_REQUIRE(!cluster.node1_lib_advancing());

// Strong vote
cluster.produce_and_push_block();
cluster.process_node1_vote();
// the vote makes a strong QC for the current block, prompting LIB advance on node0
BOOST_REQUIRE(!cluster.node0_lib_advancing());
// the block does not has a QC extension as prior block was not a strong block
// no 2-chain was formed as prior block was not a strong block
BOOST_REQUIRE(!cluster.node1_lib_advancing());

// Strong vote
Expand Down Expand Up @@ -374,13 +364,11 @@ BOOST_AUTO_TEST_CASE(weak_delayed_lost_vote) { try {
// The vote makes a strong QC, but final_on_strong_qc is null.
// Do not advance LIB
BOOST_REQUIRE(!cluster.node0_lib_advancing());
// the block does not has a QC extension as prior block was not a strong block
BOOST_REQUIRE(!cluster.node1_lib_advancing());

// A lost vote
cluster.produce_and_push_block();
BOOST_REQUIRE(!cluster.node0_lib_advancing());
// the block does not has a QC extension as prior block was not a strong block
BOOST_REQUIRE(!cluster.node1_lib_advancing());

// The delayed vote arrives
Expand Down Expand Up @@ -429,13 +417,11 @@ BOOST_AUTO_TEST_CASE(delayed_strong_weak_lost_vote) { try {
// The vote makes a strong QC, but final_on_strong_qc is null.
// LIB did not advance.
BOOST_REQUIRE(!cluster.node0_lib_advancing());
// the block does not has a QC extension as prior block was not a strong block
BOOST_REQUIRE(!cluster.node1_lib_advancing());

// A lost vote
cluster.produce_and_push_block();
BOOST_REQUIRE(!cluster.node0_lib_advancing());
// the block does not has a QC extension as prior block was not a strong block
BOOST_REQUIRE(!cluster.node1_lib_advancing());

// The delayed vote arrives
Expand All @@ -455,7 +441,6 @@ BOOST_AUTO_TEST_CASE(delayed_strong_weak_lost_vote) { try {

BOOST_REQUIRE(cluster.produce_blocks_and_verify_lib_advancing());
} FC_LOG_AND_RETHROW() }
#endif

// verify duplicate votes do not affect LIB advancing
BOOST_AUTO_TEST_CASE(duplicate_votes) { try {
Expand Down
Loading