From ac5b6b6030b36262753f642fd04d89be3ac12fac Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Fri, 23 Apr 2021 22:37:37 -0500 Subject: [PATCH] fixed few bugs in block version pre-validation(possible hardfork) --- src/currency_core/blockchain_storage.cpp | 18 +++-- tests/core_tests/atomic_tests.cpp | 4 -- tests/core_tests/block_validation.cpp | 89 ++++++++++++++++++++++++ tests/core_tests/block_validation.h | 10 +++ tests/core_tests/chaingen_helpers.h | 12 +++- tests/core_tests/chaingen_main.cpp | 1 + 6 files changed, 124 insertions(+), 10 deletions(-) diff --git a/src/currency_core/blockchain_storage.cpp b/src/currency_core/blockchain_storage.cpp index 86a8083e..497116d9 100644 --- a/src/currency_core/blockchain_storage.cpp +++ b/src/currency_core/blockchain_storage.cpp @@ -1439,6 +1439,8 @@ bool blockchain_storage::create_block_template(const create_block_template_param height = m_db_blocks.size(); if(height <= m_core_runtime_config.hard_fork_01_starts_after_height) b.major_version = BLOCK_MAJOR_VERSION_INITAL; + else if(height <= m_core_runtime_config.hard_fork_03_starts_after_height) + b.major_version = HF1_BLOCK_MAJOR_VERSION; else b.major_version = CURRENT_BLOCK_MAJOR_VERSION; @@ -5767,17 +5769,23 @@ bool blockchain_storage::is_after_hardfork_3_zone(uint64_t height)const //------------------------------------------------------------------ bool blockchain_storage::prevalidate_block(const block& bl) { + //before hard_fork1 if (bl.major_version == BLOCK_MAJOR_VERSION_INITAL && get_block_height(bl) <= m_core_runtime_config.hard_fork_01_starts_after_height) return true; - if (bl.major_version == HF1_BLOCK_MAJOR_VERSION - && get_block_height(bl) > m_core_runtime_config.hard_fork_01_starts_after_height - && get_block_height(bl) <= m_core_runtime_config.hard_fork_03_starts_after_height + + //after hard_fork1 and before hard_fork3 + if ( get_block_height(bl) > m_core_runtime_config.hard_fork_01_starts_after_height && + get_block_height(bl) <= m_core_runtime_config.hard_fork_03_starts_after_height ) { - return true; + if (bl.major_version == HF1_BLOCK_MAJOR_VERSION) + return true; + else + return false; } + //after hard_fork3 if (bl.major_version > CURRENT_BLOCK_MAJOR_VERSION) { LOG_ERROR("prevalidation failed for block " << get_block_hash(bl) << ": major block version " << static_cast(bl.major_version) << " is incorrect, " << CURRENT_BLOCK_MAJOR_VERSION << " is expected" << ENDL @@ -5785,7 +5793,7 @@ bool blockchain_storage::prevalidate_block(const block& bl) return false; } - if (is_after_hardfork_3_zone() && bl.minor_version > CURRENT_BLOCK_MINOR_VERSION) + if (bl.minor_version > CURRENT_BLOCK_MINOR_VERSION) { //this means that binary block is compatible, but semantics got changed due to hardfork, daemon should be updated LOG_PRINT_MAGENTA("Block's MINOR_VERSION is: " << bl.minor_version diff --git a/tests/core_tests/atomic_tests.cpp b/tests/core_tests/atomic_tests.cpp index 7711ff38..9fa9dea5 100644 --- a/tests/core_tests/atomic_tests.cpp +++ b/tests/core_tests/atomic_tests.cpp @@ -673,10 +673,6 @@ bool atomic_test_check_hardfork_rules::c1(currency::core& c, size_t ev_index, co pc.hard_fork_03_starts_after_height = 30; c.get_blockchain_storage().set_core_runtime_config(pc); - //try to submit wrong transaction that do refund before expiration - //std::vector txs; - //txs.push_back(refund_tx); - //bool r = mine_next_pow_block_in_playtime_with_given_txs(m_mining_accunt.get_public_address(), c, txs); bool r = mine_next_pow_block_in_playtime(m_mining_accunt.get_public_address(), c); CHECK_AND_FORCE_ASSERT_MES(!r, false, "Block with HTLC before hard fork accepted"); diff --git a/tests/core_tests/block_validation.cpp b/tests/core_tests/block_validation.cpp index 5963626d..320ad03d 100644 --- a/tests/core_tests/block_validation.cpp +++ b/tests/core_tests/block_validation.cpp @@ -610,3 +610,92 @@ bool gen_block_invalid_binary_format::check_all_blocks_purged(currency::core& c, return true; } + + +gen_block_wrong_version_agains_hardfork::gen_block_wrong_version_agains_hardfork() +{ + REGISTER_CALLBACK("c1", gen_block_wrong_version_agains_hardfork::c1); +} + +bool gen_block_wrong_version_agains_hardfork::c1(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_fork_01_starts_after_height = 10; + pc.hard_fork_02_starts_after_height = 10; + pc.hard_fork_03_starts_after_height = 10; + c.get_blockchain_storage().set_core_runtime_config(pc); + + currency::account_base mining_accunt; + mining_accunt.generate(); + + bool r = mine_next_pow_block_in_playtime(mining_accunt.get_public_address(), c); // block with height 1 + + uint8_t major_version_to_set = 0; + uint8_t minor_version_to_set = 0; + auto cb = [&] (currency::block& b) + { + b.major_version = major_version_to_set; + b.minor_version = minor_version_to_set; + }; + + //between 1 and 2 hardforks + pc.hard_fork_01_starts_after_height = 1; + pc.hard_fork_02_starts_after_height = 10; + pc.hard_fork_03_starts_after_height = 20; + c.get_blockchain_storage().set_core_runtime_config(pc); + + //major unknown + major_version_to_set = 2; + + r = mine_next_pow_block_in_playtime(mining_accunt.get_public_address(), c, cb); // block with height 2 (won't pass) + CHECK_TEST_CONDITION(!r); + + //minor unknown + major_version_to_set = 1; + minor_version_to_set = 2; + r = mine_next_pow_block_in_playtime(mining_accunt.get_public_address(), c, cb); // block with height 2 + CHECK_TEST_CONDITION(r); + + //between 1 and 2 hardforks + pc.hard_fork_01_starts_after_height = 1; + pc.hard_fork_02_starts_after_height = 1; + pc.hard_fork_03_starts_after_height = 1; + c.get_blockchain_storage().set_core_runtime_config(pc); + + + //major correct + major_version_to_set = 2; + minor_version_to_set = 0; + r = mine_next_pow_block_in_playtime(mining_accunt.get_public_address(), c, cb); // block with height 3 + CHECK_TEST_CONDITION(r); + + //major incorrect + major_version_to_set = 3; + minor_version_to_set = 0; + r = mine_next_pow_block_in_playtime(mining_accunt.get_public_address(), c, cb); // block with height 4 (won't pass) + CHECK_TEST_CONDITION(!r); + + //minor incorrect for hf3 + major_version_to_set = 2; + minor_version_to_set = 1; + r = mine_next_pow_block_in_playtime(mining_accunt.get_public_address(), c, cb); // block with height 4 (won't pass) + CHECK_TEST_CONDITION(!r); + + //major lower then norma for hf3 (do we need this half-working backward compability) + major_version_to_set = 0; + minor_version_to_set = 0; + r = mine_next_pow_block_in_playtime(mining_accunt.get_public_address(), c, cb); // block with height 4 (won't pass) + CHECK_TEST_CONDITION(r); + + return true; +} + +bool gen_block_wrong_version_agains_hardfork::generate(std::vector& events) const +{ + BLOCK_VALIDATION_INIT_GENERATE(); + DO_CALLBACK(events, "c1"); + return true; +} \ No newline at end of file diff --git a/tests/core_tests/block_validation.h b/tests/core_tests/block_validation.h index 46768819..e40911a1 100644 --- a/tests/core_tests/block_validation.h +++ b/tests/core_tests/block_validation.h @@ -169,6 +169,16 @@ struct gen_block_is_too_big : public gen_block_verification_base<1> bool generate(std::vector& events) const; }; +struct gen_block_wrong_version_agains_hardfork : public gen_block_verification_base<1> +{ +public: + gen_block_wrong_version_agains_hardfork(); + bool c1(currency::core& c, size_t ev_index, const std::vector& events); + bool generate(std::vector& events) const; +}; + + + struct gen_block_invalid_binary_format : public test_chain_unit_base { gen_block_invalid_binary_format(); diff --git a/tests/core_tests/chaingen_helpers.h b/tests/core_tests/chaingen_helpers.h index 0fc0879e..510d5c89 100644 --- a/tests/core_tests/chaingen_helpers.h +++ b/tests/core_tests/chaingen_helpers.h @@ -12,7 +12,9 @@ // chaingen-independent helpers that may be used outside of core_tests (for ex. in functional_tests) -inline bool mine_next_pow_block_in_playtime(const currency::account_public_address& miner_addr, currency::core& c, currency::block* output = nullptr) + +template +inline bool mine_next_pow_block_in_playtime(const currency::account_public_address& miner_addr, currency::core& c, t_callbacktype modify_block_cb, currency::block* output = nullptr) { currency::block b = AUTO_VAL_INIT(b); currency::wide_difficulty_type diff; @@ -28,6 +30,7 @@ inline bool mine_next_pow_block_in_playtime(const currency::account_public_addre // keep global time up with blocks' timestamps test_core_time::adjust(b.timestamp); + modify_block_cb(b); r = currency::miner::find_nonce_for_given_block(b, diff, height); CHECK_AND_ASSERT_MES(r, false, "find_nonce_for_given_block failed"); @@ -41,6 +44,13 @@ inline bool mine_next_pow_block_in_playtime(const currency::account_public_addre return true; } +inline bool mine_next_pow_block_in_playtime(const currency::account_public_address& miner_addr, currency::core& c, currency::block* output = nullptr) +{ + auto cb = [&](currency::block& b) + {}; + return mine_next_pow_block_in_playtime(miner_addr, c, cb, output); +} + inline bool mine_next_pow_block_in_playtime_with_given_txs(const currency::account_public_address& miner_addr, currency::core& c, const std::vector& txs, const crypto::hash& prev_id, uint64_t height, currency::block* output = nullptr) { struct loc_helper diff --git a/tests/core_tests/chaingen_main.cpp b/tests/core_tests/chaingen_main.cpp index 8edc1f9e..b24bb27b 100644 --- a/tests/core_tests/chaingen_main.cpp +++ b/tests/core_tests/chaingen_main.cpp @@ -947,6 +947,7 @@ int main(int argc, char* argv[]) GENERATE_AND_PLAY(gen_block_miner_tx_has_out_to_alice); GENERATE_AND_PLAY(gen_block_has_invalid_tx); GENERATE_AND_PLAY(gen_block_is_too_big); + GENERATE_AND_PLAY(gen_block_wrong_version_agains_hardfork); //GENERATE_AND_PLAY(gen_block_invalid_binary_format); // Takes up to 3 hours, if CURRENCY_MINED_MONEY_UNLOCK_WINDOW == 500, up to 30 minutes, if CURRENCY_MINED_MONEY_UNLOCK_WINDOW == 10