1
0
Fork 0
forked from lthn/blockchain

Merge branch 'small_amount_min_outs' into develop

This commit is contained in:
sowle 2025-03-12 06:29:23 +01:00
commit 01b5f89725
No known key found for this signature in database
GPG key ID: C07A24B2D89D49FC
3 changed files with 40 additions and 19 deletions

View file

@ -2409,7 +2409,7 @@ bool wallet2::sweep_bare_unspent_outputs(const currency::account_public_address&
}
uint64_t fee = TX_DEFAULT_FEE;
std::vector<tx_destination_entry> destinations{ tx_destination_entry(group.total_amount + group.additional_tid_amount - fee, target_address) };
assets_selection_context needed_money_map{ std::make_pair(native_coin_asset_id, selection_for_amount{group.total_amount + group.additional_tid_amount, group.total_amount + group.additional_tid_amount}) };
assets_selection_context needed_money_map{ std::make_pair(native_coin_asset_id, selection_for_amount{group.total_amount + group.additional_tid_amount, group.total_amount + group.additional_tid_amount, group.total_amount + group.additional_tid_amount}) };
try
{
prepare_tx_destinations(needed_money_map, get_current_split_strategy(), tx_dust_policy{}, destinations, 0 /* tx_flags */, ftp.prepared_destinations);
@ -7096,25 +7096,45 @@ bool wallet2::prepare_tx_sources_htlc(crypto::hash htlc_tx_id, const std::string
assets_selection_context wallet2::get_needed_money(uint64_t fee, const std::vector<currency::tx_destination_entry>& dsts)
{
assets_selection_context amounts_map;
amounts_map[currency::native_coin_asset_id].needed_amount = fee;
auto& native_coin_item = amounts_map[currency::native_coin_asset_id];
native_coin_item.needed_amount = native_coin_item.requested_amount = fee;
uint64_t raw_amount_sum_of_non_native_assets = 0;
for (auto& dt : dsts)
{
if (dt.asset_id == currency::null_pkey)
continue; //this destination for emmition only
continue; // asset emission output, don't need to take into account
THROW_IF_TRUE_WALLET_EX(0 == dt.amount, error::zero_destination);
uint64_t money_to_add = dt.amount;
if (dt.amount_to_provide || dt.flags & tx_destination_entry_flags::tdef_explicit_amount_to_provide)
if (dt.amount_to_provide || (dt.flags & tx_destination_entry_flags::tdef_explicit_amount_to_provide))
money_to_add = dt.amount_to_provide;
amounts_map[dt.asset_id].needed_amount += money_to_add;
THROW_IF_TRUE_WALLET_EX(amounts_map[dt.asset_id].needed_amount < money_to_add, error::tx_sum_overflow, dsts, fee);
//clean up empty entries
if (amounts_map[dt.asset_id].needed_amount == 0)
auto& amount_item = amounts_map[dt.asset_id];
amount_item.needed_amount += money_to_add;
THROW_IF_TRUE_WALLET_EX(amount_item.needed_amount < money_to_add, error::tx_sum_overflow, dsts, fee);
if (amount_item.needed_amount == 0)
{
amounts_map.erase(amounts_map.find(dt.asset_id));
amounts_map.erase(amounts_map.find(dt.asset_id)); // clean up empty entries
}
else
{
amount_item.requested_amount = amount_item.needed_amount;
if (dt.asset_id != native_coin_asset_id)
raw_amount_sum_of_non_native_assets += amount_item.needed_amount;
}
}
// handle a case when the total amount of assets being transferred is too small to satisfy CURRENCY_TX_MIN_ALLOWED_OUTS limit
// AND there will be no change output in native coins => increase the needed_amount to enforce creating the change output
// (Note: in case we will be okay with zero-amount outputs at some point, this could be simplified and get rid of requested_amount field -- sowle)
if (raw_amount_sum_of_non_native_assets != 0 &&
raw_amount_sum_of_non_native_assets < CURRENCY_TX_MIN_ALLOWED_OUTS &&
amounts_map[currency::native_coin_asset_id].requested_amount == fee)
{
amounts_map[currency::native_coin_asset_id].requested_amount += CURRENCY_TX_MIN_ALLOWED_OUTS - 1;
}
return amounts_map;
}
//----------------------------------------------------------------------------------------------------------------
@ -7429,7 +7449,7 @@ bool wallet2::select_indices_for_transfer(assets_selection_context& needed_money
{
for (auto& item : needed_money_map)
{
if (item.second.needed_amount == 0)
if (item.second.requested_amount == 0)
continue;
const crypto::public_key asset_id = item.first;
@ -7439,9 +7459,9 @@ bool wallet2::select_indices_for_transfer(assets_selection_context& needed_money
WLT_LOG_L1("select_indices_for_transfer: unknown asset id: " << asset_id);
auto asset_cache_it = m_found_free_amounts.find(asset_id);
THROW_IF_FALSE_WALLET_EX(asset_cache_it != m_found_free_amounts.end(), error::not_enough_money, item.second.found_amount, item.second.needed_amount, (uint64_t)0, asset_id, asset_info.decimal_point);
item.second.found_amount = select_indices_for_transfer(selected_indexes, asset_cache_it->second, item.second.needed_amount, fake_outputs_count, asset_id, asset_info.decimal_point);
THROW_IF_FALSE_WALLET_EX(item.second.found_amount >= item.second.needed_amount, error::not_enough_money, item.second.found_amount, item.second.needed_amount, (uint64_t)0, asset_id, asset_info.decimal_point);
THROW_IF_FALSE_WALLET_EX(asset_cache_it != m_found_free_amounts.end(), error::not_enough_money, item.second.found_amount, item.second.requested_amount, (uint64_t)0, asset_id, asset_info.decimal_point);
item.second.found_amount = select_indices_for_transfer(selected_indexes, asset_cache_it->second, item.second.requested_amount, fake_outputs_count, asset_id, asset_info.decimal_point);
THROW_IF_FALSE_WALLET_EX(item.second.found_amount >= item.second.requested_amount, error::not_enough_money, item.second.found_amount, item.second.requested_amount, (uint64_t)0, asset_id, asset_info.decimal_point);
}
if (m_current_context.pconstruct_tx_param && m_current_context.pconstruct_tx_param->need_at_least_1_zc)
{
@ -7881,11 +7901,11 @@ bool wallet2::prepare_transaction(construct_tx_param& ctp, currency::finalize_tx
if (ftp.tx_version > TRANSACTION_VERSION_PRE_HF4)
{
for (const auto& el : msc.proposal_info.to_initiator)
needed_money_map[el.asset_id].needed_amount += el.amount;
needed_money_map[el.asset_id].add_to_needed_and_requested_amount(el.amount);
}
if (msc.escrow)
needed_money_map[currency::native_coin_asset_id].needed_amount += (currency::get_outs_money_amount(tx_for_mode_separate) - get_inputs_money_amount(tx_for_mode_separate));
needed_money_map[currency::native_coin_asset_id].add_to_needed_and_requested_amount(currency::get_outs_money_amount(tx_for_mode_separate) - get_inputs_money_amount(tx_for_mode_separate));
}
TIME_MEASURE_FINISH_MS(get_needed_money_time);

View file

@ -244,9 +244,10 @@ namespace tools
struct selection_for_amount
{
uint64_t needed_amount = 0;
uint64_t found_amount = 0;
//std::vector<uint64_t> selected_indicies;
uint64_t needed_amount = 0; // amount that is necessary (sum of outputs + fee)
uint64_t requested_amount = 0; // amount that is used when looking for outputs to spend (requested_amount >= needed_amount)
uint64_t found_amount = 0; // sum amount that was found in the wallet, (found_amount >= requested_amount); found_amount - needed_amount = change
void add_to_needed_and_requested_amount(uint64_t v) { needed_amount += v; requested_amount += v; } // consider removing this and 'requested_amount' when we start using zero-amount outputs -- sowle
};
typedef std::unordered_map<crypto::public_key, selection_for_amount> assets_selection_context;

View file

@ -1233,7 +1233,7 @@ bool asset_operation_and_hardfork_checks::c1(
check_balance_via_wallet(*wallet,
/* name = */ "Alice",
/* expected_total = */ 1'000'000'000'000'000'000,
/* expected_mined = */ 2 * COIN,
/* expected_mined = */ INVALID_BALANCE_VAL,
/* expected_unlocked = */ 1'000'000'000'000'000'000,
/* expected_awaiting_in = */ INVALID_BALANCE_VAL,
/* expected_awaiting_out = */ INVALID_BALANCE_VAL,