diff --git a/src/currency_core/currency_format_utils.cpp b/src/currency_core/currency_format_utils.cpp index 9adeb482..dc37bb07 100644 --- a/src/currency_core/currency_format_utils.cpp +++ b/src/currency_core/currency_format_utils.cpp @@ -1988,7 +1988,7 @@ namespace currency { if (summary_outs_money > summary_inputs_money) { - LOG_ERROR("Transaction inputs money (" << summary_inputs_money << ") less than outputs money (" << summary_outs_money << ")"); + LOG_ERROR("Transaction inputs money (" << print_money_brief(summary_inputs_money) << ") is less than outputs money (" << print_money_brief(summary_outs_money) << ")"); return false; } } diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index bb7cd199..898d4921 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -5742,6 +5742,9 @@ void wallet2::print_source_entry(std::stringstream& output, const currency::tx_s << ", real_output: " << src.real_output << ", real_output_in_tx_index: " << src.real_output_in_tx_index << ", indexes: " << ss.str(); + + if (src.asset_id != currency::null_hash) + output << ", asset_id: " << print16(src.asset_id); } //---------------------------------------------------------------------------------------------------- bool wallet2::get_tx_key(const crypto::hash &txid, crypto::secret_key &tx_key) const @@ -5769,15 +5772,25 @@ void wallet2::prepare_tx_destinations(const assets_selection_context& needed_mon prepare_tx_destinations(el.second.needed_amount, el.second.found_amount, destination_split_strategy_id, dust_policy, dsts, final_destinations, el.first); } - if (is_in_hardfork_zone(ZANO_HARDFORK_04_ZARCANUM) && final_destinations.size() < CURRENCY_TX_MIN_ALLOWED_OUTS) + if (is_in_hardfork_zone(ZANO_HARDFORK_04_ZARCANUM)) { + // special case for asset minting destinations + for (auto& dst : dsts) + if (dst.asset_id == currency::ffff_hash) + final_destinations.emplace_back(dst.amount, dst.addr, dst.asset_id); + // if there's not ehough destinations items (i.e. outputs), split the last one - tx_destination_entry de = final_destinations.back(); - final_destinations.pop_back(); - size_t items_to_be_added = CURRENCY_TX_MIN_ALLOWED_OUTS - final_destinations.size(); - decompose_amount_randomly(de.amount, [&](uint64_t amount){ de.amount = amount; final_destinations.push_back(de); }, items_to_be_added); - WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(final_destinations.size() == CURRENCY_TX_MIN_ALLOWED_OUTS, - "can't get necessary number of outputs using decompose_amount_randomly(), got " << final_destinations.size() << " while mininum is " << CURRENCY_TX_MIN_ALLOWED_OUTS); + if (final_destinations.size() > 0 && final_destinations.size() < CURRENCY_TX_MIN_ALLOWED_OUTS) + { + tx_destination_entry de = final_destinations.back(); + final_destinations.pop_back(); + size_t items_to_be_added = CURRENCY_TX_MIN_ALLOWED_OUTS - final_destinations.size(); + // TODO: consider allowing to set them somewhere + size_t num_digits_to_keep = CURRENCY_TX_OUTS_RND_SPLIT_DIGITS_TO_KEEP; + decompose_amount_randomly(de.amount, [&](uint64_t amount){ de.amount = amount; final_destinations.push_back(de); }, items_to_be_added, num_digits_to_keep); + WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(final_destinations.size() == CURRENCY_TX_MIN_ALLOWED_OUTS, + "can't get necessary number of outputs using decompose_amount_randomly(), got " << final_destinations.size() << " while mininum is " << CURRENCY_TX_MIN_ALLOWED_OUTS); + } } } //---------------------------------------------------------------------------------------------------- @@ -5790,41 +5803,25 @@ void wallet2::prepare_tx_destinations(uint64_t needed_money, { WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(found_money >= needed_money, "needed_money==" << needed_money << " < found_money==" << found_money); - currency::tx_destination_entry change_dts = AUTO_VAL_INIT(change_dts); - if (needed_money < found_money) - { - change_dts.addr.push_back(m_account.get_keys().account_address); - change_dts.amount = found_money - needed_money; - change_dts.asset_id = asset_id; - } - if (is_in_hardfork_zone(ZANO_HARDFORK_04_ZARCANUM)) { - // TODO: consider allowing to set them somewhere - size_t min_number_of_outputs = CURRENCY_TX_MIN_ALLOWED_OUTS; - size_t num_digits_to_keep = CURRENCY_TX_OUTS_RND_SPLIT_DIGITS_TO_KEEP; for(auto& dst : dsts) { - decompose_amount_randomly(dst.amount, [&](uint64_t a){ final_destinations.emplace_back(a, dst.addr, dst.asset_id); }, min_number_of_outputs, num_digits_to_keep); - } - if (change_dts.amount > 0) - { - if (final_destinations.size() >= min_number_of_outputs - 1) - final_destinations.emplace_back(std::move(change_dts)); // don't split the change if there's enough outs - else - decompose_amount_randomly(change_dts.amount, [&](uint64_t a){ final_destinations.emplace_back(a, change_dts.addr, change_dts.asset_id); }, min_number_of_outputs, num_digits_to_keep); + if (dst.asset_id == asset_id) + final_destinations.emplace_back(dst.amount, dst.addr, dst.asset_id); } + if (found_money > needed_money) + final_destinations.emplace_back(found_money - needed_money, m_account.get_public_address(), asset_id); // returning back the change } else { // pre-HF4 - if (asset_id != currency::null_hash) + WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(asset_id != currency::null_hash, "assets are not allowed prior to HF4"); + currency::tx_destination_entry change_dts = AUTO_VAL_INIT(change_dts); + if (needed_money < found_money) { - if (change_dts.amount) - { - final_destinations.push_back(change_dts); - } - return; + change_dts.addr.push_back(m_account.get_keys().account_address); + change_dts.amount = found_money - needed_money; } uint64_t dust = 0; bool r = detail::apply_split_strategy_by_id(destination_split_strategy_id, dsts, change_dts, dust_policy.dust_threshold, final_destinations, dust, WALLET_MAX_ALLOWED_OUTPUT_AMOUNT); @@ -5833,7 +5830,7 @@ void wallet2::prepare_tx_destinations(uint64_t needed_money, if (0 != dust && !dust_policy.add_to_fee) { - final_destinations.emplace_back(dust, dust_policy.addr_for_dust, asset_id); + final_destinations.emplace_back(dust, dust_policy.addr_for_dust); } } } diff --git a/src/wallet/wallet_errors.h b/src/wallet/wallet_errors.h index e45eafb6..635f4617 100644 --- a/src/wallet/wallet_errors.h +++ b/src/wallet/wallet_errors.h @@ -438,8 +438,19 @@ namespace tools for (size_t i = 0; i < m_sources.size(); ++i) { const currency::tx_source_entry& src = m_sources[i]; - ss << "\n source " << i << ":"; - ss << "\n amount: " << currency::print_money(src.amount); + ss << "\n " << i << ": "; + ss << " amount: " << std::setw(21) << currency::print_money(src.amount); + ss << src.is_zarcanum() ? " ZC " : " old "; + ss << " asset_id: " << src.asset_id; + for (size_t j = 0; j < src.outputs.size(); ++j) + { + const currency::tx_source_entry::output_entry& out = src.outputs[j]; + if (out.out_reference.type() == typeid(uint64_t)) + ss << "\n ref #" << j << ": " << boost::get(out.out_reference); + else + ss << "\n ref #" << j << ": ref by id"; + } + // It's not good, if logs will contain such much data //ss << "\n real_output: " << src.real_output; //ss << "\n real_output_in_tx_index: " << src.real_output_in_tx_index; @@ -462,7 +473,7 @@ namespace tools { ss << currency::get_account_address_as_str(a) << ";"; } - ss << " anount: " << currency::print_money(dst.amount); + ss << " amount: " << std::setw(21) << currency::print_money(dst.amount); ss << " asset_id: " << dst.asset_id; }