Skip to content

Commit

Permalink
Merge pull request #167 from AntelopeIO/more_unittests_two_modes
Browse files Browse the repository at this point in the history
Make unit tests run in both Legacy and Savanna (Part 4,  block_tests, chain_tests, database_tests, restart_chain_tests)
  • Loading branch information
linh2931 authored May 20, 2024
2 parents 1844666 + 846517e commit 2187c80
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 57 deletions.
82 changes: 52 additions & 30 deletions unittests/block_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ using namespace chain;

BOOST_AUTO_TEST_SUITE(block_tests)

BOOST_AUTO_TEST_CASE(block_with_invalid_tx_test)
BOOST_AUTO_TEST_CASE_TEMPLATE( block_with_invalid_tx_test, T, testers )
{
tester main;
T main;

// First we create a valid block with valid transaction
main.create_account("newacc"_n);
Expand All @@ -19,7 +19,7 @@ BOOST_AUTO_TEST_CASE(block_with_invalid_tx_test)
auto copy_b = std::make_shared<signed_block>(std::move(*b));
auto signed_tx = std::get<packed_transaction>(copy_b->transactions.back().trx).get_signed_transaction();
auto& act = signed_tx.actions.back();
auto act_data = act.data_as<newaccount>();
auto act_data = act.template data_as<newaccount>();
// Make the transaction invalid by having the new account name the same as the creator name
act_data.name = act_data.creator;
act.data = fc::raw::pack(act_data);
Expand All @@ -35,15 +35,23 @@ BOOST_AUTO_TEST_CASE(block_with_invalid_tx_test)
const auto& trxs = copy_b->transactions;
for( const auto& a : trxs )
trx_digests.emplace_back( a.digest() );
copy_b->transaction_mroot = calculate_merkle_legacy( std::move(trx_digests) );
if constexpr (std::is_same_v<T, savanna_tester>) {
copy_b->transaction_mroot = calculate_merkle( std::move(trx_digests) );
} else {
copy_b->transaction_mroot = calculate_merkle_legacy( std::move(trx_digests) );
}

// Re-sign the block
auto header_bmroot = digest_type::hash( std::make_pair( copy_b->digest(), main.control->head_block_state_legacy()->blockroot_merkle.get_root() ) );
auto sig_digest = digest_type::hash( std::make_pair(header_bmroot, main.control->head_block_state_legacy()->pending_schedule.schedule_hash) );
copy_b->producer_signature = main.get_private_key(config::system_account_name, "active").sign(sig_digest);
if constexpr (std::is_same_v<T, savanna_tester>) {
copy_b->producer_signature = main.get_private_key(config::system_account_name, "active").sign(copy_b->calculate_id());
} else {
auto header_bmroot = digest_type::hash( std::make_pair( copy_b->digest(), main.control->head_block_state_legacy()->blockroot_merkle.get_root() ) );
auto sig_digest = digest_type::hash( std::make_pair(header_bmroot, main.control->head_block_state_legacy()->pending_schedule.schedule_hash) );
copy_b->producer_signature = main.get_private_key(config::system_account_name, "active").sign(sig_digest);
}

// Push block with invalid transaction to other chain
tester validator;
T validator;
auto btf = validator.control->create_block_handle_future( copy_b->calculate_id(), copy_b );
validator.control->abort_block();
controller::block_report br;
Expand All @@ -54,9 +62,9 @@ BOOST_AUTO_TEST_CASE(block_with_invalid_tx_test)

}

BOOST_AUTO_TEST_CASE(block_with_invalid_tx_mroot_test)
BOOST_AUTO_TEST_CASE_TEMPLATE( block_with_invalid_tx_mroot_test, T, testers )
{
tester main;
T main;

// First we create a valid block with valid transaction
main.create_account("newacc"_n);
Expand All @@ -77,12 +85,16 @@ BOOST_AUTO_TEST_CASE(block_with_invalid_tx_mroot_test)
copy_b->transactions.back().trx = std::move(invalid_packed_tx);

// Re-sign the block
auto header_bmroot = digest_type::hash( std::make_pair( copy_b->digest(), main.control->head_block_state_legacy()->blockroot_merkle.get_root() ) );
auto sig_digest = digest_type::hash( std::make_pair(header_bmroot, main.control->head_block_state_legacy()->pending_schedule.schedule_hash) );
copy_b->producer_signature = main.get_private_key(config::system_account_name, "active").sign(sig_digest);
if constexpr (std::is_same_v<T, savanna_tester>) {
copy_b->producer_signature = main.get_private_key(config::system_account_name, "active").sign(copy_b->calculate_id());
} else {
auto header_bmroot = digest_type::hash( std::make_pair( copy_b->digest(), main.control->head_block_state_legacy()->blockroot_merkle.get_root() ) );
auto sig_digest = digest_type::hash( std::make_pair(header_bmroot, main.control->head_block_state_legacy()->pending_schedule.schedule_hash) );
copy_b->producer_signature = main.get_private_key(config::system_account_name, "active").sign(sig_digest);
}

// Push block with invalid transaction to other chain
tester validator;
T validator;
auto btf = validator.control->create_block_handle_future( copy_b->calculate_id(), copy_b );
validator.control->abort_block();
controller::block_report br;
Expand All @@ -93,6 +105,7 @@ BOOST_AUTO_TEST_CASE(block_with_invalid_tx_mroot_test)
}) ;
}

template <typename T>
std::pair<signed_block_ptr, signed_block_ptr> corrupt_trx_in_block(validating_tester& main, account_name act_name) {
// First we create a valid block with valid transaction
main.create_account(act_name);
Expand All @@ -115,20 +128,29 @@ std::pair<signed_block_ptr, signed_block_ptr> corrupt_trx_in_block(validating_te
const auto& trxs = copy_b->transactions;
for( const auto& a : trxs )
trx_digests.emplace_back( a.digest() );
copy_b->transaction_mroot = calculate_merkle_legacy( std::move(trx_digests) );
if constexpr (std::is_same_v<T, savanna_tester>) {
copy_b->transaction_mroot = calculate_merkle( std::move(trx_digests) );
} else {
copy_b->transaction_mroot = calculate_merkle_legacy( std::move(trx_digests) );
}

// Re-sign the block
auto header_bmroot = digest_type::hash( std::make_pair( copy_b->digest(), main.control->head_block_state_legacy()->blockroot_merkle.get_root() ) );
auto sig_digest = digest_type::hash( std::make_pair(header_bmroot, main.control->head_block_state_legacy()->pending_schedule.schedule_hash) );
copy_b->producer_signature = main.get_private_key(b->producer, "active").sign(sig_digest);
if constexpr (std::is_same_v<T, savanna_tester>) {
copy_b->producer_signature = main.get_private_key(b->producer, "active").sign(copy_b->calculate_id());
} else {
auto header_bmroot = digest_type::hash( std::make_pair( copy_b->digest(), main.control->head_block_state_legacy()->blockroot_merkle.get_root() ) );
auto sig_digest = digest_type::hash( std::make_pair(header_bmroot, main.control->head_block_state_legacy()->pending_schedule.schedule_hash) );
copy_b->producer_signature = main.get_private_key(b->producer, "active").sign(sig_digest);
}

return std::pair<signed_block_ptr, signed_block_ptr>(b, copy_b);
}

// verify that a block with a transaction with an incorrect signature, is blindly accepted from a trusted producer
BOOST_AUTO_TEST_CASE(trusted_producer_test)
BOOST_AUTO_TEST_CASE_TEMPLATE( trusted_producer_test, T, validating_testers )
{
flat_set<account_name> trusted_producers = { "defproducera"_n, "defproducerc"_n };
validating_tester main(trusted_producers);
T main(trusted_producers);
// only using validating_tester to keep the 2 chains in sync, not to validate that the validating_node matches the main node,
// since it won't be
main.skip_validate = true;
Expand All @@ -146,15 +168,15 @@ BOOST_AUTO_TEST_CASE(trusted_producer_test)
b = main.produce_block();
}

auto blocks = corrupt_trx_in_block(main, "tstproducera"_n);
auto blocks = corrupt_trx_in_block<T>(main, "tstproducera"_n);
main.validate_push_block( blocks.second );
}

// like trusted_producer_test, except verify that any entry in the trusted_producer list is accepted
BOOST_AUTO_TEST_CASE(trusted_producer_verify_2nd_test)
BOOST_AUTO_TEST_CASE_TEMPLATE( trusted_producer_verify_2nd_test, T, validating_testers )
{
flat_set<account_name> trusted_producers = { "defproducera"_n, "defproducerc"_n };
validating_tester main(trusted_producers);
T main(trusted_producers);
// only using validating_tester to keep the 2 chains in sync, not to validate that the validating_node matches the main node,
// since it won't be
main.skip_validate = true;
Expand All @@ -172,15 +194,15 @@ BOOST_AUTO_TEST_CASE(trusted_producer_verify_2nd_test)
b = main.produce_block();
}

auto blocks = corrupt_trx_in_block(main, "tstproducera"_n);
auto blocks = corrupt_trx_in_block<T>(main, "tstproducera"_n);
main.validate_push_block( blocks.second );
}

// verify that a block with a transaction with an incorrect signature, is rejected if it is not from a trusted producer
BOOST_AUTO_TEST_CASE(untrusted_producer_test)
BOOST_AUTO_TEST_CASE_TEMPLATE( untrusted_producer_test, T, validating_testers )
{
flat_set<account_name> trusted_producers = { "defproducera"_n, "defproducerc"_n };
validating_tester main(trusted_producers);
T main(trusted_producers);
// only using validating_tester to keep the 2 chains in sync, not to validate that the validating_node matches the main node,
// since it won't be
main.skip_validate = true;
Expand All @@ -198,7 +220,7 @@ BOOST_AUTO_TEST_CASE(untrusted_producer_test)
b = main.produce_block();
}

auto blocks = corrupt_trx_in_block(main, "tstproducera"_n);
auto blocks = corrupt_trx_in_block<T>(main, "tstproducera"_n);
BOOST_REQUIRE_EXCEPTION(main.validate_push_block( blocks.second ), fc::exception ,
[] (const fc::exception &e)->bool {
return e.code() == unsatisfied_authorization::code_value ;
Expand All @@ -208,11 +230,11 @@ BOOST_AUTO_TEST_CASE(untrusted_producer_test)
/**
* Ensure that the block broadcasted by producing node and receiving node is identical
*/
BOOST_AUTO_TEST_CASE(broadcasted_block_test)
BOOST_AUTO_TEST_CASE_TEMPLATE( broadcasted_block_test, T, testers )
{

tester producer_node;
tester receiving_node;
T producer_node;
T receiving_node;

signed_block_ptr bcasted_blk_by_prod_node;
signed_block_ptr bcasted_blk_by_recv_node;
Expand Down
22 changes: 11 additions & 11 deletions unittests/chain_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ BOOST_AUTO_TEST_CASE( replace_producer_keys ) try {
BOOST_REQUIRE(old_version == pending_version);
BOOST_REQUIRE(pending_version == old_pending_version);

const auto& gpo = tester.control->db().get<global_property_object>();
const auto& gpo = tester.control->db().template get<global_property_object>();
BOOST_REQUIRE(!gpo.proposed_schedule_block_num);
BOOST_REQUIRE(gpo.proposed_schedule.version == 0);
BOOST_REQUIRE(gpo.proposed_schedule.producers.empty());
Expand All @@ -57,12 +57,12 @@ BOOST_AUTO_TEST_CASE( replace_producer_keys ) try {
}
} FC_LOG_AND_RETHROW()

BOOST_AUTO_TEST_CASE( replace_account_keys ) try {
validating_tester tester;
BOOST_AUTO_TEST_CASE_TEMPLATE( replace_account_keys, T, validating_testers ) try {
T tester;
const name usr = config::system_account_name;
const name active_permission = config::active_name;
const auto& rlm = tester.control->get_resource_limits_manager();
const auto* perm = tester.control->db().find<permission_object, by_owner>(boost::make_tuple(usr, active_permission));
const auto* perm = tester.control->db().template find<permission_object, by_owner>(boost::make_tuple(usr, active_permission));
BOOST_REQUIRE(perm != NULL);

const int64_t old_size = (int64_t)(chain::config::billable_size_v<permission_object> + perm->auth.get_billable_size());
Expand All @@ -81,8 +81,8 @@ BOOST_AUTO_TEST_CASE( replace_account_keys ) try {

} FC_LOG_AND_RETHROW()

BOOST_AUTO_TEST_CASE( decompressed_size_over_limit ) try {
tester chain;
BOOST_AUTO_TEST_CASE_TEMPLATE( decompressed_size_over_limit, T, testers ) try {
T chain;

// build a transaction, add cf data, sign
cf_action cfa;
Expand Down Expand Up @@ -116,8 +116,8 @@ BOOST_AUTO_TEST_CASE( decompressed_size_over_limit ) try {
});
} FC_LOG_AND_RETHROW()

BOOST_AUTO_TEST_CASE( decompressed_size_under_limit ) try {
tester chain;
BOOST_AUTO_TEST_CASE_TEMPLATE( decompressed_size_under_limit, T, testers ) try {
T chain;

// build a transaction, add cf data, sign
cf_action cfa;
Expand Down Expand Up @@ -150,9 +150,9 @@ BOOST_AUTO_TEST_CASE( decompressed_size_under_limit ) try {
} FC_LOG_AND_RETHROW()

// verify accepted_block signals validated blocks
BOOST_AUTO_TEST_CASE( signal_validated_blocks ) try {
tester chain;
tester validator;
BOOST_AUTO_TEST_CASE_TEMPLATE( signal_validated_blocks, T, testers ) try {
T chain;
T validator;

signed_block_ptr accepted_block;
block_id_type accepted_id;
Expand Down
8 changes: 4 additions & 4 deletions unittests/database_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ using namespace eosio::testing;
BOOST_AUTO_TEST_SUITE(database_tests)

// Simple tests of undo infrastructure
BOOST_AUTO_TEST_CASE(undo_test) {
BOOST_AUTO_TEST_CASE_TEMPLATE( undo_test, T, validating_testers ) {
try {
validating_tester test;
T test;

// Bypass read-only restriction on state DB access for this unit test which really needs to mutate the DB to properly conduct its test.
eosio::chain::database& db = const_cast<eosio::chain::database&>( test.control->db() );
Expand All @@ -39,9 +39,9 @@ BOOST_AUTO_TEST_SUITE(database_tests)
}

// Test the block fetching methods on database, fetch_bock_by_id, and fetch_block_by_number
BOOST_AUTO_TEST_CASE(get_blocks) {
BOOST_AUTO_TEST_CASE_TEMPLATE( get_blocks, T, validating_testers ) {
try {
validating_tester test;
T test;
vector<block_id_type> block_ids;

const uint32_t num_of_blocks_to_prod = 200;
Expand Down
30 changes: 18 additions & 12 deletions unittests/restart_chain_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,14 @@ FC_REFLECT(cf_action, (payload)(cfd_idx))
#define DUMMY_ACTION_DEFAULT_B 0xab11cd1244556677
#define DUMMY_ACTION_DEFAULT_C 0x7451ae12

template <typename T>
class replay_tester : public base_tester {
public:
template <typename OnAppliedTrx>
replay_tester(controller::config config, const genesis_state& genesis, OnAppliedTrx&& on_applied_trx) {
if constexpr (std::is_same_v<T, savanna_tester>) {
is_savanna = true;
}
cfg = config;
base_tester::open(make_protocol_feature_set(), genesis.compute_chain_id(), [&genesis,&control=this->control, &on_applied_trx]() {
control->applied_transaction().connect(on_applied_trx);
Expand Down Expand Up @@ -86,15 +90,15 @@ class replay_tester : public base_tester {

BOOST_AUTO_TEST_SUITE(restart_chain_tests)

BOOST_AUTO_TEST_CASE(test_existing_state_without_block_log) {
tester chain;
BOOST_AUTO_TEST_CASE_TEMPLATE( test_existing_state_without_block_log, T, testers ) {
T chain;

std::vector<signed_block_ptr> blocks;
blocks.push_back(chain.produce_block());
blocks.push_back(chain.produce_block());
blocks.push_back(chain.produce_block());

tester other;
T other;
for (const auto& new_block : blocks) {
other.push_block(new_block);
}
Expand All @@ -116,15 +120,15 @@ BOOST_AUTO_TEST_CASE(test_existing_state_without_block_log) {
}
}

BOOST_AUTO_TEST_CASE(test_restart_with_different_chain_id) {
tester chain;
BOOST_AUTO_TEST_CASE_TEMPLATE( test_restart_with_different_chain_id, T, testers ) {
T chain;

std::vector<signed_block_ptr> blocks;
blocks.push_back(chain.produce_block());
blocks.push_back(chain.produce_block());
blocks.push_back(chain.produce_block());

tester other;
T other;
for (const auto& new_block : blocks) {
other.push_block(new_block);
}
Expand All @@ -139,8 +143,8 @@ BOOST_AUTO_TEST_CASE(test_restart_with_different_chain_id) {
fc_exception_message_starts_with("chain ID in state "));
}

BOOST_AUTO_TEST_CASE(test_restart_from_block_log) {
tester chain;
BOOST_AUTO_TEST_CASE_TEMPLATE( test_restart_from_block_log, T, testers ) {
T chain;

chain.create_account("replay1"_n);
chain.produce_blocks(1);
Expand Down Expand Up @@ -169,8 +173,8 @@ BOOST_AUTO_TEST_CASE(test_restart_from_block_log) {
BOOST_REQUIRE_NO_THROW(from_block_log_chain.control->get_account("replay3"_n));
}

BOOST_AUTO_TEST_CASE(test_light_validation_restart_from_block_log) {
tester chain(setup_policy::full);
BOOST_AUTO_TEST_CASE_TEMPLATE( test_light_validation_restart_from_block_log, T, testers ) {
T chain(setup_policy::full);

chain.create_account("testapi"_n);
chain.create_account("dummy"_n);
Expand Down Expand Up @@ -214,7 +218,7 @@ BOOST_AUTO_TEST_CASE(test_light_validation_restart_from_block_log) {
remove_existing_states(copied_config);
transaction_trace_ptr other_trace;

replay_tester from_block_log_chain(copied_config, *genesis,
replay_tester<T> from_block_log_chain(copied_config, *genesis,
[&](std::tuple<const transaction_trace_ptr&, const packed_transaction_ptr&> x) {
auto& t = std::get<0>(x);
if (t && t->id == trace->id) {
Expand All @@ -232,7 +236,9 @@ BOOST_AUTO_TEST_CASE(test_light_validation_restart_from_block_log) {
auto check_action_traces = [](const auto& t, const auto& ot) {
BOOST_CHECK_EQUAL("", ot.console); // cfa not executed for replay
BOOST_CHECK_EQUAL(t.receipt->global_sequence, ot.receipt->global_sequence);
BOOST_CHECK_EQUAL(t.digest_legacy(), ot.digest_legacy()); // digest_legacy because test doesn't switch to Savanna
// both legacy and savanna digests should be the same
BOOST_CHECK_EQUAL(t.digest_legacy(), ot.digest_legacy());
BOOST_CHECK_EQUAL(t.digest_savanna(), ot.digest_savanna());
};

BOOST_CHECK(other_trace->action_traces.at(0).context_free); // cfa
Expand Down

0 comments on commit 2187c80

Please sign in to comment.