Skip to content

Commit

Permalink
GH-985 Add unittest for interrupt_transaction
Browse files Browse the repository at this point in the history
  • Loading branch information
heifner committed Oct 30, 2024
1 parent 73120f5 commit 2ff14e7
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 6 deletions.
35 changes: 29 additions & 6 deletions tests/chain_test_utils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,17 @@ struct reqactivated {
}
};

inline private_key_type get_private_key( name keyname, string role ) {
if (keyname == config::system_account_name)
return private_key_type::regenerate<fc::ecc::private_key_shim>(fc::sha256::hash(std::string("nathan")));

return private_key_type::regenerate<fc::ecc::private_key_shim>(fc::sha256::hash(keyname.to_string()+role));
}

inline public_key_type get_public_key( name keyname, string role ){
return get_private_key( keyname, role ).get_public_key();
}

// Create a read-only trx that works with bios reqactivated action
inline auto make_bios_ro_trx(eosio::chain::controller& control) {
const auto& pfm = control.get_protocol_feature_manager();
Expand All @@ -66,12 +77,7 @@ inline auto make_bios_ro_trx(eosio::chain::controller& control) {
inline auto push_input_trx(appbase::scoped_app& app, eosio::chain::controller& control, account_name account, signed_transaction& trx) {
trx.expiration = fc::time_point_sec{fc::time_point::now() + fc::seconds(30)};
trx.set_reference_block( control.head().id() );
if (account == config::system_account_name) {
auto default_priv_key = private_key_type::regenerate<fc::ecc::private_key_shim>(fc::sha256::hash(std::string("nathan")));
trx.sign(default_priv_key, control.get_chain_id());
} else {
trx.sign(testing::tester::get_private_key(account, "active"), control.get_chain_id());
}
trx.sign(get_private_key(account, "active"), control.get_chain_id());
auto ptrx = std::make_shared<packed_transaction>( trx, packed_transaction::compression_type::zlib );

auto trx_promise = std::make_shared<std::promise<transaction_trace_ptr>>();
Expand Down Expand Up @@ -120,6 +126,23 @@ inline auto set_code(appbase::scoped_app& app, eosio::chain::controller& control
return push_input_trx(app, control, account, trx);
}

inline transaction_trace_ptr create_account(appbase::scoped_app& app, eosio::chain::controller& control, account_name a, account_name creator) {
signed_transaction trx;

authority owner_auth{ get_public_key( a, "owner" ) };
authority active_auth{ get_public_key( a, "active" ) };

trx.actions.emplace_back( vector<permission_level>{{creator,config::active_name}},
chain::newaccount{
.creator = creator,
.name = a,
.owner = owner_auth,
.active = active_auth,
});

return push_input_trx(app, control, creator, trx);
}

inline void activate_protocol_features_set_bios_contract(appbase::scoped_app& app, chain_plugin* chain_plug) {
using namespace appbase;

Expand Down
49 changes: 49 additions & 0 deletions unittests/checktime_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,55 @@ BOOST_AUTO_TEST_CASE_TEMPLATE( checktime_fail_tests, T, validating_testers ) { t
BOOST_REQUIRE_EQUAL( t.validate(), true );
} FC_LOG_AND_RETHROW() }

BOOST_AUTO_TEST_CASE( checktime_interrupt_test) { try {
savanna_tester t;
savanna_tester other;
auto block = t.produce_block();
other.push_block(block);
t.create_account( "testapi"_n );
t.set_code( "testapi"_n, test_contracts::test_api_wasm() );
block = t.produce_block();
other.push_block(block);

auto [trace, b] = CALL_TEST_FUNCTION_WITH_BLOCK( t, "test_checktime", "checktime_pass", {});
BOOST_REQUIRE_EQUAL( b->transactions.size(), 1 );

// Make a copy of the valid block and swicth the checktime_pass transaction with checktime_failure
auto copy_b = std::make_shared<signed_block>(b->clone());
auto signed_tx = std::get<packed_transaction>(copy_b->transactions.back().trx).get_signed_transaction();
auto& act = signed_tx.actions.back();
constexpr chain::name checktime_fail_n{WASM_TEST_ACTION("test_checktime", "checktime_failure")};
act.name = checktime_fail_n;
act.data = fc::raw::pack(10000000000000000000ULL);
// Re-sign the transaction
signed_tx.signatures.clear();
signed_tx.sign(t.get_private_key("testapi"_n, "active"), t.get_chain_id());
// Replace the transaction
auto new_packed_tx = packed_transaction(signed_tx);
copy_b->transactions.back().trx = std::move(new_packed_tx);

// Re-calculate the transaction merkle
deque<digest_type> trx_digests;
const auto& trxs = copy_b->transactions;
for( const auto& a : trxs )
trx_digests.emplace_back( a.digest() );
copy_b->transaction_mroot = calculate_merkle( std::move(trx_digests) );
// Re-sign the block
copy_b->producer_signature = t.get_private_key(config::system_account_name, "active").sign(copy_b->calculate_id());

std::thread th( [&c=*other.control]() {
std::this_thread::sleep_for( std::chrono::milliseconds(50) );
c.interrupt_transaction();
} );

// apply block, caught in an "infinite" loop
BOOST_CHECK_EXCEPTION( other.push_block(copy_b), fc::exception,
[](const fc::exception& e) { return e.code() == interrupt_exception::code_value; } );

th.join();

} FC_LOG_AND_RETHROW() }

BOOST_AUTO_TEST_CASE_TEMPLATE( checktime_pause_max_trx_cpu_extended_test, T, testers ) { try {
fc::temp_directory tempdir;
auto conf_genesis = tester::default_config( tempdir );
Expand Down

0 comments on commit 2ff14e7

Please sign in to comment.