Merge branch 'master' into develop

# Conflicts:
#	src/currency_core/tx_pool.cpp
This commit is contained in:
sowle 2024-03-27 23:52:24 +01:00
commit f4da18cc3f
No known key found for this signature in database
GPG key ID: C07A24B2D89D49FC
17 changed files with 350 additions and 55 deletions

View file

@ -4016,7 +4016,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);
@ -4028,32 +4028,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*/)
@ -4096,25 +4087,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;
@ -6412,11 +6418,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<crypto::point_t&> 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");
@ -6433,7 +6444,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);

View file

@ -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);

View file

@ -134,7 +134,7 @@ namespace currency
//---------------------------------------------------------------
// if cb returns true, it means "continue", false -- means "stop"
template<typename specific_type_t, typename variant_container_t, typename callback_t>
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)
@ -151,6 +151,27 @@ namespace currency
return return_value_if_none_found;
}
//---------------------------------------------------------------
// if cb returns false, stop immediately and return false
template<typename specific_type_t, typename variant_container_t, typename callback_t>
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<specific_type_t>(ai)))
return false;
}
}
if (found)
return true;
return return_value_if_none_found;
}
//---------------------------------------------------------------
// callback should return true to continue iterating through the container
template <typename A, typename B, typename container_t, typename callback_t>
bool handle_2_alternative_types_in_variant_container(const container_t& container, callback_t cb)

View file

@ -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
@ -224,13 +238,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<asset_descriptor_operation>(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);
@ -885,7 +905,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 +996,8 @@ namespace currency
return "(no transactions, the pool is empty)";
// sort output by receive time
txs.sort([](const std::pair<crypto::hash, tx_details>& lhs, const std::pair<crypto::hash, tx_details>& 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 +1015,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 +1344,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);

View file

@ -141,6 +141,12 @@ 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;
#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);
@ -195,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;
};
}

View file

@ -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;
}
//------------------------------------------------------------------------------------------------------------------------------
@ -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<crypto::hash>(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, dummy2);
}
res.status = API_RETURN_CODE_OK;
return true;
}
}

View file

@ -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)

View file

@ -1250,6 +1250,28 @@ namespace currency
};
};
struct COMMAND_RPC_REMOVE_TX_FROM_POOL
{
struct request
{
std::list<std::string> 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

View file

@ -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 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 "]"

View file

@ -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)
@ -3672,6 +3673,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{};
@ -6001,8 +6005,8 @@ bool wallet2::decrypt_buffer(const std::string& buff, std::string& res_buff)
//----------------------------------------------------------------------------------------------------
bool wallet2::prepare_tx_sources_for_defragmentation_tx(std::vector<currency::tx_source_entry>& sources, std::vector<uint64_t>& 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)

View file

@ -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

View file

@ -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 <vector>

View file

@ -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 <string>
#include <iostream>
#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"

View file

@ -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)

View file

@ -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();

View file

@ -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<test_event_entry>& 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<test_event_entry>& events)
{
bool r = false;
std::shared_ptr<tools::wallet2> miner_wlt = init_playtime_test_wallet(events, c, MINER_ACC_IDX);
std::shared_ptr<tools::wallet2> 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<transaction> 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;
}

View file

@ -294,3 +294,11 @@ struct wallet_and_sweep_below : public wallet_test
bool generate(std::vector<test_event_entry>& events) const;
bool c1(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events);
};
struct block_template_blacklist_test : public wallet_test
{
block_template_blacklist_test();
bool generate(std::vector<test_event_entry>& events) const;
bool c1(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events);
};