Skip to content

Commit

Permalink
Merge pull request #346 from AntelopeIO/validate_qc_bitset_size
Browse files Browse the repository at this point in the history
Reject a QC if bitset size of its strong_votes or weak_votes is invalid
  • Loading branch information
linh2931 authored Jul 8, 2024
2 parents e2c32c4 + 3acb54b commit abc65ce
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 9 deletions.
9 changes: 6 additions & 3 deletions libraries/chain/block_state.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -231,10 +231,13 @@ void block_state::verify_qc(const valid_quorum_certificate& qc) const {

// utility to accumulate voted weights
auto weights = [&] ( const vote_bitset& votes_bitset ) -> uint64_t {
EOS_ASSERT( num_finalizers == votes_bitset.size(),
invalid_qc_claim,
"vote bitset size is not the same as the number of finalizers for the policy it refers to, vote bitset size: ${s}, num of finalizers for the policy: ${n}",
("s", votes_bitset.size())("n", num_finalizers) );

uint64_t sum = 0;
assert(num_finalizers == votes_bitset.size());
auto n = std::min(num_finalizers, votes_bitset.size());
for (auto i = 0u; i < n; ++i) {
for (auto i = 0u; i < num_finalizers; ++i) {
if( votes_bitset[i] ) { // ith finalizer voted
sum += finalizers[i].weight;
}
Expand Down
50 changes: 44 additions & 6 deletions unittests/block_state_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ BOOST_AUTO_TEST_CASE(verify_qc_test) try {
// create a valid_quorum_certificate
valid_quorum_certificate qc(strong_votes, {}, agg_sig);

BOOST_CHECK_EXCEPTION( bsp->verify_qc(qc), block_validate_exception, eosio::testing::fc_exception_message_starts_with("strong quorum is not met") );
BOOST_CHECK_EXCEPTION( bsp->verify_qc(qc), invalid_qc_claim, eosio::testing::fc_exception_message_starts_with("strong quorum is not met") );
}

{ // weak QC quorem not met
Expand All @@ -301,7 +301,45 @@ BOOST_AUTO_TEST_CASE(verify_qc_test) try {
// create a valid_quorum_certificate
valid_quorum_certificate qc({}, weak_votes, agg_sig);

BOOST_CHECK_EXCEPTION( bsp->verify_qc(qc), block_validate_exception, eosio::testing::fc_exception_message_starts_with("weak quorum is not met") );
BOOST_CHECK_EXCEPTION( bsp->verify_qc(qc), invalid_qc_claim, eosio::testing::fc_exception_message_starts_with("weak quorum is not met") );
}

{ // strong QC bitset size does not match number of finalizers in the policy

// construct vote bitset with a size greater than num_finalizers
vote_bitset strong_votes(num_finalizers + 1);

// vote by finalizer 0
strong_votes[0] = 1;

// aggregate votes
bls_aggregate_signature agg_sig;
bls_signature sig = private_key[0].sign(strong_digest.to_uint8_span());
agg_sig.aggregate(sig);

// create a valid_quorum_certificate
valid_quorum_certificate qc(strong_votes, {}, agg_sig);

BOOST_CHECK_EXCEPTION( bsp->verify_qc(qc), invalid_qc_claim, eosio::testing::fc_exception_message_starts_with("vote bitset size is not the same as the number of finalizers") );
}

{ // weak QC bitset size does not match number of finalizers in the policy

// construct vote bitset with a size less than num_finalizers
vote_bitset weak_votes(num_finalizers - 1);

// vote by finalizer 0
weak_votes[0] = 1;

// aggregate votes
bls_aggregate_signature agg_sig;
bls_signature sig = private_key[0].sign(weak_digest);
agg_sig.aggregate(sig);

// create a valid_quorum_certificate
valid_quorum_certificate qc({}, weak_votes, agg_sig);

BOOST_CHECK_EXCEPTION( bsp->verify_qc(qc), invalid_qc_claim, eosio::testing::fc_exception_message_starts_with("vote bitset size is not the same as the number of finalizers") );
}

{ // strong QC with a wrong signing private key
Expand All @@ -318,7 +356,7 @@ BOOST_AUTO_TEST_CASE(verify_qc_test) try {
// create a valid_quorum_certificate
valid_quorum_certificate qc(strong_votes, {}, sig);

BOOST_CHECK_EXCEPTION( bsp->verify_qc(qc), block_validate_exception, eosio::testing::fc_exception_message_is("signature validation failed") );
BOOST_CHECK_EXCEPTION( bsp->verify_qc(qc), invalid_qc_claim, eosio::testing::fc_exception_message_is("signature validation failed") );
}

{ // strong QC with a wrong digest
Expand All @@ -335,7 +373,7 @@ BOOST_AUTO_TEST_CASE(verify_qc_test) try {
// create a valid_quorum_certificate
valid_quorum_certificate qc(strong_votes, {}, sig);

BOOST_CHECK_EXCEPTION( bsp->verify_qc(qc), block_validate_exception, eosio::testing::fc_exception_message_is("signature validation failed") );
BOOST_CHECK_EXCEPTION( bsp->verify_qc(qc), invalid_qc_claim, eosio::testing::fc_exception_message_is("signature validation failed") );
}

{ // weak QC with a wrong signing private key
Expand All @@ -352,7 +390,7 @@ BOOST_AUTO_TEST_CASE(verify_qc_test) try {
sig.aggregate(weak_sig);

valid_quorum_certificate qc(strong_votes, weak_votes, sig);
BOOST_CHECK_EXCEPTION( bsp->verify_qc(qc), block_validate_exception, eosio::testing::fc_exception_message_is("signature validation failed") );
BOOST_CHECK_EXCEPTION( bsp->verify_qc(qc), invalid_qc_claim, eosio::testing::fc_exception_message_is("signature validation failed") );
}

{ // weak QC with a wrong digest
Expand All @@ -369,7 +407,7 @@ BOOST_AUTO_TEST_CASE(verify_qc_test) try {
sig.aggregate(weak_sig);

valid_quorum_certificate qc(strong_votes, weak_votes, sig);
BOOST_CHECK_EXCEPTION( bsp->verify_qc(qc), block_validate_exception, eosio::testing::fc_exception_message_is("signature validation failed") );
BOOST_CHECK_EXCEPTION( bsp->verify_qc(qc), invalid_qc_claim, eosio::testing::fc_exception_message_is("signature validation failed") );
}
} FC_LOG_AND_RETHROW();

Expand Down

0 comments on commit abc65ce

Please sign in to comment.