1
0
Fork 0
forked from lthn/blockchain

fixed crash in decoy_selection api

This commit is contained in:
cryptozoidberg 2024-01-17 18:07:41 +01:00
parent 01f00a67e6
commit 997dcb8312
No known key found for this signature in database
GPG key ID: 22DEB97A54C6FDEC
3 changed files with 51 additions and 14 deletions

View file

@ -2726,11 +2726,12 @@ bool blockchain_storage::get_target_outs_for_amount_prezarcanum(const COMMAND_RP
}
}
//------------------------------------------------------------------
bool blockchain_storage::get_target_outs_for_amount_postzarcanum(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2::request& req, const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2::offsets_distribution& details, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount& result_outs, std::map<uint64_t, uint64_t>& amounts_to_up_index_limit_cache) const
bool blockchain_storage::get_target_outs_for_postzarcanum(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2::request& req, const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2::offsets_distribution& details, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount& result_outs, std::map<uint64_t, uint64_t>& amounts_to_up_index_limit_cache) const
{
std::set<uint64_t> used;
for (auto offset : details.offsets)
{
//perfectly we would need to find transaction's output on the given height, with the given probability
//of being coinbase(coinbase outputs should be included less in decoy selection algorithm)
bool is_coinbase = (crypto::rand<uint64_t>() % 101) > req.coinbase_percents ? false : true;
@ -2749,8 +2750,6 @@ bool blockchain_storage::get_target_outs_for_amount_postzarcanum(const COMMAND_R
#define TARGET_RANDOM_OUTS_SELECTIOM_POOL_MIN 10
//try to find output around given H
std::vector<uint64_t> selected_global_indexes;
auto process_tx = [&](const crypto::hash& tx_id) {
auto tx_ptr = m_db_transactions.find(tx_id);
@ -2778,6 +2777,11 @@ bool blockchain_storage::get_target_outs_for_amount_postzarcanum(const COMMAND_R
continue;
}
if (used.find(tx_ptr->m_global_output_indexes[i]) != used.end())
{
continue;
}
// add output
// note: code that will process selected_global_indes will be revisiting transactions entries to obtain all
// needed data, that should work relatively effective because of on-top-of-db cache keep daya unserialized
@ -2788,7 +2792,7 @@ bool blockchain_storage::get_target_outs_for_amount_postzarcanum(const COMMAND_R
while (selected_global_indexes.size() < TARGET_RANDOM_OUTS_SELECTIOM_POOL_MIN)
{
auto block_ptr = m_db_blocks.get(estimated_h--);
auto block_ptr = m_db_blocks.get(estimated_h);
if (is_coinbase && is_pos_block(block_ptr->bl) )
{
process_tx(get_transaction_hash(block_ptr->bl.miner_tx));
@ -2801,12 +2805,25 @@ bool blockchain_storage::get_target_outs_for_amount_postzarcanum(const COMMAND_R
process_tx(tx_id);
}
}
if(estimated_h)
estimated_h--;
else
{
//likely unusual situation when blocks enumerated all way back to genesis
//let's check if we have at least something
if (!selected_global_indexes.size())
{
//need to regenerate offsets
return false;
}
}
}
//pick up a random output from selected_global_indes
uint64_t global_index = selected_global_indexes[crypto::rand<uint64_t>() % selected_global_indexes.size()];
bool res = add_out_to_get_random_outs(result_outs, details.amount, global_index, details.offsets.size(), req.use_forced_mix_outs, req.height_upper_limit);
CHECK_AND_ASSERT_THROW_MES(res, "Failed to add_out_to_get_random_outs([" << global_index << "]) at postzarcanum era");
used.insert(global_index);
}
return true;
}
@ -2824,16 +2841,19 @@ bool blockchain_storage::get_random_outs_for_amounts2(const COMMAND_RPC_GET_RAND
COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount& result_outs = *res.outs.insert(res.outs.end(), COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount());
result_outs.amount = amount;
bool r = false;
if (amount == 0)
{
//zarcanum era inputs
get_target_outs_for_amount_postzarcanum(req, req.amounts[i], result_outs, amounts_to_up_index_limit_cache);
r = get_target_outs_for_postzarcanum(req, req.amounts[i], result_outs, amounts_to_up_index_limit_cache);
}
else
{
//zarcanum era inputs
get_target_outs_for_amount_prezarcanum(req, req.amounts[i], result_outs, amounts_to_up_index_limit_cache);
r = get_target_outs_for_amount_prezarcanum(req, req.amounts[i], result_outs, amounts_to_up_index_limit_cache);
}
if (!r)
return false;
}
return true;
}

View file

@ -639,7 +639,7 @@ namespace currency
bool pop_transaction_from_global_index(const transaction& tx, const crypto::hash& tx_id);
bool add_out_to_get_random_outs(COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount& result_outs, uint64_t amount, size_t i, uint64_t mix_count, bool use_only_forced_to_mix = false, uint64_t height_upper_limit = 0) const;
bool get_target_outs_for_amount_prezarcanum(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2::request& req, const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2::offsets_distribution& details, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount& result_outs, std::map<uint64_t, uint64_t>& amounts_to_up_index_limit_cache) const;
bool get_target_outs_for_amount_postzarcanum(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2::request& req, const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2::offsets_distribution& details, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount& result_outs, std::map<uint64_t, uint64_t>& amounts_to_up_index_limit_cache) const;
bool get_target_outs_for_postzarcanum(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2::request& req, const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2::offsets_distribution& details, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount& result_outs, std::map<uint64_t, uint64_t>& amounts_to_up_index_limit_cache) const;
bool add_block_as_invalid(const block& bl, const crypto::hash& h);
bool add_block_as_invalid(const block_extended_info& bei, const crypto::hash& h);
size_t find_end_of_allowed_index(uint64_t amount)const;

View file

@ -5922,12 +5922,29 @@ bool wallet2::prepare_tx_sources(size_t fake_outputs_count, std::vector<currency
}
}
bool r = m_core_proxy->call_COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2(req, daemon_resp);
THROW_IF_FALSE_WALLET_EX(r, error::no_connection_to_daemon, "getrandom_outs2.bin");
THROW_IF_FALSE_WALLET_EX(daemon_resp.status != API_RETURN_CODE_BUSY, error::daemon_busy, "getrandom_outs.bin");
THROW_IF_FALSE_WALLET_EX(daemon_resp.status == API_RETURN_CODE_OK, error::get_random_outs_error, daemon_resp.status);
WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(daemon_resp.outs.size() == selected_indicies.size(),
"daemon returned wrong response for getrandom_outs.bin, wrong amounts count = " << daemon_resp.outs.size() << ", expected: " << selected_indicies.size());
size_t attempt_count = 0;
while (true)
{
bool r = m_core_proxy->call_COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2(req, daemon_resp);
THROW_IF_FALSE_WALLET_EX(r, error::no_connection_to_daemon, "getrandom_outs2.bin");
if(daemon_resp.status == API_RETURN_CODE_FAIL)
{
if (attempt_count < 10)
{
attempt_count++;
continue;
}
else
{
WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(daemon_resp.outs.size() == selected_indicies.size(),
"unable to exacute getrandom_outs.bin after 10 attempts with code API_RETURN_CODE_FAIL, there must be problems with mixins");
}
}
THROW_IF_FALSE_WALLET_EX(daemon_resp.status != API_RETURN_CODE_BUSY, error::daemon_busy, "getrandom_outs.bin");
THROW_IF_FALSE_WALLET_EX(daemon_resp.status == API_RETURN_CODE_OK, error::get_random_outs_error, daemon_resp.status);
WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(daemon_resp.outs.size() == selected_indicies.size(),
"daemon returned wrong response for getrandom_outs.bin, wrong amounts count = " << daemon_resp.outs.size() << ", expected: " << selected_indicies.size());
}
std::vector<COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount> scanty_outs;
for(COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount& amount_outs : daemon_resp.outs)