Skip to content

Commit

Permalink
Merge pull request #93 from Tay8NWWFKpz9JT4NXU0w/wallet-overflow
Browse files Browse the repository at this point in the history
Wallet overflow
  • Loading branch information
kleinroy authored Nov 30, 2024
2 parents faf790f + 910b87c commit 6c21a6a
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 11 deletions.
4 changes: 2 additions & 2 deletions src/simplewallet/simplewallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10766,7 +10766,7 @@ void simple_wallet::print_accounts(const std::string& tag)
success_msg_writer() << tr("Tag's description: ") << account_tags.first.find(tag)->second;
}
success_msg_writer() << boost::format(" %15s %21s %21s %21s %21s") % tr("Account") % tr("Balance") % tr("Unlocked balance") % tr("Asset") % tr("Label");
std::map<std::string, std::pair<uint64_t, uint64_t>> total_balances;
std::map<std::string, std::pair<boost::multiprecision::uint128_t , boost::multiprecision::uint128_t >> total_balances;
for (const auto& asset: offshore::ASSET_TYPES) {
boost::multiprecision::uint128_t total_balance = 0, total_unlocked_balance = 0;
for (uint32_t account_index = 0; account_index < m_wallet->get_num_subaddress_accounts(); ++account_index)
Expand All @@ -10790,7 +10790,7 @@ void simple_wallet::print_accounts(const std::string& tag)
total_unlocked_balance += unlocked_balance;
}
if (total_balance > 0)
total_balances[asset] = std::pair<uint64_t, uint64_t>(total_balance, total_unlocked_balance);
total_balances[asset] = std::pair<boost::multiprecision::uint128_t, boost::multiprecision::uint128_t>(total_balance, total_unlocked_balance);
}
success_msg_writer() << tr("------------------------------------------------------------------------------------");
for (const auto& it: total_balances)
Expand Down
43 changes: 34 additions & 9 deletions src/wallet/wallet2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11210,6 +11210,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(
boost::multiprecision::uint128_t amount_so_far = 0;
std::vector<size_t> non_dust_transfer_indeces;
bool has_huge_transfer=false;
uint64_t huge_transfer_value=0;

for (size_t i = 0; i < specific_transfers.size(); ++i)
{
Expand All @@ -11226,8 +11227,9 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(
MDEBUG("Ignoring output " << i << " of amount " << print_money(td.amount()) << " which is outside prescribed range [" << print_money(m_ignore_outputs_below) << ", " << print_money(m_ignore_outputs_above) << "]");
continue;
}
if (td.amount()>=uint64_max/2){
if (!has_huge_transfer && td.amount()>=uint64_max/2){
has_huge_transfer=true;
huge_transfer_value=td.amount();
}
}
}
Expand All @@ -11236,6 +11238,8 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(



bool huge_transfer_applied = false;

for (size_t i = 0; i < specific_transfers.size(); ++i)
{
const transfer_details& td = *specific_transfers[i];
Expand All @@ -11252,16 +11256,35 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(
continue;
}

if (has_huge_transfer && td.amount()<uint64_max/2)
{
MDEBUG("Ignoring output " << i << " of amount " << print_money(td.amount()) << " which is less than " << uint64_max/2);
continue;

//Skip the output if it will overflow the wallet
if ((boost::multiprecision::uint128_t) td.amount() + amount_so_far > (boost::multiprecision::uint128_t) uint64_max){
MDEBUG("Ignoring output " << i << " of amount " << print_money(td.amount()) << " which will lead to overflow");
continue;
}
//If the output is not huge, we have a huge output, and we have not yet added the huge output, we should
//limit the maximum amount to uint64_max - amount_so_far - huge_transfer_value
if (has_huge_transfer && !huge_transfer_applied && (td.amount() < uint64_max/2) &&
((boost::multiprecision::uint128_t) td.amount() + amount_so_far + (boost::multiprecision::uint128_t) huge_transfer_value > (boost::multiprecision::uint128_t) uint64_max)) {
MDEBUG("Ignoring output " << i << " of amount " << print_money(td.amount()) << " which will lead to overflow when the huge transfer is added");
continue;
}

if (amount_so_far >= uint64_max/2)
{
MDEBUG("Ignoring output " << i << " of amount " << print_money(td.amount()) << ", we have already collected enough transfers");
continue;
//If the transfer is huge, and we have already applied a huge transfer, ignore the output
if (huge_transfer_applied && td.amount() >= uint64_max/2) {
MDEBUG("Ignoring output " << i << " of amount " << print_money(td.amount()) << " which will lead to overflow, being a second huge transfer");
continue;
}

//If the transfer is huge, it should match huge_transfer_value or else it should be ignored
if (td.amount() >= uint64_max/2 && td.amount() != huge_transfer_value) {
MDEBUG("Ignoring output " << i << " of amount " << print_money(td.amount()) << " which is huge, but not the expected one");
continue;
}

//If the transfer is huge and with the expected value, indicate we have applied it
if (td.amount() == huge_transfer_value) {
huge_transfer_applied = true;
}

amount_so_far+=td.amount();
Expand Down Expand Up @@ -11296,6 +11319,8 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(
}
}

THROW_WALLET_EXCEPTION_IF(amount_so_far > (boost::multiprecision::uint128_t) uint64_max, error::wallet_internal_error, "Sum of transfers exceeds 18 million");

// sort output indices
{
auto sort_predicate = [&unlocked_balance_per_subaddr] (const std::pair<uint32_t, std::vector<size_t>>& x, const std::pair<uint32_t, std::vector<size_t>>& y)
Expand Down

0 comments on commit 6c21a6a

Please sign in to comment.