diff --git a/tests/core_tests/chaingen_main.cpp b/tests/core_tests/chaingen_main.cpp index 6a8f021b..641f1908 100644 --- a/tests/core_tests/chaingen_main.cpp +++ b/tests/core_tests/chaingen_main.cpp @@ -946,6 +946,7 @@ int main(int argc, char* argv[]) GENERATE_AND_PLAY(hard_fork_1_unlock_time_2_in_normal_tx); GENERATE_AND_PLAY(hard_fork_1_unlock_time_2_in_coinbase); GENERATE_AND_PLAY(hard_fork_1_chain_switch_pow_only); + GENERATE_AND_PLAY(hard_fork_1_checkpoint_basic_test); //GENERATE_AND_PLAY(gen_block_reward); */ diff --git a/tests/core_tests/hard_fork_1.cpp b/tests/core_tests/hard_fork_1.cpp index d9ed5a2d..41f561e7 100644 --- a/tests/core_tests/hard_fork_1.cpp +++ b/tests/core_tests/hard_fork_1.cpp @@ -4,7 +4,7 @@ #include "chaingen.h" #include "hard_fork_1.h" -//#include "pos_validation.h" +#include "pos_block_builder.h" //#include "tx_builder.h" //#include "random_helper.h" @@ -82,7 +82,7 @@ bool hard_fork_1_unlock_time_2_in_normal_tx::generate(std::vector& return true; } + +//------------------------------------------------------------------------------ + +hard_fork_1_checkpoint_basic_test::hard_fork_1_checkpoint_basic_test() + : hard_fork_1_base_test(13) + , checkpoints_test() +{ +} + +bool hard_fork_1_checkpoint_basic_test::generate(std::vector& events) const +{ + bool r = false; + GENERATE_ACCOUNT(miner_acc); + GENERATE_ACCOUNT(alice_acc); + MAKE_GENESIS_BLOCK(events, blk_0, miner_acc, test_core_time::get_time()); + generator.set_hardfork_height(m_hardfork_height); + DO_CALLBACK(events, "configure_core"); + DO_CALLBACK_PARAMS(events, "set_checkpoint", params_checkpoint(CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 2)); + REWIND_BLOCKS_N_WITH_TIME(events, blk_0r, blk_0, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW); + + // + // before hardfork 1 + // + + std::vector sources; + std::vector destinations; + CHECK_AND_ASSERT_MES(fill_tx_sources_and_destinations(events, blk_0r, miner_acc, alice_acc, MK_TEST_COINS(1), TESTS_DEFAULT_FEE, 0, sources, destinations), false, ""); + + // set unlock_time_2, should be rejected before hardfork 1 + std::vector extra; + etc_tx_details_unlock_time2 ut2 = AUTO_VAL_INIT(ut2); + ut2.unlock_time_array.resize(destinations.size()); + ut2.unlock_time_array[0] = 1; // not zero, unlocked from block 1 + extra.push_back(ut2); + transaction tx_0 = AUTO_VAL_INIT(tx_0); + crypto::secret_key tx_sec_key; + r = construct_tx(miner_acc.get_keys(), sources, destinations, extra, empty_attachment, tx_0, tx_sec_key, 0 /* unlock time 1 is zero and thus will not be set */); + CHECK_AND_ASSERT_MES(r, false, "construct_tx failed"); + // tx_0 should be accepted + events.push_back(tx_0); + + DO_CALLBACK(events, "mark_invalid_block"); + MAKE_NEXT_BLOCK_TX1(events, blk_1_bad, blk_0r, miner_acc, tx_0); // should be rejected because of tx_0 + DO_CALLBACK_PARAMS(events, "check_tx_pool_count", static_cast(1)); + DO_CALLBACK(events, "clear_tx_pool"); + + MAKE_NEXT_BLOCK(events, blk_1, blk_0r, miner_acc); + MAKE_NEXT_BLOCK(events, blk_2, blk_1, miner_acc); // <-- checkpoint + + MAKE_NEXT_BLOCK(events, blk_3, blk_2, miner_acc); // <-- hard fork + MAKE_NEXT_BLOCK(events, blk_4, blk_3, miner_acc); + // make sure hardfork went okay + CHECK_AND_ASSERT_MES(blk_3.major_version != CURRENT_BLOCK_MAJOR_VERSION && blk_4.major_version == CURRENT_BLOCK_MAJOR_VERSION, false, "hardfork did not happen as expected"); + + return true; +} + +//------------------------------------------------------------------------------ + +hard_fork_1_pos_and_locked_coins::hard_fork_1_pos_and_locked_coins() + : hard_fork_1_base_test(13) // hardfork height + , m_unique_amount(TESTS_DEFAULT_FEE * 9) +{ + REGISTER_CALLBACK_METHOD(hard_fork_1_pos_and_locked_coins, check_outputs_with_unique_amount); +} + +bool hard_fork_1_pos_and_locked_coins::generate(std::vector& events) const +{ + bool r = false; + GENERATE_ACCOUNT(miner_acc); + GENERATE_ACCOUNT(alice_acc); + MAKE_GENESIS_BLOCK(events, blk_0, miner_acc, test_core_time::get_time()); + generator.set_hardfork_height(m_hardfork_height); + DO_CALLBACK(events, "configure_core"); + REWIND_BLOCKS_N_WITH_TIME(events, blk_0r, blk_0, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 3); + + DO_CALLBACK_PARAMS(events, "check_outputs_with_unique_amount", static_cast(0)); + + // create few locked outputs in the blockchain with unique amount + std::vector extra; + etc_tx_details_unlock_time ut = AUTO_VAL_INIT(ut); + ut.v = 100; // locked until block 100 + extra.push_back(ut); + + std::vector destinations; + for (size_t i = 0; i < 5; ++i) + destinations.push_back(tx_destination_entry(m_unique_amount, alice_acc.get_public_address())); + + transaction tx_0 = AUTO_VAL_INIT(tx_0); + r = construct_tx_to_key(events, tx_0, blk_0r, miner_acc, destinations, TESTS_DEFAULT_FEE, 0, 0, extra); + CHECK_AND_ASSERT_MES(r, false, "construct_tx failed"); + events.push_back(tx_0); + + MAKE_NEXT_BLOCK_TX1(events, blk_1, blk_0r, miner_acc, tx_0); + + DO_CALLBACK_PARAMS(events, "check_outputs_with_unique_amount", static_cast(5)); + + + block blk_0a; + { + crypto::hash prev_id = get_block_hash(blk_0); + size_t height = get_block_height(blk_0) + 1; + currency::wide_difficulty_type diff = generator.get_difficulty_for_next_block(prev_id, false); + + const transaction& stake = blk_0.miner_tx; + crypto::public_key stake_tx_pub_key = get_tx_pub_key_from_extra(stake); + size_t stake_output_idx = 0; + size_t stake_output_gidx = 0; + uint64_t stake_output_amount = stake.vout[stake_output_idx].amount; + crypto::key_image stake_output_key_image; + keypair kp; + generate_key_image_helper(miner_acc.get_keys(), stake_tx_pub_key, stake_output_idx, kp, stake_output_key_image); + crypto::public_key stake_output_pubkey = boost::get(stake.vout[stake_output_idx].target).key; + + pos_block_builder pb; + pb.step1_init_header(height, prev_id); + pb.step2_set_txs(std::vector()); + pb.step3_build_stake_kernel(stake_output_amount, stake_output_gidx, stake_output_key_image, diff, prev_id, null_hash, blk_0r.timestamp); + pb.step4_generate_coinbase_tx(generator.get_timestamps_median(prev_id), generator.get_already_generated_coins(blk_0r), miner_acc.get_public_address()); + pb.step5_sign(stake_tx_pub_key, stake_output_idx, stake_output_pubkey, miner_acc); + blk_0a = pb.m_block; + } + + return true; +} + +bool hard_fork_1_pos_and_locked_coins::check_outputs_with_unique_amount(currency::core& c, size_t ev_index, const std::vector& events) +{ + size_t expected_outputs_count = 0; + const std::string& params = boost::get(events[ev_index]).callback_params; + CHECK_AND_ASSERT_MES(epee::string_tools::hex_to_pod(params, expected_outputs_count), false, "hex_to_pod failed, params = " << params); + + std::list pub_keys; + bool r = c.get_outs(m_unique_amount, pub_keys); + + CHECK_AND_ASSERT_MES(r && pub_keys.size() == expected_outputs_count, false, "amount " << print_money_brief(m_unique_amount) << ": " << pub_keys.size() << " != " << expected_outputs_count); + + return true; +} diff --git a/tests/core_tests/hard_fork_1.h b/tests/core_tests/hard_fork_1.h index ae5e9793..261dcd8b 100644 --- a/tests/core_tests/hard_fork_1.h +++ b/tests/core_tests/hard_fork_1.h @@ -4,9 +4,10 @@ #pragma once #include "chaingen.h" -#include "wallet_tests_basic.h" +//#include "wallet_tests_basic.h" +#include "checkpoints_tests.h" -struct hard_fork_1_base_test : public test_chain_unit_enchanced +struct hard_fork_1_base_test : virtual public test_chain_unit_enchanced { hard_fork_1_base_test(size_t hardfork_height); bool configure_core(currency::core& c, size_t ev_index, const std::vector& events); @@ -31,3 +32,19 @@ struct hard_fork_1_chain_switch_pow_only : public hard_fork_1_base_test hard_fork_1_chain_switch_pow_only(); bool generate(std::vector& events) const; }; + +struct hard_fork_1_checkpoint_basic_test : public hard_fork_1_base_test, public checkpoints_test +{ + hard_fork_1_checkpoint_basic_test(); + bool generate(std::vector& events) const; +}; + +struct hard_fork_1_pos_and_locked_coins : public hard_fork_1_base_test +{ + hard_fork_1_pos_and_locked_coins(); + bool generate(std::vector& events) const; + + bool check_outputs_with_unique_amount(currency::core& c, size_t ev_index, const std::vector& events); + + uint64_t m_unique_amount; +};