diff --git a/src/currency_core/blockchain_storage.cpp b/src/currency_core/blockchain_storage.cpp index bc20ffda..624cdfb8 100644 --- a/src/currency_core/blockchain_storage.cpp +++ b/src/currency_core/blockchain_storage.cpp @@ -3331,6 +3331,11 @@ bool blockchain_storage::push_transaction_to_global_outs_index(const transaction { m_db_outputs.push_back_item(ot.amount, global_output_entry::construct(tx_id, i)); global_indexes.push_back(m_db_outputs.get_item_size(ot.amount) - 1); + if (ot.target.type() == typeid(txout_htlc) && !is_in_hardfork_2_zone()) + { + LOG_ERROR("Error: Transaction with txout_htlc before is_in_hardfork_2_zone(before height " << m_core_runtime_config.hard_fork_02_starts_after_height <<")"); + return false; + } } else if (ot.target.type() == typeid(txout_multisig)) { @@ -3844,6 +3849,11 @@ namespace currency } bool operator()(const txin_htlc& in) const { + if (!m_bcs.is_in_hardfork_2_zone()) + { + LOG_ERROR("Error: Transaction with txin_htlc before is_in_hardfork_2_zone(before height " << m_bcs.get_core_runtime_config().hard_fork_02_starts_after_height << ")"); + return false; + } return this->operator()(static_cast(in)); } bool operator()(const txin_gen& in) const { return true; } @@ -4262,6 +4272,12 @@ bool blockchain_storage::check_tx_inputs(const transaction& tx, const crypto::ha } else if (txin.type() == typeid(txin_htlc)) { + if (!is_in_hardfork_2_zone()) + { + LOG_ERROR("Error: Transaction with txin_htlc before is_in_hardfork_2_zone(before height " << m_core_runtime_config.hard_fork_02_starts_after_height << ")"); + return false; + } + const txin_htlc& in_htlc = boost::get(txin); CHECK_AND_ASSERT_MES(in_htlc.key_offsets.size(), false, "Empty in_to_key.key_offsets for input #" << sig_index << " tx: " << tx_prefix_hash); TIME_MEASURE_START_PD(tx_check_inputs_loop_kimage_check); @@ -4299,7 +4315,29 @@ bool blockchain_storage::is_tx_spendtime_unlocked(uint64_t unlock_time) const { return currency::is_tx_spendtime_unlocked(unlock_time, get_current_blockchain_size(), m_core_runtime_config.get_core_time()); } - +//------------------------------------------------------------------ +bool blockchain_storage::check_tx_fit_hardfork(const transaction& tx) +{ + //inputs + for (const auto in : tx.vin) + { + if (in.type() == typeid(txin_htlc)) + { + if (!is_in_hardfork_2_zone()) + return false; + } + } + //outputs + for (const auto out : tx.vout) + { + if (out.target.type() == typeid(txout_htlc)) + { + if (!is_in_hardfork_2_zone()) + return false; + } + } + return true; +} //------------------------------------------------------------------ bool blockchain_storage::check_tx_input(const transaction& tx, size_t in_index, const txin_to_key& txin, const crypto::hash& tx_prefix_hash, const std::vector& sig, uint64_t& max_related_block_height, uint64_t& source_max_unlock_time_for_pos_coinbase) const { @@ -5686,16 +5724,43 @@ bool blockchain_storage::update_next_comulative_size_limit() return true; } //------------------------------------------------------------------ +bool blockchain_storage::is_in_hardfork_2_zone()const +{ + if (m_db_blocks.size() > m_core_runtime_config.hard_fork_02_starts_after_height) + return true; + return false; +} +//------------------------------------------------------------------ bool blockchain_storage::prevalidate_block(const block& bl) { 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 != CURRENT_BLOCK_MAJOR_VERSION) + + 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_02_starts_after_height + ) + { + return true; + } + + 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 << obj_to_json_str(bl)); return false; } + + if (is_in_hardfork_2_zone() && 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 + << ", while current build supports not bigger then " << CURRENT_BLOCK_MINOR_VERSION + << ", please make sure you using latest version.", LOG_LEVEL_0 + ); + return false; + } + return true; } //------------------------------------------------------------------ diff --git a/src/currency_core/blockchain_storage.h b/src/currency_core/blockchain_storage.h index bb3dd331..8db91a00 100644 --- a/src/currency_core/blockchain_storage.h +++ b/src/currency_core/blockchain_storage.h @@ -470,6 +470,7 @@ namespace currency bool print_tx_outputs_lookup(const crypto::hash& tx_id) const; uint64_t get_last_x_block_height(bool pos)const; bool is_tx_spendtime_unlocked(uint64_t unlock_time)const; + bool check_tx_fit_hardfork(const transaction& tx); private: //-------------- DB containers -------------- @@ -658,6 +659,7 @@ namespace currency bool is_output_allowed_for_input(const output_key_or_htlc_v& out_v, const txin_v& in_v, uint64_t top_minus_source_height)const; bool is_output_allowed_for_input(const txout_to_key& out_v, const txin_v& in_v)const; bool is_output_allowed_for_input(const txout_htlc& out_v, const txin_v& in_v, uint64_t top_minus_source_height)const; + bool is_in_hardfork_2_zone()const; diff --git a/src/currency_core/currency_config.h b/src/currency_core/currency_config.h index 8b576556..22c20002 100644 --- a/src/currency_core/currency_config.h +++ b/src/currency_core/currency_config.h @@ -27,7 +27,9 @@ #define CURRENCY_PUBLIC_AUDITABLE_INTEG_ADDRESS_BASE58_PREFIX 0x8a49 // auditable integrated addresses start with 'aiZX' #define CURRENCY_MINED_MONEY_UNLOCK_WINDOW 10 #define CURRENT_TRANSACTION_VERSION 1 -#define CURRENT_BLOCK_MAJOR_VERSION 1 +#define HF1_BLOCK_MAJOR_VERSION 1 +#define CURRENT_BLOCK_MAJOR_VERSION 2 + #define CURRENT_BLOCK_MINOR_VERSION 0 #define CURRENCY_BLOCK_FUTURE_TIME_LIMIT 60*60*2 #define CURRENCY_POS_BLOCK_FUTURE_TIME_LIMIT 60*20 diff --git a/src/currency_core/currency_format_utils.cpp b/src/currency_core/currency_format_utils.cpp index 1a780ce7..1a7fcb72 100644 --- a/src/currency_core/currency_format_utils.cpp +++ b/src/currency_core/currency_format_utils.cpp @@ -1660,7 +1660,6 @@ namespace currency CHECK_AND_ASSERT_MES(in.type() == typeid(txin_to_key) || in.type() == typeid(txin_multisig) || in.type() == typeid(txin_htlc), false, "wrong variant type: " << in.type().name() << ", in transaction id=" << get_transaction_hash(tx)); - } return true; } diff --git a/src/currency_core/tx_pool.cpp b/src/currency_core/tx_pool.cpp index 81ce88b6..d7a5c17d 100644 --- a/src/currency_core/tx_pool.cpp +++ b/src/currency_core/tx_pool.cpp @@ -102,6 +102,14 @@ namespace currency return false; } + if (!m_blockchain.check_tx_fit_hardfork(tx)) + { + // + LOG_ERROR("Transaction " << id <<" doesn't fit current hardfork"); + tvc.m_verification_failed = true; + return false; + } + TIME_MEASURE_START_PD(tx_processing_time); TIME_MEASURE_START_PD(check_inputs_types_supported_time); if(!check_inputs_types_supported(tx)) diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 06546edc..13a8a0bf 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -1392,7 +1392,11 @@ void wallet2::process_htlc_triggers_on_block_added(uint64_t height) tr.m_flags &= ~(WALLET_TRANSFER_DETAIL_FLAG_SPENT); //reset spent flag m_found_free_amounts.clear(); //reset free amounts cache tr.m_spent_height = 0; - } + } + + //reset cache + m_found_free_amounts.clear(); + //remove it from active contracts auto it_active_htlc = m_active_htlcs.find(std::make_pair(tr.m_ptx_wallet_info->m_tx.vout[tr.m_internal_output_index].amount, tr.m_global_output_index)); if (it_active_htlc == m_active_htlcs.end()) diff --git a/tests/core_tests/atomic_tests.cpp b/tests/core_tests/atomic_tests.cpp index 93174070..472007eb 100644 --- a/tests/core_tests/atomic_tests.cpp +++ b/tests/core_tests/atomic_tests.cpp @@ -31,12 +31,16 @@ struct wallet_tests_callback_handler : public tools::i_wallet2_callback std::vector all_wtis; }; -atomic_simple_test::atomic_simple_test() +////////////////////////////////////////////////////////////////////////// + + +atomic_base_test::atomic_base_test() { - REGISTER_CALLBACK_METHOD(atomic_simple_test, c1); + REGISTER_CALLBACK_METHOD(atomic_base_test, c1); + REGISTER_CALLBACK_METHOD(atomic_base_test, configure_core); } -bool atomic_simple_test::generate(std::vector& events) const +bool atomic_base_test::generate(std::vector& events) const { epee::debug::get_set_enable_assert(true, true); @@ -48,7 +52,7 @@ bool atomic_simple_test::generate(std::vector& events) const block blk_0 = AUTO_VAL_INIT(blk_0); generator.construct_genesis_block(blk_0, genesis_acc, test_core_time::get_time()); events.push_back(blk_0); - + DO_CALLBACK(events, "configure_core"); REWIND_BLOCKS_N(events, blk_0r, blk_0, m_mining_accunt, CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 5); DO_CALLBACK(events, "c1"); @@ -56,6 +60,45 @@ bool atomic_simple_test::generate(std::vector& events) const return true; } +bool atomic_base_test::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_fork_01_starts_after_height = 10; + pc.hard_fork_01_starts_after_height = 12; + c.get_blockchain_storage().set_core_runtime_config(pc); + return true; +} +/************************************************************************/ +/* */ +/************************************************************************/ + +atomic_simple_test::atomic_simple_test() +{ + //REGISTER_CALLBACK_METHOD(atomic_simple_test, c1); +} + +// bool atomic_simple_test::generate(std::vector& events) const +// { +// epee::debug::get_set_enable_assert(true, true); +// +// currency::account_base genesis_acc; +// genesis_acc.generate(); +// m_mining_accunt.generate(); +// +// +// block blk_0 = AUTO_VAL_INIT(blk_0); +// generator.construct_genesis_block(blk_0, genesis_acc, test_core_time::get_time()); +// events.push_back(blk_0); +// +// REWIND_BLOCKS_N(events, blk_0r, blk_0, m_mining_accunt, CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 5); +// +// DO_CALLBACK(events, "c1"); +// epee::debug::get_set_enable_assert(true, false); +// return true; +// } + bool atomic_simple_test::c1(currency::core& c, size_t ev_index, const std::vector& events) @@ -287,28 +330,28 @@ bool atomic_simple_test::c1(currency::core& c, size_t ev_index, const std::vecto atomic_test_wrong_redeem_wrong_refund::atomic_test_wrong_redeem_wrong_refund() { - REGISTER_CALLBACK_METHOD(atomic_test_wrong_redeem_wrong_refund, c1); + //REGISTER_CALLBACK_METHOD(atomic_test_wrong_redeem_wrong_refund, c1); } -bool atomic_test_wrong_redeem_wrong_refund::generate(std::vector& events) const -{ - epee::debug::get_set_enable_assert(true, true); - - currency::account_base genesis_acc; - genesis_acc.generate(); - m_mining_accunt.generate(); - - - block blk_0 = AUTO_VAL_INIT(blk_0); - generator.construct_genesis_block(blk_0, genesis_acc, test_core_time::get_time()); - events.push_back(blk_0); - - REWIND_BLOCKS_N(events, blk_0r, blk_0, m_mining_accunt, CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 5); - - DO_CALLBACK(events, "c1"); - epee::debug::get_set_enable_assert(true, false); - return true; -} +// bool atomic_test_wrong_redeem_wrong_refund::generate(std::vector& events) const +// { +// epee::debug::get_set_enable_assert(true, true); +// +// currency::account_base genesis_acc; +// genesis_acc.generate(); +// m_mining_accunt.generate(); +// +// +// block blk_0 = AUTO_VAL_INIT(blk_0); +// generator.construct_genesis_block(blk_0, genesis_acc, test_core_time::get_time()); +// events.push_back(blk_0); +// +// REWIND_BLOCKS_N(events, blk_0r, blk_0, m_mining_accunt, CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 5); +// +// DO_CALLBACK(events, "c1"); +// epee::debug::get_set_enable_assert(true, false); +// return true; +// } @@ -463,28 +506,28 @@ bool atomic_test_wrong_redeem_wrong_refund::c1(currency::core& c, size_t ev_inde atomic_test_altchain_simple::atomic_test_altchain_simple() { - REGISTER_CALLBACK_METHOD(atomic_test_altchain_simple, c1); + //REGISTER_CALLBACK_METHOD(atomic_test_altchain_simple, c1); } -bool atomic_test_altchain_simple::generate(std::vector& events) const -{ - epee::debug::get_set_enable_assert(true, true); - - currency::account_base genesis_acc; - genesis_acc.generate(); - m_mining_accunt.generate(); - - - block blk_0 = AUTO_VAL_INIT(blk_0); - generator.construct_genesis_block(blk_0, genesis_acc, test_core_time::get_time()); - events.push_back(blk_0); - - REWIND_BLOCKS_N(events, blk_0r, blk_0, m_mining_accunt, CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 5); - - DO_CALLBACK(events, "c1"); - epee::debug::get_set_enable_assert(true, false); - return true; -} +// bool atomic_test_altchain_simple::generate(std::vector& events) const +// { +// epee::debug::get_set_enable_assert(true, true); +// +// currency::account_base genesis_acc; +// genesis_acc.generate(); +// m_mining_accunt.generate(); +// +// +// block blk_0 = AUTO_VAL_INIT(blk_0); +// generator.construct_genesis_block(blk_0, genesis_acc, test_core_time::get_time()); +// events.push_back(blk_0); +// +// REWIND_BLOCKS_N(events, blk_0r, blk_0, m_mining_accunt, CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 5); +// +// DO_CALLBACK(events, "c1"); +// epee::debug::get_set_enable_assert(true, false); +// return true; +// } diff --git a/tests/core_tests/atomic_tests.h b/tests/core_tests/atomic_tests.h index 39caca07..78fa0b14 100644 --- a/tests/core_tests/atomic_tests.h +++ b/tests/core_tests/atomic_tests.h @@ -7,31 +7,36 @@ #include "wallet_tests_basic.h" -struct atomic_simple_test : public wallet_test +struct atomic_base_test : public wallet_test +{ + atomic_base_test(); + bool generate(std::vector& events) const; + virtual bool c1(currency::core& c, size_t ev_index, const std::vector& events)=0; + bool configure_core(currency::core& c, size_t ev_index, const std::vector& events); +private: + mutable currency::account_base m_mining_accunt; +}; + + +struct atomic_simple_test : public atomic_base_test { atomic_simple_test(); - bool generate(std::vector& events) const; bool c1(currency::core& c, size_t ev_index, const std::vector& events); private: - mutable currency::account_base m_mining_accunt; }; -struct atomic_test_wrong_redeem_wrong_refund : public wallet_test +struct atomic_test_wrong_redeem_wrong_refund : public atomic_base_test { atomic_test_wrong_redeem_wrong_refund(); - bool generate(std::vector& events) const; bool c1(currency::core& c, size_t ev_index, const std::vector& events); private: - mutable currency::account_base m_mining_accunt; }; -struct atomic_test_altchain_simple : public wallet_test +struct atomic_test_altchain_simple : public atomic_base_test { atomic_test_altchain_simple(); - bool generate(std::vector& events) const; bool c1(currency::core& c, size_t ev_index, const std::vector& events); private: - mutable currency::account_base m_mining_accunt; };