From d85b94df92f23a87d705ad0741ebb61391e72192 Mon Sep 17 00:00:00 2001 From: David Ed <40647185+Dedme@users.noreply.github.com> Date: Wed, 26 Mar 2025 22:29:12 +1030 Subject: [PATCH 1/7] Update Dockerfile (#514) Fixed versions and hardcoded versions in dockerfile --- utils/docker/zano-full-node/Dockerfile | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/utils/docker/zano-full-node/Dockerfile b/utils/docker/zano-full-node/Dockerfile index 4394a6db..d3240bd6 100644 --- a/utils/docker/zano-full-node/Dockerfile +++ b/utils/docker/zano-full-node/Dockerfile @@ -48,11 +48,11 @@ RUN update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-7 700 --slave /u WORKDIR /root # Lib Settings -ARG CMAKE_VERSION_DOT=3.16.9 +ARG CMAKE_VERSION_DOT=3.26.3 ARG CMAKE_HASH=d71eda07d6ecf3964de65a0e36d0b171565e1aced56ba9f53ca3783406b5cacf -ARG BOOST_VERSION=1_70_0 -ARG BOOST_VERSION_DOT=1.70.0 +ARG BOOST_VERSION=1_84_0 +ARG BOOST_VERSION_DOT=1.84.0 ARG BOOST_HASH=430ae8354789de4fd19ee52f3b1f739e1fba576f0aded0897c3c2bc00fb38778 ARG OPENSSL_VERSION_DOT=1.1.1w @@ -88,10 +88,10 @@ RUN curl https://www.openssl.org/source/openssl-${OPENSSL_VERSION_DOT}.tar.gz -O # Compile CMake RUN set -ex \ && mkdir /opt/cmake \ - && sh cmake-3.16.9-Linux-x86_64.sh --prefix=/opt/cmake --skip-license\ + && sh cmake-${CMAKE_VERSION_DOT}-Linux-x86_64.sh --prefix=/opt/cmake --skip-license\ && ln -s /opt/cmake/bin/cmake /usr/local/bin/cmake\ && cmake --version\ - && rm cmake-3.16.9-Linux-x86_64.sh + && rm cmake-${CMAKE_VERSION_DOT}-Linux-x86_64.sh # Compile Boost RUN set -ex \ From 3d2ce52b8e72ded224d5f51a22b3db25de1bb735 Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Mon, 2 Jun 2025 23:50:31 +0400 Subject: [PATCH 2/7] small performance tweak of fill_block_template and more logs related to pool txs blacklisting --- src/currency_core/tx_pool.cpp | 24 ++++++++++++++++++++---- src/currency_core/tx_pool.h | 1 + 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/src/currency_core/tx_pool.cpp b/src/currency_core/tx_pool.cpp index 4c98db89..d0649b39 100644 --- a/src/currency_core/tx_pool.cpp +++ b/src/currency_core/tx_pool.cpp @@ -723,15 +723,26 @@ namespace currency return true; } //--------------------------------------------------------------------------------- + std::string tx_memory_pool::get_blacklisted_txs_string() const + { + std::stringstream ss; + m_db_black_tx_list.enumerate_items([&](uint64_t i, const crypto::hash& td_id, const bool& /*dummy */ ) + { + ss << td_id << ENDL; + return true; + }); + return ss.str(); + } + //--------------------------------------------------------------------------------- bool tx_memory_pool::add_transaction_to_black_list(const transaction& tx) { // atm: // 1) the only side effect of a tx being blacklisted is the one is just ignored by fill_block_template(), but it still can be added to blockchain/pool // 2) it's permanent - LOG_PRINT_YELLOW("TX ADDED TO POOL'S BLACKLIST: " << get_transaction_hash(tx), LOG_LEVEL_0); m_db.begin_transaction(); m_db_black_tx_list.set(get_transaction_hash(tx), true); m_db.commit_transaction(); + LOG_PRINT_YELLOW("TX ADDED TO POOL'S BLACKLIST: " << get_transaction_hash(tx) << ", full black list: " << ENDL << get_blacklisted_txs_string(), LOG_LEVEL_0); return true; } //--------------------------------------------------------------------------------- @@ -908,8 +919,12 @@ namespace currency { //not the best implementation at this time, sorry :( - if (is_tx_blacklisted(get_transaction_hash(txd.tx))) + if (is_tx_blacklisted(id)) + { + LOG_PRINT_L2("[is_transaction_ready_to_go]Tx " << id << " skipped as it blacklisted"); return false; + } + //check is ring_signature already checked ? if(txd.max_used_block_id == null_hash) @@ -1193,13 +1208,14 @@ namespace currency if (i < best_position) { bl.tx_hashes.push_back(tx.first); + LOG_PRINT_L2("[fill_block_template]: Added tx to block: " << tx.first); } - else if (have_attachment_service_in_container(tx.second->tx.attachment, BC_OFFERS_SERVICE_ID, BC_OFFERS_SERVICE_INSTRUCTION_DEL)) + /*else if (have_attachment_service_in_container(tx.second->tx.attachment, BC_OFFERS_SERVICE_ID, BC_OFFERS_SERVICE_INSTRUCTION_DEL)) { // BC_OFFERS_SERVICE_INSTRUCTION_DEL transactions has zero fee, so include them here regardless of reward effectiveness bl.tx_hashes.push_back(tx.first); total_size += tx.second->blob_size; - } + }*/ } } // add explicit transactions diff --git a/src/currency_core/tx_pool.h b/src/currency_core/tx_pool.h index c97a498a..e573d2b5 100644 --- a/src/currency_core/tx_pool.h +++ b/src/currency_core/tx_pool.h @@ -155,6 +155,7 @@ namespace currency bool insert_alias_info(const transaction& tx); bool remove_alias_info(const transaction& tx); bool check_tx_fee(const transaction &tx, uint64_t amount_fee); + std::string get_blacklisted_txs_string() const; bool is_valid_contract_finalization_tx(const transaction &tx)const; void store_db_solo_options_values(); From 7eb6986f4d7a68464d8fe4c63324d221dc94b60a Mon Sep 17 00:00:00 2001 From: sowle Date: Tue, 3 Jun 2025 00:01:11 +0200 Subject: [PATCH 3/7] txpool fixed: txs with too small max_related_block_height will wait in the pool till the current height is okay + coretests tx_pool_validation_and_chain_switch added --- src/currency_core/blockchain_storage.h | 2 +- src/currency_core/tx_pool.cpp | 5 +- src/wallet/wallet2.cpp | 3 +- tests/core_tests/chaingen_main.cpp | 1 + tests/core_tests/tx_validation.cpp | 118 +++++++++++++++++++++++++ tests/core_tests/tx_validation.h | 8 ++ 6 files changed, 133 insertions(+), 4 deletions(-) diff --git a/src/currency_core/blockchain_storage.h b/src/currency_core/blockchain_storage.h index 035fd400..d8d9dd1f 100644 --- a/src/currency_core/blockchain_storage.h +++ b/src/currency_core/blockchain_storage.h @@ -927,7 +927,7 @@ namespace currency if (this->get_current_blockchain_size() - max_related_block_height < CURRENCY_HF4_MANDATORY_MIN_COINAGE) { - LOG_ERROR("Coinage rule broken(mainblock): h = " << this->get_current_blockchain_size() << ", max_related_block_height=" << max_related_block_height << ", tx: " << get_transaction_hash(validated_tx)); + LOG_ERROR("Coinage rule is broken (mainblock): current blockchain size = " << this->get_current_blockchain_size() << ", max_related_block_height = " << max_related_block_height << ", tx: " << get_transaction_hash(validated_tx)); return false; } } diff --git a/src/currency_core/tx_pool.cpp b/src/currency_core/tx_pool.cpp index d0649b39..ad25c21b 100644 --- a/src/currency_core/tx_pool.cpp +++ b/src/currency_core/tx_pool.cpp @@ -939,9 +939,10 @@ namespace currency txd.last_failed_id = m_blockchain.get_block_id_by_height(txd.last_failed_height); return false; } - }else + } + else { - if(txd.max_used_block_height >= m_blockchain.get_current_blockchain_size()) + if (m_blockchain.get_current_blockchain_size() < txd.max_used_block_height + CURRENCY_HF4_MANDATORY_MIN_COINAGE) // coinage rule since HF4, s.a. scan_outputkeys_for_indexes() return false; if(m_blockchain.get_block_id_by_height(txd.max_used_block_height) != txd.max_used_block_id) { diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 433c5c6d..f7e27eaf 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -3154,7 +3154,8 @@ void wallet2::detach_blockchain(uint64_t including_height) //asset descriptors handle_rollback_events(including_height); - WLT_LOG_L0("Detached blockchain on height " << including_height << ", transfers detached " << transfers_detached << ", blocks detached " << blocks_detached); + WLT_LOG_L0("Detached blockchain on height " << including_height << ", transfers detached " << transfers_detached << ", blocks detached " << blocks_detached + << ", new top: " << print16(m_chain.get_top_block_id()) << " @ " << m_chain.get_top_block_height()); } //---------------------------------------------------------------------------------------------------- void wallet2::operator()(const asset_register_event& e) diff --git a/tests/core_tests/chaingen_main.cpp b/tests/core_tests/chaingen_main.cpp index 69002a99..39bdb36c 100644 --- a/tests/core_tests/chaingen_main.cpp +++ b/tests/core_tests/chaingen_main.cpp @@ -1226,6 +1226,7 @@ int main(int argc, char* argv[]) the heights >= 10. */ GENERATE_AND_PLAY_HF(tx_pool_semantic_validation, "3"); GENERATE_AND_PLAY(input_refers_to_incompatible_by_type_output); + GENERATE_AND_PLAY_HF(tx_pool_validation_and_chain_switch, "3-*"); // Double spend GENERATE_AND_PLAY(gen_double_spend_in_tx); diff --git a/tests/core_tests/tx_validation.cpp b/tests/core_tests/tx_validation.cpp index a0527f4a..cabb10f9 100644 --- a/tests/core_tests/tx_validation.cpp +++ b/tests/core_tests/tx_validation.cpp @@ -2606,3 +2606,121 @@ bool input_refers_to_incompatible_by_type_output::assert_htlc_input_refers_zarca return true; } + +//------------------------------------------------------------------ + +tx_pool_validation_and_chain_switch::tx_pool_validation_and_chain_switch() +{ + REGISTER_CALLBACK_METHOD(tx_pool_validation_and_chain_switch, c1); +} + +bool tx_pool_validation_and_chain_switch::generate(std::vector& events) const +{ + // Test idea: + + uint64_t ts = test_core_time::get_time(); + m_accounts.resize(TOTAL_ACCS_COUNT); + account_base& miner_acc = m_accounts[MINER_ACC_IDX]; miner_acc.generate(); + account_base& alice_acc = m_accounts[ALICE_ACC_IDX]; alice_acc.generate(); + MAKE_GENESIS_BLOCK(events, blk_0, miner_acc, ts); + DO_CALLBACK(events, "configure_core"); + + std::list miner_stake_sources( {miner_acc} ); + + REWIND_BLOCKS_N_WITH_TIME(events, blk_0r, blk_0, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW * 2); + MAKE_TX(events, tx_0, miner_acc, alice_acc, MK_TEST_COINS(100), blk_0r); + MAKE_NEXT_BLOCK_TX1(events, blk_1, blk_0r, miner_acc, tx_0); + + // 0 ... 10 21 22 23 24 25 26 27 28 29 30 31 <- height + // (0 )- (0r)- (1 )- <- chain A + // tx_0 + + MAKE_NEXT_POS_BLOCK(events, blk_2, blk_1, miner_acc, miner_stake_sources); + MAKE_NEXT_POS_BLOCK(events, blk_3, blk_2, miner_acc, miner_stake_sources); + MAKE_NEXT_POS_BLOCK(events, blk_4, blk_3, miner_acc, miner_stake_sources); + MAKE_NEXT_POS_BLOCK(events, blk_5, blk_4, miner_acc, miner_stake_sources); + MAKE_NEXT_POS_BLOCK(events, blk_6, blk_5, miner_acc, miner_stake_sources); + MAKE_NEXT_POS_BLOCK(events, blk_7, blk_6, miner_acc, miner_stake_sources); + MAKE_NEXT_POS_BLOCK(events, blk_8, blk_7, miner_acc, miner_stake_sources); + MAKE_NEXT_POS_BLOCK(events, blk_9, blk_8, miner_acc, miner_stake_sources); + MAKE_NEXT_POS_BLOCK(events, blk_10, blk_9, miner_acc, miner_stake_sources); + + // now Alice should be able to spend her coins + MAKE_TX(events, tx_a, alice_acc, miner_acc, MK_TEST_COINS(100) - TESTS_DEFAULT_FEE, blk_10); + DO_CALLBACK_PARAMS(events, "check_tx_pool_count", static_cast(1)); + + MAKE_NEXT_POS_BLOCK_TX1(events, blk_11, blk_10, miner_acc, miner_stake_sources, tx_a); + DO_CALLBACK_PARAMS(events, "check_tx_pool_count", static_cast(0)); + + // construct chain B as PoW-PoS-PoW-PoS, it should win + MAKE_NEXT_BLOCK(events, blk_3a, blk_3, miner_acc); + MAKE_NEXT_POS_BLOCK(events, blk_4a, blk_3a, miner_acc, miner_stake_sources); + MAKE_NEXT_BLOCK(events, blk_5a, blk_4a, miner_acc); + MAKE_NEXT_POS_BLOCK(events, blk_6a, blk_5a, miner_acc, miner_stake_sources); + + // make sure it won + DO_CALLBACK_PARAMS(events, "check_top_block", params_top_block(blk_6a)); + + // now tx_a should have been put back to the tx pool + DO_CALLBACK_PARAMS(events, "check_tx_pool_count", static_cast(1)); + + // the next block should be rejected, because of max_related_block_height=21 and the current height is 28 + //DO_CALLBACK(events, "mark_invalid_block"); + //MAKE_NEXT_BLOCK_TX1(events, blk_7a, blk_6a, miner_acc, tx_a); + + // and if we clear tx pool ... + //DO_CALLBACK(events, "clear_tx_pool"); + //DO_CALLBACK_PARAMS(events, "check_tx_pool_count", static_cast(0)); + // and re-add the transaction on this height, it sould be added + //ADD_CUSTOM_EVENT(events, tx_a); + + // however, we need to make sure that tx pool won't be use tx_a in a block template until the height is good enough + DO_CALLBACK(events, "c1"); + + return true; +} + +bool tx_pool_validation_and_chain_switch::c1(currency::core& c, size_t ev_index, const std::vector& events) +{ + std::shared_ptr miner_wlt = init_playtime_test_wallet(events, c, MINER_ACC_IDX); + std::shared_ptr alice_wlt = init_playtime_test_wallet(events, c, ALICE_ACC_IDX); + + bool r = false; + alice_wlt->refresh(); + + // make sure tx_a is still in the pool + CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Unexpected number of txs in the pool: " << c.get_pool_transactions_count()); + // and Alice's unconfirmed balance is nonzero + CHECK_AND_ASSERT_MES(check_balance_via_wallet(*alice_wlt, "Alice", MK_TEST_COINS(100)), false, ""); + + // mine a block, make sure it is possible and the tx is still in the pool afterwards + r = mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c); + CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_blocks_in_playtime failed"); + CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Unexpected number of txs in the pool: " << c.get_pool_transactions_count()); + + // make sure tx_a is still in the pool + CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Unexpected number of txs in the pool: " << c.get_pool_transactions_count()); + // and Alice's unconfirmed balance is nonzero + alice_wlt->refresh(); + CHECK_AND_ASSERT_MES(check_balance_via_wallet(*alice_wlt, "Alice", MK_TEST_COINS(100)), false, ""); + + // mine more + r = mine_next_pow_blocks_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c, 2); + + // make sure tx_a is still in the pool + CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Unexpected number of txs in the pool: " << c.get_pool_transactions_count()); + // and Alice's unconfirmed balance is nonzero + alice_wlt->refresh(); + CHECK_AND_ASSERT_MES(check_balance_via_wallet(*alice_wlt, "Alice", MK_TEST_COINS(100)), false, ""); + + // the next blocktemplate should include it + r = mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c); + // make sure it did + CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Unexpected number of txs in the pool: " << c.get_pool_transactions_count()); + // and Alice's unconfirmed balance is zero + alice_wlt->refresh(); + CHECK_AND_ASSERT_MES(check_balance_via_wallet(*alice_wlt, "Alice", MK_TEST_COINS(0)), false, ""); + + return true; +} + diff --git a/tests/core_tests/tx_validation.h b/tests/core_tests/tx_validation.h index 6e3ae56e..3428d1eb 100644 --- a/tests/core_tests/tx_validation.h +++ b/tests/core_tests/tx_validation.h @@ -6,6 +6,7 @@ #pragma once #include "chaingen.h" +#include "wallet_tests_basic.h" struct gen_tx_big_version : public test_chain_unit_enchanced { @@ -175,3 +176,10 @@ struct input_refers_to_incompatible_by_type_output : public test_chain_unit_ench bool assert_zc_input_refers_bare_output_is_wrong(const currency::core& c, const size_t ev_index, const std::vector& events) const; bool assert_htlc_input_refers_zarcanum_output_is_wrong(const currency::core& c, const size_t ev_index, const std::vector& events) const; }; + +struct tx_pool_validation_and_chain_switch : public wallet_test +{ + tx_pool_validation_and_chain_switch(); + bool generate(std::vector& events) const; + bool c1(currency::core& c, size_t ev_index, const std::vector& events); +}; From 411cda4ad45ca7dee902d87897770c187dd44979 Mon Sep 17 00:00:00 2001 From: sowle Date: Tue, 3 Jun 2025 00:22:30 +0200 Subject: [PATCH 4/7] improved condition in tx_memory_pool::is_transaction_ready_to_go() --- src/currency_core/tx_pool.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/currency_core/tx_pool.cpp b/src/currency_core/tx_pool.cpp index ad25c21b..2f04158c 100644 --- a/src/currency_core/tx_pool.cpp +++ b/src/currency_core/tx_pool.cpp @@ -942,7 +942,7 @@ namespace currency } else { - if (m_blockchain.get_current_blockchain_size() < txd.max_used_block_height + CURRENCY_HF4_MANDATORY_MIN_COINAGE) // coinage rule since HF4, s.a. scan_outputkeys_for_indexes() + if(txd.max_used_block_height >= m_blockchain.get_current_blockchain_size()) return false; if(m_blockchain.get_block_id_by_height(txd.max_used_block_height) != txd.max_used_block_id) { @@ -958,6 +958,10 @@ namespace currency } } } + + if (m_blockchain.get_current_blockchain_size() < txd.max_used_block_height + CURRENCY_HF4_MANDATORY_MIN_COINAGE) // coinage rule since HF4, s.a. scan_outputkeys_for_indexes() + return false; + //if we here, transaction seems valid, but, anyway, check for key_images collisions with blockchain, just to be sure if (m_blockchain.have_tx_keyimges_as_spent(txd.tx)) { From 7fb2fcc1885b7785f2c5ea4717301d5ec08f126c Mon Sep 17 00:00:00 2001 From: sowle Date: Tue, 3 Jun 2025 00:33:26 +0200 Subject: [PATCH 5/7] minor fix --- src/wallet/wallet2.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index f7e27eaf..433c5c6d 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -3154,8 +3154,7 @@ void wallet2::detach_blockchain(uint64_t including_height) //asset descriptors handle_rollback_events(including_height); - WLT_LOG_L0("Detached blockchain on height " << including_height << ", transfers detached " << transfers_detached << ", blocks detached " << blocks_detached - << ", new top: " << print16(m_chain.get_top_block_id()) << " @ " << m_chain.get_top_block_height()); + WLT_LOG_L0("Detached blockchain on height " << including_height << ", transfers detached " << transfers_detached << ", blocks detached " << blocks_detached); } //---------------------------------------------------------------------------------------------------- void wallet2::operator()(const asset_register_event& e) From f84ecf579e0477f754b0f1ec5a7ba89ca43f54ae Mon Sep 17 00:00:00 2001 From: sowle Date: Tue, 3 Jun 2025 01:38:55 +0200 Subject: [PATCH 6/7] improved condition in tx_memory_pool::is_transaction_ready_to_go() limited to >=HF4 to please old tests --- src/currency_core/tx_pool.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/currency_core/tx_pool.cpp b/src/currency_core/tx_pool.cpp index 2f04158c..924f1fa7 100644 --- a/src/currency_core/tx_pool.cpp +++ b/src/currency_core/tx_pool.cpp @@ -959,7 +959,7 @@ namespace currency } } - if (m_blockchain.get_current_blockchain_size() < txd.max_used_block_height + CURRENCY_HF4_MANDATORY_MIN_COINAGE) // coinage rule since HF4, s.a. scan_outputkeys_for_indexes() + if (txd.tx.version > TRANSACTION_VERSION_PRE_HF4 && m_blockchain.get_current_blockchain_size() < txd.max_used_block_height + CURRENCY_HF4_MANDATORY_MIN_COINAGE) // coinage rule since HF4, s.a. scan_outputkeys_for_indexes() return false; //if we here, transaction seems valid, but, anyway, check for key_images collisions with blockchain, just to be sure From e725b784c1584f8da7f123ff46e3666437ac4984 Mon Sep 17 00:00:00 2001 From: sowle Date: Tue, 3 Jun 2025 01:55:58 +0200 Subject: [PATCH 7/7] version bump: 2.1.5.397 -> 2.1.6.399 --- src/version.h.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/version.h.in b/src/version.h.in index 90aeb815..a8763e12 100644 --- a/src/version.h.in +++ b/src/version.h.in @@ -5,9 +5,9 @@ #define PROJECT_MAJOR_VERSION "2" #define PROJECT_MINOR_VERSION "1" -#define PROJECT_REVISION "5" +#define PROJECT_REVISION "6" #define PROJECT_VERSION PROJECT_MAJOR_VERSION "." PROJECT_MINOR_VERSION "." PROJECT_REVISION -#define PROJECT_VERSION_BUILD_NO 397 +#define PROJECT_VERSION_BUILD_NO 399 #define PROJECT_VERSION_BUILD_NO_STR STRINGIFY_EXPAND(PROJECT_VERSION_BUILD_NO) #define PROJECT_VERSION_LONG PROJECT_VERSION "." PROJECT_VERSION_BUILD_NO_STR "[" BUILD_COMMIT_ID "]"