Merge branch 'master' into develop
# Conflicts: # src/currency_core/tx_pool.cpp
This commit is contained in:
commit
f4da18cc3f
17 changed files with 350 additions and 55 deletions
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 "]"
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
};
|
||||
Loading…
Add table
Reference in a new issue