diff --git a/src/currency_core/blockchain_storage.cpp b/src/currency_core/blockchain_storage.cpp index ac95a829..6106feac 100644 --- a/src/currency_core/blockchain_storage.cpp +++ b/src/currency_core/blockchain_storage.cpp @@ -1514,6 +1514,7 @@ bool blockchain_storage::handle_alternative_block(const block& b, const crypto:: alt_block_extended_info abei = AUTO_VAL_INIT(abei); abei.bl = b; + abei.timestamp = m_core_runtime_config.get_core_time(); abei.height = alt_chain.size() ? it_prev->second.height + 1 : *ptr_main_prev + 1; CHECK_AND_ASSERT_MES_CUSTOM(coinbase_height == abei.height, false, bvc.m_verification_failed = true, "block coinbase height doesn't match with altchain height, declined"); uint64_t connection_height = alt_chain.size() ? alt_chain.front()->second.height:abei.height; @@ -1665,6 +1666,11 @@ bool blockchain_storage::handle_alternative_block(const block& b, const crypto:: return r; } bvc.added_to_altchain = true; + + //protect ourself from altchains container flood + if (m_alternative_chains.size() > m_core_runtime_config.max_alt_blocks) + prune_aged_alt_blocks(); + return true; }else { @@ -4210,6 +4216,12 @@ bool blockchain_storage::prune_aged_alt_blocks() CRITICAL_REGION_LOCAL1(m_alternative_chains_lock); uint64_t current_height = get_current_blockchain_size(); + size_t count_to_delete = 0; + if(m_alternative_chains.size() > m_core_runtime_config.max_alt_blocks) + count_to_delete = m_alternative_chains.size() - m_core_runtime_config.max_alt_blocks; + + std::map alts_to_delete; + for(auto it = m_alternative_chains.begin(); it != m_alternative_chains.end();) { if (current_height > it->second.height && current_height - it->second.height > CURRENCY_ALT_BLOCK_LIVETIME_COUNT) @@ -4218,9 +4230,28 @@ bool blockchain_storage::prune_aged_alt_blocks() } else { + if (count_to_delete) + { + if (!alts_to_delete.size()) + alts_to_delete[it->second.timestamp] = it; + else + { + if (it->second.timestamp >= alts_to_delete.rbegin()->first) + alts_to_delete[it->second.timestamp] = it; + + if (alts_to_delete.size() > count_to_delete) + alts_to_delete.erase(alts_to_delete.begin()); + } + } + ++it; } } + //now, if there was count_to_delete we should erase most oldest entries of altblocks + for (auto& itd : alts_to_delete) + { + m_alternative_chains.erase(itd.second); + } return true; } @@ -4357,11 +4388,11 @@ bool blockchain_storage::validate_pos_block(const block& b, //check actual time if it there uint64_t actual_ts = get_actual_timestamp(b); - if ((actual_ts > b.timestamp && actual_ts - b.timestamp > POS_MAC_ACTUAL_TIMESTAMP_TO_MINED) || - (actual_ts < b.timestamp && b.timestamp - actual_ts > POS_MAC_ACTUAL_TIMESTAMP_TO_MINED) + if ((actual_ts > b.timestamp && actual_ts - b.timestamp > POS_MAX_ACTUAL_TIMESTAMP_TO_MINED) || + (actual_ts < b.timestamp && b.timestamp - actual_ts > POS_MAX_ACTUAL_TIMESTAMP_TO_MINED) ) { - LOG_PRINT_L0("PoS block actual timestamp " << actual_ts << " differs from b.timestamp " << b.timestamp << " by " << ((int64_t)actual_ts - (int64_t)b.timestamp) << " s, it's more than allowed " << POS_MAC_ACTUAL_TIMESTAMP_TO_MINED << " s."); + LOG_PRINT_L0("PoS block actual timestamp " << actual_ts << " differs from b.timestamp " << b.timestamp << " by " << ((int64_t)actual_ts - (int64_t)b.timestamp) << " s, it's more than allowed " << POS_MAX_ACTUAL_TIMESTAMP_TO_MINED << " s."); return false; } @@ -4677,6 +4708,7 @@ bool blockchain_storage::handle_block_to_main_chain(const block& bl, const crypt size_t tx_processed_count = 0; uint64_t fee_summary = 0; + uint64_t burned_coins = 0; for(const crypto::hash& tx_id : bl.tx_hashes) { @@ -4716,6 +4748,7 @@ bool blockchain_storage::handle_block_to_main_chain(const block& bl, const crypt return false; } TIME_MEASURE_FINISH_PD(tx_check_inputs_time); + burned_coins += get_burned_amount(tx); TIME_MEASURE_START_PD(tx_prapare_append); uint64_t current_bc_size = get_current_blockchain_size(); @@ -4824,7 +4857,14 @@ bool blockchain_storage::handle_block_to_main_chain(const block& bl, const crypt ////////////////////////////////////////////////////////////////////////// //etc - bei.already_generated_coins = already_generated_coins + base_reward; + if (already_generated_coins < burned_coins) + { + LOG_ERROR("Condition failed: already_generated_coins(" << already_generated_coins << ") >= burned_coins(" << burned_coins << ")"); + purge_block_data_from_blockchain(bl, tx_processed_count); + bvc.m_verification_failed = true; + return false; + } + bei.already_generated_coins = already_generated_coins - burned_coins + base_reward; auto blocks_index_ptr = m_db_blocks_index.get(id); if (blocks_index_ptr) diff --git a/src/currency_core/blockchain_storage.h b/src/currency_core/blockchain_storage.h index d584512d..ef553de1 100644 --- a/src/currency_core/blockchain_storage.h +++ b/src/currency_core/blockchain_storage.h @@ -153,6 +153,9 @@ namespace currency // {amount -> pub_keys} map of outputs' pub_keys appeared in this alt block ( index_in_vector == output_gindex - gindex_lookup_table[output_amount] ) std::map > outputs_pub_keys; + + //date added to alt chain storage + uint64_t timestamp; }; typedef std::unordered_map alt_chain_container; //typedef std::list alt_chain_type; @@ -435,6 +438,7 @@ namespace currency bool rebuild_tx_fee_medians(); bool validate_all_aliases_for_new_median_mode(); bool print_tx_outputs_lookup(const crypto::hash& tx_id) const; + uint64_t get_last_x_block_height(bool pos)const; private: //-------------- DB containers -------------- @@ -614,7 +618,6 @@ namespace currency //POS wide_difficulty_type get_adjusted_cumulative_difficulty_for_next_pos(wide_difficulty_type next_diff)const; wide_difficulty_type get_adjusted_cumulative_difficulty_for_next_alt_pos(alt_chain_type& alt_chain, uint64_t block_height, wide_difficulty_type next_diff, uint64_t connection_height)const; - uint64_t get_last_x_block_height(bool pos)const; wide_difficulty_type get_last_alt_x_block_cumulative_precise_difficulty(const alt_chain_type& alt_chain, uint64_t block_height, bool pos, wide_difficulty_type& cumulative_diff_precise_adj)const; wide_difficulty_type get_last_alt_x_block_cumulative_precise_adj_difficulty(const alt_chain_type& alt_chain, uint64_t block_height, bool pos) const; size_t get_current_sequence_factor_for_alt(alt_chain_type& alt_chain, bool pos, uint64_t connection_height)const; diff --git a/src/currency_core/core_runtime_config.h b/src/currency_core/core_runtime_config.h index f79e3e80..8e9d94b0 100644 --- a/src/currency_core/core_runtime_config.h +++ b/src/currency_core/core_runtime_config.h @@ -19,6 +19,7 @@ namespace currency uint64_t tx_pool_min_fee; uint64_t tx_default_fee; uint64_t hard_fork1_starts_after_height; + uint64_t max_alt_blocks; crypto::public_key alias_validation_pubkey; core_time_func_t get_core_time; @@ -35,6 +36,7 @@ namespace currency pc.pos_minimum_heigh = POS_START_HEIGHT; pc.tx_pool_min_fee = TX_MINIMUM_FEE; pc.tx_default_fee = TX_DEFAULT_FEE; + pc.max_alt_blocks = CURRENCY_ALT_BLOCK_MAX_COUNT; pc.hard_fork1_starts_after_height = ZANO_HARDFORK_1_AFTER_HEIGHT; pc.get_core_time = &core_runtime_config::_default_core_time_function; bool r = epee::string_tools::hex_to_pod(ALIAS_SHORT_NAMES_VALIDATION_PUB_KEY, pc.alias_validation_pubkey); diff --git a/src/currency_core/currency_config.h b/src/currency_core/currency_config.h index 3000101a..6e28fe2c 100644 --- a/src/currency_core/currency_config.h +++ b/src/currency_core/currency_config.h @@ -87,8 +87,10 @@ #define CURRENCY_ALT_BLOCK_LIVETIME_COUNT (CURRENCY_BLOCKS_PER_DAY*7)//one week +#define CURRENCY_ALT_BLOCK_MAX_COUNT 43200 //30 days #define CURRENCY_MEMPOOL_TX_LIVETIME 345600 //seconds, 4 days + #ifndef TESTNET #define P2P_DEFAULT_PORT 11121 #define RPC_DEFAULT_PORT 11211 @@ -128,7 +130,7 @@ //PoS definitions #define POS_SCAN_WINDOW 60*10 //seconds // 10 minutes #define POS_SCAN_STEP 15 //seconds -#define POS_MAC_ACTUAL_TIMESTAMP_TO_MINED (POS_SCAN_WINDOW+100) +#define POS_MAX_ACTUAL_TIMESTAMP_TO_MINED (POS_SCAN_WINDOW+100) #define POS_STARTER_KERNEL_HASH "00000000000000000006382a8d8f94588ce93a1351924f6ccb9e07dd287c6e4b" #define POS_MODFIFIER_INTERVAL 10 @@ -192,6 +194,7 @@ #define GUI_INTERNAL_CONFIG "gui_internal_config.bin" + #define CURRENT_TRANSACTION_CHAIN_ENTRY_ARCHIVE_VER 3 #define CURRENT_BLOCK_EXTENDED_INFO_ARCHIVE_VER 1 diff --git a/src/currency_core/currency_format_utils_transactions.cpp b/src/currency_core/currency_format_utils_transactions.cpp index fe9f6bf2..df589f04 100644 --- a/src/currency_core/currency_format_utils_transactions.cpp +++ b/src/currency_core/currency_format_utils_transactions.cpp @@ -32,6 +32,20 @@ namespace currency return expiration_time <= expiration_ts_median + TX_EXPIRATION_MEDIAN_SHIFT; } //--------------------------------------------------------------- + uint64_t get_burned_amount(const transaction& tx) + { + uint64_t res = 0; + for (auto& o : tx.vout) + { + if (o.target.type() == typeid(txout_to_key)) + { + if (boost::get(o.target).key == null_pkey) + res += o.amount; + } + } + return res; + } + //--------------------------------------------------------------- uint64_t get_tx_max_unlock_time(const transaction& tx) { // etc_tx_details_expiration_time have priority over etc_tx_details_expiration_time2 diff --git a/src/currency_core/currency_format_utils_transactions.h b/src/currency_core/currency_format_utils_transactions.h index 82a94fa1..ebace925 100644 --- a/src/currency_core/currency_format_utils_transactions.h +++ b/src/currency_core/currency_format_utils_transactions.h @@ -94,7 +94,7 @@ namespace currency bool is_tx_expired(const transaction& tx, uint64_t expiration_ts_median); - + uint64_t get_burned_amount(const transaction& tx); void get_transaction_prefix_hash(const transaction_prefix& tx, crypto::hash& h); crypto::hash get_transaction_prefix_hash(const transaction_prefix& tx); bool parse_and_validate_tx_from_blob(const blobdata& tx_blob, transaction& tx, crypto::hash& tx_hash); diff --git a/tests/core_tests/chaingen.cpp b/tests/core_tests/chaingen.cpp index 3a404ffe..e172221f 100644 --- a/tests/core_tests/chaingen.cpp +++ b/tests/core_tests/chaingen.cpp @@ -46,10 +46,18 @@ crypto::signature create_invalid_signature() const crypto::signature invalid_signature = create_invalid_signature(); test_generator::test_generator() - : m_wallet_test_core_proxy(new wallet_test_core_proxy()) + : m_wallet_test_core_proxy(new wallet_test_core_proxy()), + m_do_pos_to_low_timestamp(false), + m_last_found_timestamp(0), + m_hardfork_after_heigh(CURRENCY_MAX_BLOCK_NUMBER) { } +void test_generator::set_hardfork_height(uint64_t h) +{ + m_hardfork_after_heigh = h; +} + void test_generator::get_block_chain(std::vector& blockchain, const crypto::hash& head, size_t n) const { crypto::hash curr = head; @@ -142,6 +150,7 @@ void test_generator::add_block(const currency::block& blk, get_block_reward(is_pos_block(blk), misc_utils::median(block_sizes), block_size, already_generated_coins, block_reward, currency::get_block_height(blk)); m_blocks_info[get_block_hash(blk)] = block_info(blk, already_generated_coins + block_reward, block_size, cum_diff, tx_list, ks_hash); + LOG_PRINT_MAGENTA("ADDED_BLOCK[" << get_block_hash(blk) << "][" << (is_pos_block(blk)? "PoS":"PoW") <<"][" << get_block_height(blk) << "][cumul_diff:" << cum_diff << "]", LOG_LEVEL_0); } void test_generator::add_block_info(const block_info& bi) @@ -191,7 +200,11 @@ bool test_generator::construct_block(currency::block& blk, const std::list& tx_list, const std::list& coin_stake_sources)//in case of PoS block { - blk.major_version = BLOCK_MAJOR_VERSION_INITAL; + if (height > m_hardfork_after_heigh) + blk.major_version = CURRENT_BLOCK_MAJOR_VERSION; + else + blk.major_version = BLOCK_MAJOR_VERSION_INITAL; + blk.minor_version = CURRENT_BLOCK_MINOR_VERSION; blk.timestamp = timestamp; blk.prev_id = prev_id; @@ -305,11 +318,13 @@ bool test_generator::construct_block(currency::block& blk, CHECK_AND_ASSERT_MES(r, false, "Failed to find_kernel_and_sign()"); } + uint64_t last_x = get_last_block_of_type(is_pos_block(blk), blocks); + add_block(blk, txs_size, block_sizes, already_generated_coins, - blocks.size() ? blocks.back()->cumul_difficulty + a_diffic: a_diffic, + last_x ? blocks[last_x]->cumul_difficulty + a_diffic: a_diffic, tx_list, kernerl_hash); @@ -469,30 +484,44 @@ bool test_generator::find_kernel(const std::list& accs, uint64_t median_timestamp = get_timestamps_median(blck_chain); wide_difficulty_type basic_diff = 0; - uint64_t i_last_pow_block = get_last_block_of_type(false, blck_chain); - uint64_t expected_avr_timestamp = blck_chain[i_last_pow_block]->b.timestamp + (blck_chain.size() - i_last_pow_block - 1)*DIFFICULTY_POW_TARGET; - uint64_t starter_timestamp = expected_avr_timestamp - POS_SCAN_WINDOW; + uint64_t i_last_pos_block = get_last_block_of_type(true, blck_chain); + + uint64_t last_pos_block_timestamp = 0; + if(i_last_pos_block) + last_pos_block_timestamp = blck_chain[i_last_pos_block]->b.timestamp; + else + last_pos_block_timestamp = blck_chain.back()->b.timestamp - DIFFICULTY_POS_TARGET/2; + + uint64_t starter_timestamp = last_pos_block_timestamp + DIFFICULTY_POS_TARGET; + if (starter_timestamp < median_timestamp) starter_timestamp = median_timestamp; - + m_last_found_timestamp = 0; basic_diff = get_difficulty_for_next_block(blck_chain, false); - - //lets try to find block - for (auto& w : wallets) + if (basic_diff < 10) { - currency::COMMAND_RPC_SCAN_POS::request scan_pos_entries; - bool r = w->get_pos_entries(scan_pos_entries); - CHECK_AND_ASSERT_THROW_MES(r, "Failed to get_pos_entries"); + starter_timestamp -= 90; + } + if (m_do_pos_to_low_timestamp) + starter_timestamp += 60; - for (size_t i = 0; i != scan_pos_entries.pos_entries.size(); i++) + //adjust timestamp starting from timestamp%POS_SCAN_STEP = 0 + //starter_timestamp = starter_timestamp - POS_SCAN_WINDOW; + starter_timestamp = POS_SCAN_STEP - (starter_timestamp%POS_SCAN_STEP) + starter_timestamp; + + for (uint64_t ts = starter_timestamp; ts < starter_timestamp + POS_SCAN_WINDOW/2; ts += POS_SCAN_STEP) + { + //lets try to find block + for (auto& w : wallets) { - //adjust timestamp starting from timestamp%POS_SCAN_STEP = 0 - starter_timestamp = starter_timestamp - POS_SCAN_WINDOW; - starter_timestamp = POS_SCAN_STEP - (starter_timestamp%POS_SCAN_STEP) + starter_timestamp; + currency::COMMAND_RPC_SCAN_POS::request scan_pos_entries; + bool r = w->get_pos_entries(scan_pos_entries); + CHECK_AND_ASSERT_THROW_MES(r, "Failed to get_pos_entries"); - for (uint64_t ts = starter_timestamp; ts < expected_avr_timestamp + POS_SCAN_WINDOW; ts += POS_SCAN_STEP) + for (size_t i = 0; i != scan_pos_entries.pos_entries.size(); i++) { + stake_kernel sk = AUTO_VAL_INIT(sk); uint64_t coindays_weight = 0; build_kernel(scan_pos_entries.pos_entries[i].amount, @@ -509,10 +538,23 @@ bool test_generator::find_kernel(const std::list& accs, continue; else { + if (m_do_pos_to_low_timestamp) + { + if (!m_last_found_timestamp) + { + m_last_found_timestamp = ts; + continue; + } + + if(m_last_found_timestamp >= ts) + continue; + } + //found kernel LOG_PRINT_GREEN("Found kernel: amount=" << print_money(scan_pos_entries.pos_entries[i].amount) << ", index=" << scan_pos_entries.pos_entries[i].index - << ", key_image" << scan_pos_entries.pos_entries[i].keyimage, LOG_LEVEL_0); + << ", key_image" << scan_pos_entries.pos_entries[i].keyimage + << ", diff: " << this_coin_diff, LOG_LEVEL_0); pe = scan_pos_entries.pos_entries[i]; found_wallet_index = i; found_kh = kernel_hash; @@ -743,10 +785,19 @@ bool test_generator::construct_block(const std::vector& events const currency::block& blk_prev, const currency::account_base& miner_acc, const std::list& tx_list, - const std::list& coin_stake_sources - ) + const std::list& coin_stake_sources) { - uint64_t height = boost::get(blk_prev.miner_tx.vin.front()).height + 1; + return construct_block(0, events, blk, blk_prev, miner_acc, tx_list, coin_stake_sources); +} +bool test_generator::construct_block(int64_t manual_timestamp_adjustment, + const std::vector& events, + currency::block& blk, + const currency::block& blk_prev, + const currency::account_base& miner_acc, + const std::list& tx_list, + const std::list& coin_stake_sources) +{ + uint64_t height = boost::get(blk_prev.miner_tx.vin[0]).height + 1; crypto::hash prev_id = get_block_hash(blk_prev); // Keep push difficulty little up to be sure about PoW hash success std::vector blockchain; @@ -769,6 +820,7 @@ bool test_generator::construct_block(const std::vector& events block& prev_same_type = blockchain[prev_i]; timestamp = adjust_timestamp_finished ? prev_same_type.timestamp + diff_target : prev_same_type.timestamp + diff_target - diff_up_timestamp_delta; + timestamp = timestamp + manual_timestamp_adjustment; uint64_t already_generated_coins = get_already_generated_coins(prev_id); std::vector block_sizes; diff --git a/tests/core_tests/chaingen.h b/tests/core_tests/chaingen.h index 07b3bf30..d519e760 100644 --- a/tests/core_tests/chaingen.h +++ b/tests/core_tests/chaingen.h @@ -345,7 +345,7 @@ public: currency::wide_difficulty_type cumul_difficulty; std::vector m_transactions; crypto::hash ks_hash; - }; + }; // amount vec_ind, tx_index, out index in tx typedef std::map > > outputs_index; @@ -473,6 +473,7 @@ public: bool construct_genesis_block(currency::block& blk, const currency::account_base& miner_acc, uint64_t timestamp); + bool construct_block(const std::vector& events, currency::block& blk, const currency::block& blk_prev, @@ -480,6 +481,14 @@ public: const std::list& tx_list = std::list(), const std::list& coin_stake_sources = std::list() //in case of PoS block ); + bool construct_block(int64_t manual_timestamp_adjustment, + const std::vector& events, + currency::block& blk, + const currency::block& blk_prev, + const currency::account_base& miner_acc, + const std::list& tx_list = std::list(), + const std::list& coin_stake_sources = std::list() //in case of PoS block + ); bool construct_block_manually(currency::block& blk, const currency::block& prev_block, @@ -500,8 +509,15 @@ public: static const test_gentime_settings& get_test_gentime_settings() { return m_test_gentime_settings; } static void set_test_gentime_settings(const test_gentime_settings& s) { m_test_gentime_settings = s; } static void set_test_gentime_settings_default() { m_test_gentime_settings = m_test_gentime_settings_default; } + void set_pos_to_low_timestamp(bool do_pos_to_low_timestamp) { m_do_pos_to_low_timestamp = do_pos_to_low_timestamp; } + void set_hardfork_height(uint64_t h); private: + bool m_do_pos_to_low_timestamp; + uint64_t m_last_found_timestamp; + + uint64_t m_hardfork_after_heigh; + std::unordered_map m_blocks_info; static test_gentime_settings m_test_gentime_settings; static test_gentime_settings m_test_gentime_settings_default; @@ -956,6 +972,14 @@ void append_vector_by_another_vector(U& dst, const V& src) VEC_EVENTS.push_back(BLK_NAME); \ PRINT_EVENT_NO(VEC_EVENTS); + + +#define MAKE_NEXT_BLOCK_TIMESTAMP_ADJUSTMENT(ADJ, VEC_EVENTS, BLK_NAME, PREV_BLOCK, MINER_ACC) \ + currency::block BLK_NAME = AUTO_VAL_INIT(BLK_NAME); \ + generator.construct_block(ADJ, VEC_EVENTS, BLK_NAME, PREV_BLOCK, MINER_ACC); \ + VEC_EVENTS.push_back(BLK_NAME); \ + PRINT_EVENT_NO(VEC_EVENTS); + #define MAKE_NEXT_POS_BLOCK(VEC_EVENTS, BLK_NAME, PREV_BLOCK, MINER_ACC, MINERS_ACC_LIST) \ currency::block BLK_NAME = AUTO_VAL_INIT(BLK_NAME); \ generator.construct_block(VEC_EVENTS, BLK_NAME, PREV_BLOCK, MINER_ACC, std::list(), MINERS_ACC_LIST); \ diff --git a/tests/core_tests/chaingen_main.cpp b/tests/core_tests/chaingen_main.cpp index 0540e1bf..f462a8c5 100644 --- a/tests/core_tests/chaingen_main.cpp +++ b/tests/core_tests/chaingen_main.cpp @@ -935,6 +935,12 @@ int main(int argc, char* argv[]) GENERATE_AND_PLAY(gen_uint_overflow_1); GENERATE_AND_PLAY(gen_uint_overflow_2); + + // Hardfok1 tests + GENERATE_AND_PLAY(before_hard_fork_1_cumulative_difficulty); + GENERATE_AND_PLAY(inthe_middle_hard_fork_1_cumulative_difficulty); + GENERATE_AND_PLAY(after_hard_fork_1_cumulative_difficulty); + //GENERATE_AND_PLAY(gen_block_reward); */ diff --git a/tests/core_tests/chaingen_tests_list.h b/tests/core_tests/chaingen_tests_list.h index 5eaa024e..b9c4dc28 100644 --- a/tests/core_tests/chaingen_tests_list.h +++ b/tests/core_tests/chaingen_tests_list.h @@ -33,3 +33,4 @@ #include "escrow_wallet_altchain_test.h" #include "misc_tests.h" #include "emission_test.h" +#include "hard_fork_1_locked_pos_test.h" diff --git a/tests/core_tests/hard_fork_1_locked_pos_test.cpp b/tests/core_tests/hard_fork_1_locked_pos_test.cpp new file mode 100644 index 00000000..d2362c7b --- /dev/null +++ b/tests/core_tests/hard_fork_1_locked_pos_test.cpp @@ -0,0 +1,119 @@ +// Copyright (c) 2014-2018 Zano Project +// Copyright (c) 2014-2018 The Louisdor Project +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "chaingen.h" +#include "pos_validation.h" +#include "tx_builder.h" +#include "hard_fork_1_locked_pos_test.h" +#include "random_helper.h" + +using namespace epee; +using namespace crypto; +using namespace currency; + +hard_fork_1_cumulative_difficulty_base::hard_fork_1_cumulative_difficulty_base() +{ + REGISTER_CALLBACK_METHOD(hard_fork_1_cumulative_difficulty_base, c1); + REGISTER_CALLBACK_METHOD(hard_fork_1_cumulative_difficulty_base, configure_core); +} + +bool hard_fork_1_cumulative_difficulty_base::generate(std::vector& events) const +{ + random_state_test_restorer::reset_random(); + + GENERATE_ACCOUNT(preminer_acc); + GENERATE_ACCOUNT(miner_acc); + m_accounts.push_back(miner_acc); + std::list miner_acc_lst(1, miner_acc); + + MAKE_GENESIS_BLOCK(events, blk_0, preminer_acc, 1564434616); + generator.set_hardfork_height(get_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); + block last_block = blk_0r; + for (size_t i = 0; i != 20; i++) + { + MAKE_NEXT_POS_BLOCK(events, next_blk_pos, last_block, miner_acc, miner_acc_lst); + MAKE_NEXT_BLOCK(events, next_blk_pow, next_blk_pos, miner_acc); + events.push_back(event_core_time(next_blk_pow.timestamp - 10)); + + last_block = next_blk_pow; + } + + generator.set_pos_to_low_timestamp(true); + last_block = blk_0r; + for (size_t i = 0; i != 20; i++) + { + MAKE_NEXT_POS_BLOCK(events, next_blk_pos, last_block, miner_acc, miner_acc_lst); + MAKE_NEXT_BLOCK_TIMESTAMP_ADJUSTMENT(-14, events, next_blk_pow, next_blk_pos, miner_acc); + last_block = next_blk_pow; + } + + + DO_CALLBACK(events, "c1"); + return true; +} + +bool hard_fork_1_cumulative_difficulty_base::configure_core(currency::core& c, size_t ev_index, const std::vector& events) +{ + currency::core_runtime_config pc = c.get_blockchain_storage().get_core_runtime_config(); + pc.min_coinstake_age = TESTS_POS_CONFIG_MIN_COINSTAKE_AGE; //four blocks + pc.pos_minimum_heigh = TESTS_POS_CONFIG_POS_MINIMUM_HEIGH; //four blocks + pc.hard_fork1_starts_after_height = get_hardfork_height(); + + c.get_blockchain_storage().set_core_runtime_config(pc); + return true; +} + +bool before_hard_fork_1_cumulative_difficulty::c1(currency::core& c, size_t ev_index, const std::vector& events) +{ + + std::shared_ptr last_pow_block = c.get_blockchain_storage().get_last_block_of_type(false); + std::shared_ptr last_pos_block = c.get_blockchain_storage().get_last_block_of_type(true); + CHECK_AND_ASSERT_MES(last_pow_block->cumulative_diff_precise == 184, false, "Incorrect condition failed: last_pow_block->cumulative_diff_precise == 184"); + CHECK_AND_ASSERT_MES(last_pos_block->cumulative_diff_precise == 20, false, "Incorrect condition failed: last_pos_block->cumulative_diff_precise == 20"); + // + return true; +} + +uint64_t before_hard_fork_1_cumulative_difficulty::get_hardfork_height()const +{ + return 10000; //just big number which is obviously bigger then test blockchain +} + + + +bool inthe_middle_hard_fork_1_cumulative_difficulty::c1(currency::core& c, size_t ev_index, const std::vector& events) +{ + + std::shared_ptr last_pow_block = c.get_blockchain_storage().get_last_block_of_type(false); + std::shared_ptr last_pos_block = c.get_blockchain_storage().get_last_block_of_type(true); + CHECK_AND_ASSERT_MES(last_pow_block->cumulative_diff_precise == 184, false, "Incorrect condition failed: last_pow_block->cumulative_diff_precise == 184"); + CHECK_AND_ASSERT_MES(last_pos_block->cumulative_diff_precise == 20, false, "Incorrect condition failed: last_pos_block->cumulative_diff_precise == 20"); + // + return true; +} + +uint64_t inthe_middle_hard_fork_1_cumulative_difficulty::get_hardfork_height()const +{ + return 15; +} +bool after_hard_fork_1_cumulative_difficulty::c1(currency::core& c, size_t ev_index, const std::vector& events) +{ + + std::shared_ptr last_pow_block = c.get_blockchain_storage().get_last_block_of_type(false); + std::shared_ptr last_pos_block = c.get_blockchain_storage().get_last_block_of_type(true); + CHECK_AND_ASSERT_MES(last_pow_block->cumulative_diff_precise == 172, false, "Incorrect condition failed: last_pow_block->cumulative_diff_precise == 184"); + CHECK_AND_ASSERT_MES(last_pos_block->cumulative_diff_precise == 199, false, "Incorrect condition failed: last_pos_block->cumulative_diff_precise == 20"); + // + return true; +} + +uint64_t after_hard_fork_1_cumulative_difficulty::get_hardfork_height()const +{ + return 12; +} + diff --git a/tests/core_tests/hard_fork_1_locked_pos_test.h b/tests/core_tests/hard_fork_1_locked_pos_test.h new file mode 100644 index 00000000..6898e46c --- /dev/null +++ b/tests/core_tests/hard_fork_1_locked_pos_test.h @@ -0,0 +1,40 @@ +// Copyright (c) 2014-2018 Zano Project +// Copyright (c) 2014-2018 The Louisdor Project +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#pragma once +#include "chaingen.h" +#include "wallet_tests_basic.h" + + +struct hard_fork_1_cumulative_difficulty_base : public wallet_test +{ + hard_fork_1_cumulative_difficulty_base(); + bool generate(std::vector& events) const; + bool configure_core(currency::core& c, size_t ev_index, const std::vector& events); + virtual bool c1(currency::core& c, size_t ev_index, const std::vector& events)= 0; + virtual uint64_t get_hardfork_height()const =0; +}; + +// this test check if code still work same way as it supposed to work before hard fork point +struct before_hard_fork_1_cumulative_difficulty : public hard_fork_1_cumulative_difficulty_base +{ + bool c1(currency::core& c, size_t ev_index, const std::vector& events); + virtual uint64_t get_hardfork_height()const; +}; + +// this test check if code still work same way as it supposed to work is split happened before hard fork point but finished after hard fork point +struct inthe_middle_hard_fork_1_cumulative_difficulty : public hard_fork_1_cumulative_difficulty_base +{ + bool c1(currency::core& c, size_t ev_index, const std::vector& events); + virtual uint64_t get_hardfork_height()const; +}; + +// this test check if code follow the new consensus algorithm and prefer balanced branch of the blockchain tree +struct after_hard_fork_1_cumulative_difficulty : public hard_fork_1_cumulative_difficulty_base +{ + bool c1(currency::core& c, size_t ev_index, const std::vector& events); + virtual uint64_t get_hardfork_height()const; +}; +