From 806eb326d1e9f8abde2d0fd138adf12ffcffe7cf Mon Sep 17 00:00:00 2001 From: sowle Date: Sat, 16 Mar 2024 14:57:25 +0100 Subject: [PATCH 01/16] (cherry picked) tx_pool: add post-HF4 txs are now being check for balance proof. Core test hard_fork_4_consolidated_txs changed accordingly --- src/currency_core/tx_pool.cpp | 12 ++++++++- src/currency_core/tx_pool.h | 3 ++- tests/core_tests/hard_fork_4.cpp | 46 +++++++++++++++++++++++--------- 3 files changed, 47 insertions(+), 14 deletions(-) diff --git a/src/currency_core/tx_pool.cpp b/src/currency_core/tx_pool.cpp index 211599ab..b8185cbf 100644 --- a/src/currency_core/tx_pool.cpp +++ b/src/currency_core/tx_pool.cpp @@ -224,6 +224,14 @@ namespace currency } TIME_MEASURE_FINISH_PD(check_inputs_time); + TIME_MEASURE_START_PD(check_post_hf4_balance); + if (tx.version > TRANSACTION_VERSION_PRE_HF4) + { + r = check_tx_balance(tx, id); + CHECK_AND_ASSERT_MES_CUSTOM(r, false, { tvc.m_verification_failed = true; }, "post-HF4 tx: balance proof is invalid"); + } + TIME_MEASURE_FINISH_PD(check_post_hf4_balance); + do_insert_transaction(tx, id, blob_size, kept_by_block, tx_fee, ch_inp_res ? max_used_block_id : null_hash, ch_inp_res ? max_used_block_height : 0); TIME_MEASURE_FINISH_PD(tx_processing_time); @@ -240,9 +248,11 @@ namespace currency << "/" << m_performance_data.validate_alias_time.get_last_val() << "/" << m_performance_data.check_keyimages_ws_ms_time.get_last_val() << "/" << m_performance_data.check_inputs_time.get_last_val() + << "/b"<< m_performance_data.check_post_hf4_balance.get_last_val() << "/" << m_performance_data.begin_tx_time.get_last_val() << "/" << m_performance_data.update_db_time.get_last_val() - << "/" << m_performance_data.db_commit_time.get_last_val() << ")" ); + << "/" << m_performance_data.db_commit_time.get_last_val() + << ")"); return true; } diff --git a/src/currency_core/tx_pool.h b/src/currency_core/tx_pool.h index 92d60604..b837f28f 100644 --- a/src/currency_core/tx_pool.h +++ b/src/currency_core/tx_pool.h @@ -77,7 +77,8 @@ namespace currency epee::math_helper::average check_inputs_time; epee::math_helper::average begin_tx_time; epee::math_helper::average update_db_time; - epee::math_helper::average db_commit_time; + epee::math_helper::average db_commit_time; + epee::math_helper::average check_post_hf4_balance; }; typedef std::unordered_map> key_image_cache; diff --git a/tests/core_tests/hard_fork_4.cpp b/tests/core_tests/hard_fork_4.cpp index 2c4a7fd3..e5b4d6b4 100644 --- a/tests/core_tests/hard_fork_4.cpp +++ b/tests/core_tests/hard_fork_4.cpp @@ -89,6 +89,10 @@ bool hard_fork_4_consolidated_txs::generate(std::vector& event ADD_CUSTOM_EVENT(events, tx_0b); MAKE_NEXT_BLOCK_TX_LIST(events, blk_1, blk_0r, miner_acc, std::list({tx_0a, tx_0b})); + size_t dhc = count_type_in_variant_container(tx_0b.extra); + CHECK_AND_ASSERT_MES(dhc == tx_0b.vout.size(), false, "unexpected derivation hints count: " << dhc); + + REWIND_BLOCKS_N_WITH_TIME(events, blk_1r, blk_1, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW); // check Alice's balance @@ -100,7 +104,7 @@ bool hard_fork_4_consolidated_txs::generate(std::vector& event CHECK_AND_ASSERT_MES(check_balance_via_wallet(*alice_wlt.get(), "alice", alice_amount, 0, alice_amount, 0, 0), false, ""); uint64_t miner_amount = MK_TEST_COINS(60); - uint64_t bob_amount = miner_amount + alice_amount - TX_DEFAULT_FEE; + m_bob_amount = miner_amount + alice_amount - TX_DEFAULT_FEE; // Consolidated tx (TX_FLAG_SIGNATURE_MODE_SEPARATE). @@ -119,17 +123,33 @@ bool hard_fork_4_consolidated_txs::generate(std::vector& event std::vector destinations; if (miner_change != 0) destinations.push_back(tx_destination_entry(miner_change, miner_acc.get_public_address())); - destinations.push_back(tx_destination_entry(bob_amount, bob_acc.get_public_address())); + destinations.push_back(tx_destination_entry(m_bob_amount, bob_acc.get_public_address())); add_flags_to_all_destination_entries(tx_destination_entry_flags::tdef_explicit_native_asset_id, destinations); r = construct_tx(miner_acc.get_keys(), sources, destinations, empty_extra, empty_attachment, tx_1, get_tx_version_from_events(events), one_time_secret_key, 0, 0, 0, true, TX_FLAG_SIGNATURE_MODE_SEPARATE, TX_DEFAULT_FEE, gen_context); CHECK_AND_ASSERT_MES(r, false, "construct_tx failed"); + dhc = count_type_in_variant_container(tx_1.extra); + CHECK_AND_ASSERT_MES(dhc == destinations.size(), false, "unexpected derivation hints count: " << dhc); + // partially completed tx_1 shouldn't be accepted - //DO_CALLBACK(events, "mark_invalid_tx"); - ADD_CUSTOM_EVENT(events, tx_1); - MAKE_NEXT_BLOCK_TX1(events, blk_2a, blk_1r, miner_acc, tx_1); + + // now we added a balance check to tx_memory_pool::add_tx() for post-HF4 txs, so the behaviour is the same -- partially completed consolidated tx won't be added to the pool -- sowle + // (subject to change in future) + + //if (m_post_hf4_zarcanum) + //{ + // ADD_CUSTOM_EVENT(events, tx_1); + // DO_CALLBACK(events, "mark_invalid_block"); + // MAKE_NEXT_BLOCK_TX1(events, blk_2a, blk_1r, miner_acc, tx_1); + // DO_CALLBACK(events, "clear_tx_pool"); + //} + //else + //{ + DO_CALLBACK(events, "mark_invalid_tx"); + ADD_CUSTOM_EVENT(events, tx_1); + //} } @@ -147,23 +167,25 @@ bool hard_fork_4_consolidated_txs::generate(std::vector& event 0, 0, 0, true, TX_FLAG_SIGNATURE_MODE_SEPARATE, 0 /* note zero fee here */, gen_context); CHECK_AND_ASSERT_MES(r, false, "construct_tx failed"); + size_t dhc_2 = count_type_in_variant_container(tx_1.extra); + CHECK_AND_ASSERT_MES(dhc_2 == dhc, false, "unexpected derivation hints count: " << dhc_2); + ADD_CUSTOM_EVENT(events, tx_1); } MAKE_NEXT_BLOCK_TX1(events, blk_2, blk_1r, miner_acc, tx_1); - //std::shared_ptr bob_wlt; - //r = generator.init_test_wallet(bob_acc, get_block_hash(blk_0), bob_wlt); - //CHECK_AND_ASSERT_MES(r, false, "init_test_wallet failed"); - //r = generator.refresh_test_wallet(events, bob_wlt.get(), get_block_hash(blk_2), 2 * CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 2); - //CHECK_AND_ASSERT_MES(r, false, "refresh_test_wallet failed"); - //CHECK_AND_ASSERT_MES(check_balance_via_wallet(*bob_wlt.get(), "Bob", bob_amount, 0, 0, 0, 0), false, ""); - + DO_CALLBACK(events, "c1"); return true; } bool hard_fork_4_consolidated_txs::c1(currency::core& c, size_t ev_index, const std::vector& events) { + std::shared_ptr bob_wlt = init_playtime_test_wallet(events, c, BOB_ACC_IDX); + bob_wlt->refresh(); + + CHECK_AND_ASSERT_MES(check_balance_via_wallet(*bob_wlt.get(), "Bob", m_bob_amount, 0, 0, 0, 0), false, ""); + return true; } From 3eb711fbf80c48518fa12fe813c53544e6731519 Mon Sep 17 00:00:00 2001 From: sowle Date: Wed, 27 Mar 2024 17:08:19 +0100 Subject: [PATCH 02/16] tx_pool: is_tx_blacklisted() --- src/currency_core/tx_pool.cpp | 13 +++++++++---- src/currency_core/tx_pool.h | 2 ++ 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/currency_core/tx_pool.cpp b/src/currency_core/tx_pool.cpp index b8185cbf..998d4fed 100644 --- a/src/currency_core/tx_pool.cpp +++ b/src/currency_core/tx_pool.cpp @@ -885,7 +885,7 @@ namespace currency { //not the best implementation at this time, sorry :( - if (m_db_black_tx_list.get(get_transaction_hash(txd.tx))) + if (is_tx_blacklisted(get_transaction_hash(txd.tx))) return false; //check is ring_signature already checked ? @@ -976,8 +976,8 @@ namespace currency return "(no transactions, the pool is empty)"; // sort output by receive time txs.sort([](const std::pair& lhs, const std::pair& rhs) -> bool { return lhs.second.receive_time < rhs.second.receive_time; }); - ss << "# | transaction id | size | fee | ins | outs | live_time | max used block | last failed block | ver | kept by a block?" << ENDL; - // 1234 f99fe6d4335fc0ddd69e6880a4d95e0f6ea398de0324a6837021a61c6a31cacd 187157 0.10000111 2000 2000 d0.h10.m16.s17 1234567 <12345..> 1234567 <12345..> 2 YES + ss << "# | transaction id | size | fee | ins | outs | live_time | max used block | last failed block | ver | status " << ENDL; + // 1234 f99fe6d4335fc0ddd69e6880a4d95e0f6ea398de0324a6837021a61c6a31cacd 187157 0.10000111 2000 2000 d0.h10.m16.s17 1234567 <12345..> 1234567 <12345..> 2 kept_by_block BLACKLISTED size_t i = 0; for (auto& tx : txs) { @@ -995,7 +995,7 @@ namespace currency << std::setw(7) << txd.last_failed_height << " " << std::setw(9) << print16(txd.last_failed_id) << " " << std::setw(3) << txd.tx.version << " " - << (txd.kept_by_block ? "YES" : "no ") + << (txd.kept_by_block ? "kept_by_block " : "") << (is_tx_blacklisted(tx.first) ? "BLACKLISTED " : "") << ENDL; } return ss.str(); @@ -1324,6 +1324,11 @@ namespace currency } } //--------------------------------------------------------------------------------- + bool tx_memory_pool::is_tx_blacklisted(const crypto::hash& id) const + { + return m_db_black_tx_list.get(id) != nullptr; + } + //--------------------------------------------------------------------------------- bool tx_memory_pool::load_keyimages_cache() { CRITICAL_REGION_LOCAL(m_key_images_lock); diff --git a/src/currency_core/tx_pool.h b/src/currency_core/tx_pool.h index b837f28f..8b3ec595 100644 --- a/src/currency_core/tx_pool.h +++ b/src/currency_core/tx_pool.h @@ -141,6 +141,8 @@ namespace currency void remove_incompatible_txs(); // made public to be called after the BCS is loaded and hardfork info is ready + bool is_tx_blacklisted(const crypto::hash& id) const; + private: bool on_tx_add(crypto::hash tx_id, const transaction& tx, bool kept_by_block); bool on_tx_remove(const crypto::hash &tx_id, const transaction& tx, bool kept_by_block); From 709d16eb753be332773d681a404406affd562577 Mon Sep 17 00:00:00 2001 From: sowle Date: Wed, 27 Mar 2024 17:18:17 +0100 Subject: [PATCH 03/16] tx pool: asset operations basic validation on tx add --- src/currency_core/blockchain_storage.cpp | 72 ++++++++++--------- src/currency_core/blockchain_storage.h | 4 +- .../currency_format_utils_abstract.h | 21 ++++++ src/currency_core/tx_pool.cpp | 10 ++- 4 files changed, 71 insertions(+), 36 deletions(-) diff --git a/src/currency_core/blockchain_storage.cpp b/src/currency_core/blockchain_storage.cpp index 6e781c68..500983fc 100644 --- a/src/currency_core/blockchain_storage.cpp +++ b/src/currency_core/blockchain_storage.cpp @@ -4012,7 +4012,7 @@ bool blockchain_storage::pop_asset_info(const crypto::public_key& asset_id) return true; } //------------------------------------------------------------------ -bool blockchain_storage::validate_ado_ownership(asset_op_verification_context& avc) +bool validate_ado_ownership(asset_op_verification_context& avc) { asset_operation_ownership_proof aoop = AUTO_VAL_INIT(aoop); bool r = get_type_in_variant_container(avc.tx.proofs, aoop); @@ -4024,32 +4024,23 @@ bool blockchain_storage::validate_ado_ownership(asset_op_verification_context& a return crypto::verify_schnorr_sig(avc.tx_id, owner_key, aoop.gss); } //------------------------------------------------------------------ -bool blockchain_storage::put_asset_info(const transaction& tx, const crypto::hash& tx_id, const asset_descriptor_operation& ado) +bool blockchain_storage::validate_asset_operation_against_current_blochain_state(asset_op_verification_context& avc) const { CRITICAL_REGION_LOCAL(m_read_lock); - asset_op_verification_context avc = { tx, tx_id, ado }; + CHECK_AND_ASSERT_MES(get_or_calculate_asset_id(avc.ado, &avc.asset_id_pt, &avc.asset_id), false, "get_or_calculate_asset_id failed"); + avc.asset_op_history = m_db_assets.find(avc.asset_id); + + const asset_descriptor_operation& ado = avc.ado; if (ado.operation_type == ASSET_DESCRIPTOR_OPERATION_REGISTER) { - CHECK_AND_ASSERT_MES(get_or_calculate_asset_id(avc.ado, &avc.asset_id_pt, &avc.asset_id), false, "get_or_calculate_asset_id failed"); - - avc.asset_op_history = m_db_assets.find(avc.asset_id); CHECK_AND_ASSERT_MES(!avc.asset_op_history, false, "asset with id " << avc.asset_id << " has already been registered"); - avc.amount_to_validate = ado.descriptor.current_supply; - CHECK_AND_ASSERT_MES(validate_asset_operation_amount_commitment(avc), false, "asset operation validation failed!"); - - assets_container::t_value_type local_asset_history = AUTO_VAL_INIT(local_asset_history); - local_asset_history.push_back(ado); - m_db_assets.set(avc.asset_id, local_asset_history); - LOG_PRINT_MAGENTA("[ASSET_REGISTERED]: " << print_money_brief(ado.descriptor.current_supply, ado.descriptor.decimal_point) << ", " << avc.asset_id << ": " << ado.descriptor.ticker << ", \"" << ado.descriptor.full_name << "\"", LOG_LEVEL_1); + CHECK_AND_ASSERT_MES(validate_asset_operation_amount_commitment(avc), false, "validate_asset_operation_amount_commitment failed!"); } else { - CHECK_AND_ASSERT_MES(get_or_calculate_asset_id(avc.ado, &avc.asset_id_pt, &avc.asset_id), false, "get_or_calculate_asset_id failed"); - avc.asset_op_history = m_db_assets.find(avc.asset_id); - CHECK_AND_ASSERT_MES(avc.asset_op_history && avc.asset_op_history->size(), false, "asset with id " << avc.asset_id << " has not been registered"); // check ownership permission if (ado.operation_type == ASSET_DESCRIPTOR_OPERATION_EMIT || ado.operation_type == ASSET_DESCRIPTOR_OPERATION_UPDATE /*|| ado.operation_type == ASSET_DESCRIPTOR_OPERATION_PUBLIC_BURN*/) @@ -4092,25 +4083,40 @@ bool blockchain_storage::put_asset_info(const transaction& tx, const crypto::has bool r = validate_asset_operation_amount_commitment(avc); CHECK_AND_ASSERT_MES(r, false, "Balance proof validation failed for asset_descriptor_operation"); } + } - assets_container::t_value_type local_asset_history = *avc.asset_op_history; - local_asset_history.push_back(ado); - m_db_assets.set(avc.asset_id, local_asset_history); + return true; +} +//------------------------------------------------------------------ +bool blockchain_storage::put_asset_info(const transaction& tx, const crypto::hash& tx_id, const asset_descriptor_operation& ado) +{ + CRITICAL_REGION_LOCAL(m_read_lock); - switch(ado.operation_type) - { - case ASSET_DESCRIPTOR_OPERATION_UPDATE: - LOG_PRINT_MAGENTA("[ASSET_UPDATED]: " << avc.asset_id << ": " << ado.descriptor.ticker << ", \"" << ado.descriptor.full_name << "\"", LOG_LEVEL_1); - break; - case ASSET_DESCRIPTOR_OPERATION_EMIT: - LOG_PRINT_MAGENTA("[ASSET_EMITTED]: " << print_money_brief(avc.amount_to_validate, ado.descriptor.decimal_point) << ", " << avc.asset_id << ": " << ado.descriptor.ticker << ", \"" << ado.descriptor.full_name << "\"", LOG_LEVEL_1); - break; - case ASSET_DESCRIPTOR_OPERATION_PUBLIC_BURN: - LOG_PRINT_MAGENTA("[ASSET_BURNT]: " << print_money_brief(avc.amount_to_validate, ado.descriptor.decimal_point) << ", " << avc.asset_id << ": " << ado.descriptor.ticker << ", \"" << ado.descriptor.full_name << "\"", LOG_LEVEL_1); - break; - default: - LOG_ERROR("Unknown operation type: " << (int)ado.operation_type); - } + asset_op_verification_context avc = { tx, tx_id, ado }; + CHECK_AND_ASSERT_MES(validate_asset_operation_against_current_blochain_state(avc), false, "asset operation validation failed"); + + assets_container::t_value_type local_asset_history{}; + if (avc.asset_op_history) + local_asset_history = *avc.asset_op_history; + local_asset_history.push_back(ado); + m_db_assets.set(avc.asset_id, local_asset_history); + + switch(ado.operation_type) + { + case ASSET_DESCRIPTOR_OPERATION_REGISTER: + LOG_PRINT_MAGENTA("[ASSET_REGISTERED]: " << print_money_brief(ado.descriptor.current_supply, ado.descriptor.decimal_point) << ", " << avc.asset_id << ": " << ado.descriptor.ticker << ", \"" << ado.descriptor.full_name << "\"", LOG_LEVEL_1); + break; + case ASSET_DESCRIPTOR_OPERATION_UPDATE: + LOG_PRINT_MAGENTA("[ASSET_UPDATED]: " << avc.asset_id << ": " << ado.descriptor.ticker << ", \"" << ado.descriptor.full_name << "\"", LOG_LEVEL_1); + break; + case ASSET_DESCRIPTOR_OPERATION_EMIT: + LOG_PRINT_MAGENTA("[ASSET_EMITTED]: " << print_money_brief(avc.amount_to_validate, ado.descriptor.decimal_point) << ", " << avc.asset_id << ": " << ado.descriptor.ticker << ", \"" << ado.descriptor.full_name << "\"", LOG_LEVEL_1); + break; + case ASSET_DESCRIPTOR_OPERATION_PUBLIC_BURN: + LOG_PRINT_MAGENTA("[ASSET_BURNT]: " << print_money_brief(avc.amount_to_validate, ado.descriptor.decimal_point) << ", " << avc.asset_id << ": " << ado.descriptor.ticker << ", \"" << ado.descriptor.full_name << "\"", LOG_LEVEL_1); + break; + default: + LOG_ERROR("Unknown operation type: " << (int)ado.operation_type); } return true; diff --git a/src/currency_core/blockchain_storage.h b/src/currency_core/blockchain_storage.h index eb9c017a..c24e1104 100644 --- a/src/currency_core/blockchain_storage.h +++ b/src/currency_core/blockchain_storage.h @@ -375,6 +375,8 @@ namespace currency bool for_altchain, const alt_chain_type& alt_chain = alt_chain_type(), uint64_t split_height = 0)const; + bool validate_asset_operation_against_current_blochain_state(asset_op_verification_context& avc) const; + void set_core_runtime_config(const core_runtime_config& pc) const; const core_runtime_config& get_core_runtime_config()const; size_t get_current_sequence_factor(bool pos)const; @@ -494,6 +496,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; + private: //-------------- DB containers -------------- @@ -670,7 +673,6 @@ namespace currency bool unprocess_blockchain_tx_extra(const transaction& tx); bool process_blockchain_tx_attachments(const transaction& tx, uint64_t h, const crypto::hash& bl_id, uint64_t timestamp); bool unprocess_blockchain_tx_attachments(const transaction& tx, uint64_t h, uint64_t timestamp); - bool validate_ado_ownership(asset_op_verification_context& avc); bool pop_alias_info(const extra_alias_entry& ai); bool put_alias_info(const transaction& tx, extra_alias_entry& ai); bool pop_asset_info(const crypto::public_key& asset_id); diff --git a/src/currency_core/currency_format_utils_abstract.h b/src/currency_core/currency_format_utils_abstract.h index 11d051b9..416d955b 100644 --- a/src/currency_core/currency_format_utils_abstract.h +++ b/src/currency_core/currency_format_utils_abstract.h @@ -151,6 +151,27 @@ namespace currency return return_value_if_none_found; } //--------------------------------------------------------------- + // if cb returns false, stop immediately and return false + template + bool process_type_in_variant_container_and_make_sure_its_unique(const variant_container_t& av, callback_t& cb, bool return_value_if_none_found = true) + { + bool found = false; + for (auto& ai : av) + { + if (ai.type() == typeid(specific_type_t)) + { + if (found) + return false; // already have it, type in not unique + found = true; + if (!cb(boost::get(ai))) + return false; + } + } + if (found) + return true; + return return_value_if_none_found; + } + //--------------------------------------------------------------- // callback should return true to continue iterating through the container template bool handle_2_alternative_types_in_variant_container(const container_t& container, callback_t cb) diff --git a/src/currency_core/tx_pool.cpp b/src/currency_core/tx_pool.cpp index 998d4fed..a18e896d 100644 --- a/src/currency_core/tx_pool.cpp +++ b/src/currency_core/tx_pool.cpp @@ -224,13 +224,19 @@ namespace currency } TIME_MEASURE_FINISH_PD(check_inputs_time); - TIME_MEASURE_START_PD(check_post_hf4_balance); if (tx.version > TRANSACTION_VERSION_PRE_HF4) { + TIME_MEASURE_START_PD(check_post_hf4_balance); r = check_tx_balance(tx, id); CHECK_AND_ASSERT_MES_CUSTOM(r, false, { tvc.m_verification_failed = true; }, "post-HF4 tx: balance proof is invalid"); + TIME_MEASURE_FINISH_PD(check_post_hf4_balance); + + r = process_type_in_variant_container_and_make_sure_its_unique(tx.extra, [&](const asset_descriptor_operation& ado){ + asset_op_verification_context avc = { tx, id, ado }; + return m_blockchain.validate_asset_operation_against_current_blochain_state(avc); + }, true); + CHECK_AND_ASSERT_MES_CUSTOM(r, false, { tvc.m_verification_failed = true; }, "post-HF4 tx: asset operation is invalid"); } - TIME_MEASURE_FINISH_PD(check_post_hf4_balance); do_insert_transaction(tx, id, blob_size, kept_by_block, tx_fee, ch_inp_res ? max_used_block_id : null_hash, ch_inp_res ? max_used_block_height : 0); From 80fd303081008bd53a29fbade886e90a334e0d05 Mon Sep 17 00:00:00 2001 From: sowle Date: Wed, 13 Mar 2024 21:30:43 +0100 Subject: [PATCH 04/16] compilation fixed for gcc (by using universal references for process_type_in_variant_container_*) --- src/currency_core/currency_format_utils_abstract.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/currency_core/currency_format_utils_abstract.h b/src/currency_core/currency_format_utils_abstract.h index 416d955b..3e5a63fe 100644 --- a/src/currency_core/currency_format_utils_abstract.h +++ b/src/currency_core/currency_format_utils_abstract.h @@ -134,7 +134,7 @@ namespace currency //--------------------------------------------------------------- // if cb returns true, it means "continue", false -- means "stop" template - bool process_type_in_variant_container(const variant_container_t& av, callback_t& cb, bool return_value_if_none_found = true) + bool process_type_in_variant_container(const variant_container_t& av, callback_t&& cb, bool return_value_if_none_found = true) { bool found = false; for (auto& ai : av) @@ -153,7 +153,7 @@ namespace currency //--------------------------------------------------------------- // if cb returns false, stop immediately and return false template - bool process_type_in_variant_container_and_make_sure_its_unique(const variant_container_t& av, callback_t& cb, bool return_value_if_none_found = true) + bool process_type_in_variant_container_and_make_sure_its_unique(const variant_container_t& av, callback_t&& cb, bool return_value_if_none_found = true) { bool found = false; for (auto& ai : av) From 69e68807bfe1afa2ea2a3f00c89a894cc1996ff3 Mon Sep 17 00:00:00 2001 From: sowle Date: Wed, 27 Mar 2024 18:57:30 +0100 Subject: [PATCH 05/16] coretests: minor forgotten change --- tests/core_tests/hard_fork_4.h | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/core_tests/hard_fork_4.h b/tests/core_tests/hard_fork_4.h index bf12419f..f8235675 100644 --- a/tests/core_tests/hard_fork_4.h +++ b/tests/core_tests/hard_fork_4.h @@ -13,6 +13,7 @@ struct hard_fork_4_consolidated_txs : public wallet_test bool c1(currency::core& c, size_t ev_index, const std::vector& events); mutable bool m_post_hf4_zarcanum = false; + mutable uint64_t m_bob_amount = 0; }; From 320816fd992a13f02ec1bd939437f083de5e6688 Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Wed, 27 Mar 2024 18:34:03 +0100 Subject: [PATCH 06/16] added test for getblocktemplate --- src/currency_core/blockchain_storage.cpp | 10 ++- tests/core_tests/chaingen_main.cpp | 2 + tests/core_tests/wallet_tests.cpp | 92 ++++++++++++++++++++++++ tests/core_tests/wallet_tests.h | 8 +++ 4 files changed, 109 insertions(+), 3 deletions(-) diff --git a/src/currency_core/blockchain_storage.cpp b/src/currency_core/blockchain_storage.cpp index 500983fc..0e6c923c 100644 --- a/src/currency_core/blockchain_storage.cpp +++ b/src/currency_core/blockchain_storage.cpp @@ -6414,11 +6414,16 @@ bool blockchain_storage::handle_block_to_main_chain(const block& bl, const crypt tx.signatures.clear(); tx.proofs.clear(); } - + currency::tx_verification_context tvc = AUTO_VAL_INIT(tvc); //std::vector tx_outs_commitments; if (!m_is_in_checkpoint_zone) { - auto cleanup = [&](){ purge_block_data_from_blockchain(bl, tx_processed_count); bvc.m_verification_failed = true; }; + auto cleanup = [&](){ + bool add_res = m_tx_pool.add_tx(tx, tvc, true, true); + m_tx_pool.add_transaction_to_black_list(tx); + purge_block_data_from_blockchain(bl, tx_processed_count); + bvc.m_verification_failed = true; + }; CHECK_AND_ASSERT_MES_CUSTOM(collect_rangeproofs_data_from_tx(tx, tx_id, range_proofs_agregated), false, cleanup(), "block " << id << ", tx " << tx_id << ": collect_rangeproofs_data_from_tx failed"); @@ -6435,7 +6440,6 @@ bool blockchain_storage::handle_block_to_main_chain(const block& bl, const crypt if(!check_tx_inputs(tx, tx_id)) { LOG_PRINT_L0("Block with id: " << id << " has at least one transaction (id: " << tx_id << ") with wrong inputs."); - currency::tx_verification_context tvc = AUTO_VAL_INIT(tvc); if (taken_from_pool) { bool add_res = m_tx_pool.add_tx(tx, tvc, true, true); diff --git a/tests/core_tests/chaingen_main.cpp b/tests/core_tests/chaingen_main.cpp index 31d317f7..aa0974a4 100644 --- a/tests/core_tests/chaingen_main.cpp +++ b/tests/core_tests/chaingen_main.cpp @@ -1089,6 +1089,8 @@ int main(int argc, char* argv[]) GENERATE_AND_PLAY_HF(wallet_rpc_exchange_suite, "3,4"); GENERATE_AND_PLAY(wallet_chain_switch_with_spending_the_same_ki); GENERATE_AND_PLAY(wallet_sending_to_integrated_address); + GENERATE_AND_PLAY_HF(block_template_blacklist_test, "4-*"); + // GENERATE_AND_PLAY(emission_test); // simulate 1 year of blockchain, too long run (1 y ~= 1 hr), by demand only // LOG_ERROR2("print_reward_change_first_blocks.log", currency::print_reward_change_first_blocks(525601).str()); // outputs first 1 year of blocks' rewards (simplier) diff --git a/tests/core_tests/wallet_tests.cpp b/tests/core_tests/wallet_tests.cpp index 373ac3a0..0be2a9bd 100644 --- a/tests/core_tests/wallet_tests.cpp +++ b/tests/core_tests/wallet_tests.cpp @@ -3809,3 +3809,95 @@ bool wallet_and_sweep_below::c1(currency::core& c, size_t ev_index, const std::v return true; } + + +//------------------------------------------------------------------------------ +block_template_blacklist_test::block_template_blacklist_test() +{ + REGISTER_CALLBACK_METHOD(block_template_blacklist_test, c1); +} + +bool block_template_blacklist_test::generate(std::vector& events) const +{ + // Test idea: basic check for wallet2::sweep_below() functionality + + uint64_t ts = test_core_time::get_time(); + m_accounts.resize(TOTAL_ACCS_COUNT); + account_base preminer_acc; + preminer_acc.generate(); + preminer_acc.set_createtime(ts); + account_base& miner_acc = m_accounts[MINER_ACC_IDX]; miner_acc.generate(); miner_acc.set_createtime(ts); + account_base& alice_acc = m_accounts[ALICE_ACC_IDX]; alice_acc.generate(); alice_acc.set_createtime(ts); + MAKE_GENESIS_BLOCK(events, blk_0, preminer_acc, ts); + DO_CALLBACK(events, "configure_core"); + + MAKE_NEXT_BLOCK(events, blk_1, blk_0, preminer_acc); + + REWIND_BLOCKS_N_WITH_TIME(events, blk_1r, blk_1, miner_acc, 3 * CURRENCY_MINED_MONEY_UNLOCK_WINDOW - 1); + + DO_CALLBACK(events, "c1"); + return true; +} + +bool block_template_blacklist_test::c1(currency::core& c, size_t ev_index, const std::vector& events) +{ + bool r = false; + 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); + + miner_wlt->refresh(); + miner_wlt->transfer(COIN / 10, alice_wlt->get_account().get_public_address()); + miner_wlt->transfer(COIN / 10, alice_wlt->get_account().get_public_address()); + + //take first transaction and corrupt it intentionalyy + std::list txs; + c.get_tx_pool().get_transactions(txs); + CHECK_AND_ASSERT_MES(txs.size() == 2, false, "wrong tx count"); + + + txs.resize(1); + currency::transaction broken_tx; + uint64_t blob_size = 0; + uint64_t fee = 0; + r = c.get_tx_pool().take_tx(currency::get_transaction_hash(*txs.begin()), broken_tx, blob_size, fee); + CHECK_AND_ASSERT_MES(r, false, "failed to take from pool"); + + + broken_tx.signatures.resize(broken_tx.signatures.size() - 1); + //manually add completely broken tx to pool + c.get_tx_pool().do_insert_transaction(broken_tx, get_transaction_hash(broken_tx), currency::get_object_blobsize(broken_tx), false, get_tx_fee(broken_tx), c.get_block_id_by_height(0), 0); + + CHECK_AND_ASSERT_MES(c.get_tx_pool().get_transactions_count() == 2, false, "wrong tx count"); + + + currency::create_block_template_params cbtp = AUTO_VAL_INIT(cbtp); + cbtp.miner_address = miner_wlt->get_account().get_public_address(); + + { + currency::create_block_template_response cbtr = AUTO_VAL_INIT(cbtr); + r = c.get_block_template(cbtp, cbtr); + + CHECK_AND_ASSERT_MES(r, false, "failed to create block template"); + CHECK_AND_ASSERT_MES(cbtr.b.tx_hashes.size() == 2, false, "failed to create block template"); + } + + r = mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c); + CHECK_AND_ASSERT_MES(!r, false, "Unexpectedly created block"); + + //now let's check if broken tx actually added to next blocktemplate + + { + currency::create_block_template_response cbtr = AUTO_VAL_INIT(cbtr); + r = c.get_block_template(cbtp, cbtr); + + CHECK_AND_ASSERT_MES(r, false, "failed to create block template"); + CHECK_AND_ASSERT_MES(cbtr.b.tx_hashes.size() == 1, false, "failed to create block template"); + + } + + r = mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c); + CHECK_AND_ASSERT_MES(r, false, "Unexpectedly failed to create block"); + + + return true; +} diff --git a/tests/core_tests/wallet_tests.h b/tests/core_tests/wallet_tests.h index a5aad448..cad3871e 100644 --- a/tests/core_tests/wallet_tests.h +++ b/tests/core_tests/wallet_tests.h @@ -294,3 +294,11 @@ struct wallet_and_sweep_below : public wallet_test bool generate(std::vector& events) const; bool c1(currency::core& c, size_t ev_index, const std::vector& events); }; + + +struct block_template_blacklist_test : public wallet_test +{ + block_template_blacklist_test(); + bool generate(std::vector& events) const; + bool c1(currency::core& c, size_t ev_index, const std::vector& events); +}; \ No newline at end of file From d2ee1b3fa8ae18a9ad96d76fbdff49b0da36ee5c Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Wed, 27 Mar 2024 19:10:15 +0100 Subject: [PATCH 07/16] added COMMAND_RPC_REMOVE_TX_FROM_POOL --- src/rpc/core_rpc_server.cpp | 14 ++++++++++++++ src/rpc/core_rpc_server.h | 2 ++ src/rpc/core_rpc_server_commands_defs.h | 22 ++++++++++++++++++++++ 3 files changed, 38 insertions(+) diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index d45e9704..1fbe0a5a 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -1333,6 +1333,20 @@ namespace currency res.status = API_RETURN_CODE_OK; return true; } + + //------------------------------------------------------------------------------------------------------------------------------ + bool core_rpc_server::on_remove_tx_from_pool(const COMMAND_RPC_REMOVE_TX_FROM_POOL::request& req, COMMAND_RPC_REMOVE_TX_FROM_POOL::response& res, connection_context& cntx) + { + for (const auto& tx_id_str : req.tx_to_remove) + { + crypto::hash tx_id = epee::transform_str_to_t_pod(tx_id_str); + currency::transaction tx; uint64_t dummy1 = 0; uint64_t dummy2 = 0; + m_core.get_tx_pool().take_tx(tx_id,tx, dummy1, dummy1); + } + + res.status = API_RETURN_CODE_OK; + return true; + } } diff --git a/src/rpc/core_rpc_server.h b/src/rpc/core_rpc_server.h index e88f6dbf..daf9452c 100644 --- a/src/rpc/core_rpc_server.h +++ b/src/rpc/core_rpc_server.h @@ -75,6 +75,7 @@ namespace currency bool on_aliases_by_address(const COMMAND_RPC_GET_ALIASES_BY_ADDRESS::request& req, COMMAND_RPC_GET_ALIASES_BY_ADDRESS::response& res, epee::json_rpc::error& error_resp, connection_context& cntx); bool on_get_alias_reward(const COMMAND_RPC_GET_ALIAS_REWARD::request& req, COMMAND_RPC_GET_ALIAS_REWARD::response& res, epee::json_rpc::error& error_resp, connection_context& cntx); bool on_reset_transaction_pool(const COMMAND_RPC_RESET_TX_POOL::request& req, COMMAND_RPC_RESET_TX_POOL::response& res, connection_context& cntx); + bool on_remove_tx_from_pool(const COMMAND_RPC_REMOVE_TX_FROM_POOL::request& req, COMMAND_RPC_REMOVE_TX_FROM_POOL::response& res, connection_context& cntx); bool on_get_pos_mining_details(const COMMAND_RPC_GET_POS_MINING_DETAILS::request& req, COMMAND_RPC_GET_POS_MINING_DETAILS::response& res, connection_context& cntx); bool on_get_current_core_tx_expiration_median(const COMMAND_RPC_GET_CURRENT_CORE_TX_EXPIRATION_MEDIAN::request& req, COMMAND_RPC_GET_CURRENT_CORE_TX_EXPIRATION_MEDIAN::response& res, connection_context& cntx); bool on_get_tx_details(const COMMAND_RPC_GET_TX_DETAILS::request& req, COMMAND_RPC_GET_TX_DETAILS::response& res, epee::json_rpc::error& error_resp, connection_context& cntx); @@ -156,6 +157,7 @@ namespace currency MAP_JON_RPC ("get_alt_blocks_details", on_get_alt_blocks_details, COMMAND_RPC_GET_ALT_BLOCKS_DETAILS) // MAP_JON_RPC ("reset_transaction_pool", on_reset_transaction_pool, COMMAND_RPC_RESET_TX_POOL) + MAP_JON_RPC ("remove_tx_from_pool", on_remove_tx_from_pool, COMMAND_RPC_REMOVE_TX_FROM_POOL) MAP_JON_RPC ("get_current_core_tx_expiration_median", on_get_current_core_tx_expiration_median, COMMAND_RPC_GET_CURRENT_CORE_TX_EXPIRATION_MEDIAN) // MAP_JON_RPC_WE("marketplace_global_get_offers_ex", on_get_offers_ex, COMMAND_RPC_GET_OFFERS_EX) diff --git a/src/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h index ce931d9d..42648bfa 100644 --- a/src/rpc/core_rpc_server_commands_defs.h +++ b/src/rpc/core_rpc_server_commands_defs.h @@ -1250,6 +1250,28 @@ namespace currency }; }; + struct COMMAND_RPC_REMOVE_TX_FROM_POOL + { + + struct request + { + std::list tx_to_remove; + + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(tx_to_remove) + END_KV_SERIALIZE_MAP() + }; + + struct response + { + std::string status; + + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(status) + END_KV_SERIALIZE_MAP() + }; + }; + struct COMMAND_RPC_GET_POS_MINING_DETAILS { struct request From f3820c32f2831a53ce10bcce75e8e65a872cb6d1 Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Wed, 27 Mar 2024 20:06:20 +0100 Subject: [PATCH 08/16] added log message for COMMAND_RPC_GETBLOCKTEMPLATE --- src/rpc/core_rpc_server.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index 1fbe0a5a..65a90b58 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -983,7 +983,7 @@ namespace currency res.seed = currency::ethash_epoch_to_seed(currency::ethash_height_to_epoch(res.height)); res.status = API_RETURN_CODE_OK; - + LOG_PRINT_L1("COMMAND_RPC_GETBLOCKTEMPLATE OK, response block: " << ENDL << currency::obj_to_json_str(resp.b)); return true; } //------------------------------------------------------------------------------------------------------------------------------ From b72a0593c6816b686656cd9ac9b90ad9c9b1fd1d Mon Sep 17 00:00:00 2001 From: zano build machine Date: Wed, 27 Mar 2024 22:53:47 +0300 Subject: [PATCH 09/16] === build number: 287 -> 288 === --- src/version.h.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/version.h.in b/src/version.h.in index 931b5c93..c1e80ca9 100644 --- a/src/version.h.in +++ b/src/version.h.in @@ -8,6 +8,6 @@ #define PROJECT_REVISION "0" #define PROJECT_VERSION PROJECT_MAJOR_VERSION "." PROJECT_MINOR_VERSION "." PROJECT_REVISION -#define PROJECT_VERSION_BUILD_NO 287 +#define PROJECT_VERSION_BUILD_NO 288 #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 "]" From df7b6a36745b7fbf436b0bb57b668a9931a5a485 Mon Sep 17 00:00:00 2001 From: sowle Date: Wed, 27 Mar 2024 22:13:43 +0100 Subject: [PATCH 10/16] tx pool: added ability to disable tx validation for tests --- src/currency_core/tx_pool.cpp | 14 ++++++++++++++ src/currency_core/tx_pool.h | 5 +++++ 2 files changed, 19 insertions(+) diff --git a/src/currency_core/tx_pool.cpp b/src/currency_core/tx_pool.cpp index a18e896d..33315870 100644 --- a/src/currency_core/tx_pool.cpp +++ b/src/currency_core/tx_pool.cpp @@ -104,6 +104,20 @@ namespace currency //--------------------------------------------------------------------------------- bool tx_memory_pool::add_tx(const transaction &tx, const crypto::hash &id, uint64_t blob_size, tx_verification_context& tvc, bool kept_by_block, bool from_core) { + // ------------------ UNSECURE CODE FOR TESTS --------------------- + if (m_unsecure_disable_tx_validation_on_addition) + { + uint64_t tx_fee = 0; + CHECK_AND_ASSERT_MES(get_tx_fee(tx, tx_fee), false, "get_tx_fee failed"); + do_insert_transaction(tx, id, blob_size, kept_by_block, tx_fee, null_hash, 0); + tvc.m_added_to_pool = true; + tvc.m_should_be_relayed = true; + tvc.m_verification_failed = false; + tvc.m_verification_impossible = false; + return true; + } + // ---------------- END OF UNSECURE CODE FOR TESTS ------------------- + bool r = false; // defaults diff --git a/src/currency_core/tx_pool.h b/src/currency_core/tx_pool.h index 8b3ec595..c97a498a 100644 --- a/src/currency_core/tx_pool.h +++ b/src/currency_core/tx_pool.h @@ -143,6 +143,10 @@ namespace currency bool is_tx_blacklisted(const crypto::hash& id) const; +#ifdef TX_POOL_USE_UNSECURE_TEST_FUNCTIONS + void unsecure_disable_tx_validation_on_addition(bool validation_disabled) { m_unsecure_disable_tx_validation_on_addition = validation_disabled; } +#endif + private: bool on_tx_add(crypto::hash tx_id, const transaction& tx, bool kept_by_block); bool on_tx_remove(const crypto::hash &tx_id, const transaction& tx, bool kept_by_block); @@ -197,6 +201,7 @@ namespace currency key_image_cache m_key_images; mutable epee::critical_section m_remove_stuck_txs_lock; + bool m_unsecure_disable_tx_validation_on_addition = false; }; } From 754a29a70963cb6904b75b8f3b2c72d84b9a30b6 Mon Sep 17 00:00:00 2001 From: sowle Date: Wed, 27 Mar 2024 22:15:13 +0100 Subject: [PATCH 11/16] wallet: defragmentation tx generation is now disabled by default --- src/wallet/wallet2.cpp | 10 +++++++--- src/wallet/wallet2.h | 3 +++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index cc533644..1264781e 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2023 Zano Project +// Copyright (c) 2014-2024 Zano Project // Copyright (c) 2014-2018 The Louisdor Project // Copyright (c) 2012-2013 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying @@ -81,6 +81,7 @@ namespace tools , m_log_prefix("???") , m_watch_only(false) , m_required_decoys_count(CURRENCY_DEFAULT_DECOY_SET_SIZE) + , m_defragmentation_tx_enabled(false) , m_max_allowed_output_amount_for_defragmentation_tx(CURRENCY_BLOCK_REWARD) , m_min_utxo_count_for_defragmentation_tx(WALLET_MIN_UTXO_COUNT_FOR_DEFRAGMENTATION_TX) , m_max_utxo_count_for_defragmentation_tx(WALLET_MAX_UTXO_COUNT_FOR_DEFRAGMENTATION_TX) @@ -3676,6 +3677,9 @@ void wallet2::get_transfers(transfer_container& incoming_transfers) const //---------------------------------------------------------------------------------------------------- bool wallet2::generate_utxo_defragmentation_transaction_if_needed(currency::transaction& tx) { + if (!m_defragmentation_tx_enabled) + return false; + construct_tx_param ctp = get_default_construct_tx_param(); ctp.create_utxo_defragmentation_tx = true; finalized_tx ftp{}; @@ -5947,8 +5951,8 @@ bool wallet2::decrypt_buffer(const std::string& buff, std::string& res_buff) //---------------------------------------------------------------------------------------------------- bool wallet2::prepare_tx_sources_for_defragmentation_tx(std::vector& sources, std::vector& selected_indicies, uint64_t& found_money) { - //prepare_free_transfers_cache(fake_outputs_count); - //free_amounts_cache_type& free_amounts_for_native_coin = m_found_free_amounts[currency::native_coin_asset_id]; + if (!m_defragmentation_tx_enabled) + return false; std::stringstream ss; if (epee::log_space::log_singletone::get_log_detalisation_level() >= LOG_LEVEL_2) diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index 413adb97..05863a18 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -884,10 +884,13 @@ private: bool m_do_rise_transfer; + + bool m_defragmentation_tx_enabled; uint64_t m_max_allowed_output_amount_for_defragmentation_tx; uint64_t m_min_utxo_count_for_defragmentation_tx; uint64_t m_max_utxo_count_for_defragmentation_tx; size_t m_decoys_count_for_defragmentation_tx; + size_t m_required_decoys_count; pending_ki_file_container_t m_pending_key_images_file_container; uint64_t m_upper_transaction_size_limit; //TODO: auto-calc this value or request from daemon, now use some fixed value From dd04d6367b35ff6379c3ecbaf9b872db6fd63647 Mon Sep 17 00:00:00 2001 From: sowle Date: Wed, 27 Mar 2024 22:18:06 +0100 Subject: [PATCH 12/16] coretests: multiassets_basic_test improved to reflect recent changes with tx pool validation --- tests/core_tests/chaingen.cpp | 4 +- tests/core_tests/chaingen.h | 5 +- tests/core_tests/multiassets_test.cpp | 86 ++++++++++++++++++++++++++- 3 files changed, 89 insertions(+), 6 deletions(-) diff --git a/tests/core_tests/chaingen.cpp b/tests/core_tests/chaingen.cpp index f7aa0612..73340589 100644 --- a/tests/core_tests/chaingen.cpp +++ b/tests/core_tests/chaingen.cpp @@ -1,11 +1,9 @@ -// Copyright (c) 2014-2022 Zano Project +// Copyright (c) 2014-2024 Zano Project // Copyright (c) 2014-2018 The Louisdor Project // Copyright (c) 2012-2013 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#define USE_INSECURE_RANDOM_RPNG_ROUTINES // turns on pseudorandom number generator manupulations for tests - #include "chaingen.h" #include diff --git a/tests/core_tests/chaingen.h b/tests/core_tests/chaingen.h index 65a89226..087e0c3a 100644 --- a/tests/core_tests/chaingen.h +++ b/tests/core_tests/chaingen.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2022 Zano Project +// Copyright (c) 2014-2024 Zano Project // Copyright (c) 2014-2018 The Louisdor Project // Copyright (c) 2012-2013 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying @@ -9,7 +9,8 @@ #include #include -#define USE_INSECURE_RANDOM_RPNG_ROUTINES // turns on pseudorandom number generator manupulations for tests +#define USE_INSECURE_RANDOM_RPNG_ROUTINES // turns on pseudorandom number generator manupulations for tests +#define TX_POOL_USE_UNSECURE_TEST_FUNCTIONS // turns on special tests functions of tx pool #include "currency_core/currency_basic.h" #include "currency_core/currency_core.h" diff --git a/tests/core_tests/multiassets_test.cpp b/tests/core_tests/multiassets_test.cpp index 1a933292..240b3bb3 100644 --- a/tests/core_tests/multiassets_test.cpp +++ b/tests/core_tests/multiassets_test.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2023 Zano Project +// Copyright (c) 2014-2024 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. @@ -186,7 +186,20 @@ bool multiassets_basic_test::c1(currency::core& c, size_t ev_index, const std::v CHECK_AND_ASSERT_MES(r, false, "Failed to get_asset_info"); asset_info.meta_info = "{\"some2\": \"info2\"}"; + r = false; + try + { + miner_wlt->update_asset(asset_id, asset_info, tx); + } + catch(tools::error::tx_rejected&) + { + r = true; + } + CHECK_AND_ASSERT_MES(r, false, "Test failed, broken ownership passed"); + + c.get_tx_pool().unsecure_disable_tx_validation_on_addition(true); miner_wlt->update_asset(asset_id, asset_info, tx); + c.get_tx_pool().unsecure_disable_tx_validation_on_addition(false); r = mine_next_pow_blocks_in_playtime(miner_wlt->get_account().get_public_address(), c, 2); CHECK_AND_ASSERT_MES(!r, false, "Test failed, broken ownership passed"); c.get_tx_pool().purge_transactions(); @@ -202,25 +215,54 @@ bool multiassets_basic_test::c1(currency::core& c, size_t ev_index, const std::v CHECK_AND_ASSERT_MES(r, false, "Failed to get_asset_info"); asset_info.ticker = "XXX"; + r = false; + try + { + miner_wlt->update_asset(asset_id, asset_info, tx); + } + catch(tools::error::tx_rejected&) + { + r = true; + } + CHECK_AND_ASSERT_MES(r, false, "update_asset succeeded, but this shouldn't happened"); + + c.get_tx_pool().unsecure_disable_tx_validation_on_addition(true); miner_wlt->update_asset(asset_id, asset_info, tx); CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Unexpected number of txs in the pool: " << c.get_pool_transactions_count()); r = mine_next_pow_block_in_playtime(miner_wlt->get_account().get_public_address(), c); CHECK_AND_ASSERT_MES(!r, false, "block with a bad tx was unexpectedly mined"); 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 was not confirmed + c.get_tx_pool().unsecure_disable_tx_validation_on_addition(false); c.get_tx_pool().purge_transactions(); + CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Unexpected number of txs in the pool: " << c.get_pool_transactions_count()); // make sure tx was not added + // check update_asset() with modified 'full_name' r = c.get_blockchain_storage().get_asset_info(asset_id, asset_info); CHECK_AND_ASSERT_MES(r, false, "Failed to get_asset_info"); asset_info.full_name = "XXX"; + r = false; + try + { + miner_wlt->update_asset(asset_id, asset_info, tx); + } + catch(tools::error::tx_rejected&) + { + r = true; + } + CHECK_AND_ASSERT_MES(r, false, "update_asset succeeded, but this shouldn't happened"); + + c.get_tx_pool().unsecure_disable_tx_validation_on_addition(true); miner_wlt->update_asset(asset_id, asset_info, tx); CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Unexpected number of txs in the pool: " << c.get_pool_transactions_count()); r = mine_next_pow_block_in_playtime(miner_wlt->get_account().get_public_address(), c); CHECK_AND_ASSERT_MES(!r, false, "block with a bad tx was unexpectedly mined"); 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 was not confirmed + c.get_tx_pool().unsecure_disable_tx_validation_on_addition(false); c.get_tx_pool().purge_transactions(); + CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Unexpected number of txs in the pool: " << c.get_pool_transactions_count()); // make sure tx was not added miner_wlt->refresh(); @@ -229,13 +271,27 @@ bool multiassets_basic_test::c1(currency::core& c, size_t ev_index, const std::v CHECK_AND_ASSERT_MES(r, false, "Failed to get_asset_info"); asset_info.decimal_point = 3; + r = false; + try + { + miner_wlt->update_asset(asset_id, asset_info, tx); + } + catch(tools::error::tx_rejected&) + { + r = true; + } + CHECK_AND_ASSERT_MES(r, false, "update_asset succeeded, but this shouldn't happened"); + + c.get_tx_pool().unsecure_disable_tx_validation_on_addition(true); miner_wlt->update_asset(asset_id, asset_info, tx); CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Unexpected number of txs in the pool: " << c.get_pool_transactions_count()); r = mine_next_pow_block_in_playtime(miner_wlt->get_account().get_public_address(), c); CHECK_AND_ASSERT_MES(!r, false, "block with a bad tx was unexpectedly mined"); 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 was not confirmed + c.get_tx_pool().unsecure_disable_tx_validation_on_addition(false); c.get_tx_pool().purge_transactions(); miner_wlt->refresh(); + CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Unexpected number of txs in the pool: " << c.get_pool_transactions_count()); // make sure tx was not added // check update_asset() with modified 'owner' @@ -258,14 +314,29 @@ bool multiassets_basic_test::c1(currency::core& c, size_t ev_index, const std::v o.pado->descriptor.current_supply += 1000000; }); //test emit function but re-adjust current_supply to wrong amount + r = false; + try + { + miner_wlt->emit_asset(asset_id, destinations, tx); + } + catch(tools::error::tx_rejected&) + { + r = true; + } + CHECK_AND_ASSERT_MES(r, false, "emit_asset succeeded, but this shouldn't happened"); + + c.get_tx_pool().unsecure_disable_tx_validation_on_addition(true); miner_wlt->emit_asset(asset_id, destinations, tx); CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Unexpected number of txs in the pool: " << c.get_pool_transactions_count()); r = mine_next_pow_block_in_playtime(miner_wlt->get_account().get_public_address(), c); CHECK_AND_ASSERT_MES(!r, false, "block with a bad tx was unexpectedly mined"); 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 was not confirmed + c.get_tx_pool().unsecure_disable_tx_validation_on_addition(false); c.get_tx_pool().purge_transactions(); miner_wlt->refresh(); + CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Unexpected number of txs in the pool: " << c.get_pool_transactions_count()); // make sure tx was not added + //------------------- tests that trying to break stuff ------------------- //test burn that burns more than tx has miner_wlt->get_debug_events_dispatcher().UNSUBSCRIBE_ALL(); @@ -276,11 +347,24 @@ bool multiassets_basic_test::c1(currency::core& c, size_t ev_index, const std::v }); + r = false; + try + { + miner_wlt->burn_asset(asset_id, 10000000000000, tx); + } + catch(tools::error::tx_rejected&) + { + r = true; + } + CHECK_AND_ASSERT_MES(r, false, "burn_asset succeeded, but this shouldn't happened"); + + c.get_tx_pool().unsecure_disable_tx_validation_on_addition(true); miner_wlt->burn_asset(asset_id, 10000000000000, tx); CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Unexpected number of txs in the pool: " << c.get_pool_transactions_count()); r = mine_next_pow_block_in_playtime(miner_wlt->get_account().get_public_address(), c); CHECK_AND_ASSERT_MES(!r, false, "block with a bad tx was unexpectedly mined"); 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 was not confirmed + c.get_tx_pool().unsecure_disable_tx_validation_on_addition(false); c.get_tx_pool().purge_transactions(); miner_wlt->refresh(); miner_wlt->get_debug_events_dispatcher().UNSUBSCRIBE_ALL(); From 9cf3c80fba6a46c55ea057ee52b91c4a91b18e18 Mon Sep 17 00:00:00 2001 From: zano build machine Date: Thu, 28 Mar 2024 00:23:34 +0300 Subject: [PATCH 13/16] === build number: 288 -> 289 === --- src/version.h.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/version.h.in b/src/version.h.in index c1e80ca9..0292ae28 100644 --- a/src/version.h.in +++ b/src/version.h.in @@ -8,6 +8,6 @@ #define PROJECT_REVISION "0" #define PROJECT_VERSION PROJECT_MAJOR_VERSION "." PROJECT_MINOR_VERSION "." PROJECT_REVISION -#define PROJECT_VERSION_BUILD_NO 288 +#define PROJECT_VERSION_BUILD_NO 289 #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 "]" From ad281664c38b5208d5782e143129c592eb38a89a Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Wed, 27 Mar 2024 23:07:26 +0100 Subject: [PATCH 14/16] fixed macos compilation --- src/rpc/core_rpc_server.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index 65a90b58..46d27670 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -1340,8 +1340,8 @@ namespace currency for (const auto& tx_id_str : req.tx_to_remove) { crypto::hash tx_id = epee::transform_str_to_t_pod(tx_id_str); - currency::transaction tx; uint64_t dummy1 = 0; uint64_t dummy2 = 0; - m_core.get_tx_pool().take_tx(tx_id,tx, dummy1, dummy1); + currency::transaction tx; size_t dummy1 = 0; uint64_t dummy2 = 0; + m_core.get_tx_pool().take_tx(tx_id, tx, dummy1, dummy1); } res.status = API_RETURN_CODE_OK; From 6f35ced0525e71dce0ed57329bfc3aa50e4104e9 Mon Sep 17 00:00:00 2001 From: zano build machine Date: Thu, 28 Mar 2024 01:08:01 +0300 Subject: [PATCH 15/16] === build number: 289 -> 290 === --- src/version.h.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/version.h.in b/src/version.h.in index 0292ae28..fc6d8a54 100644 --- a/src/version.h.in +++ b/src/version.h.in @@ -8,6 +8,6 @@ #define PROJECT_REVISION "0" #define PROJECT_VERSION PROJECT_MAJOR_VERSION "." PROJECT_MINOR_VERSION "." PROJECT_REVISION -#define PROJECT_VERSION_BUILD_NO 289 +#define PROJECT_VERSION_BUILD_NO 290 #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 "]" From 98d124860cbef3747991ce9637948ff62cef717c Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Wed, 27 Mar 2024 23:21:56 +0100 Subject: [PATCH 16/16] fixed macos compilation - 2 --- src/rpc/core_rpc_server.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index 46d27670..cd9c20d2 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -1341,7 +1341,7 @@ namespace currency { crypto::hash tx_id = epee::transform_str_to_t_pod(tx_id_str); currency::transaction tx; size_t dummy1 = 0; uint64_t dummy2 = 0; - m_core.get_tx_pool().take_tx(tx_id, tx, dummy1, dummy1); + m_core.get_tx_pool().take_tx(tx_id, tx, dummy1, dummy2); } res.status = API_RETURN_CODE_OK;