Distinguish "not enough money" and "not enough unlocked money"

Fix #1530
This commit is contained in:
binaryFate 2017-10-16 15:13:23 +02:00
parent 8d511f3c24
commit b2d416f211
5 changed files with 96 additions and 14 deletions

View File

@ -2821,13 +2821,20 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vector<std::stri
{ {
fail_msg_writer() << tr("failed to get random outputs to mix: ") << e.what(); fail_msg_writer() << tr("failed to get random outputs to mix: ") << e.what();
} }
catch (const tools::error::not_enough_money& e) catch (const tools::error::not_enough_unlocked_money& e)
{ {
LOG_PRINT_L0(boost::format("not enough money to transfer, available only %s, sent amount %s") % LOG_PRINT_L0(boost::format("not enough money to transfer, available only %s, sent amount %s") %
print_money(e.available()) % print_money(e.available()) %
print_money(e.tx_amount())); print_money(e.tx_amount()));
fail_msg_writer() << tr("Not enough money in unlocked balance"); fail_msg_writer() << tr("Not enough money in unlocked balance");
} }
catch (const tools::error::not_enough_money& e)
{
LOG_PRINT_L0(boost::format("not enough money to transfer, overall balance only %s, sent amount %s") %
print_money(e.available()) %
print_money(e.tx_amount()));
fail_msg_writer() << tr("Not enough money in overall balance");
}
catch (const tools::error::tx_not_possible& e) catch (const tools::error::tx_not_possible& e)
{ {
LOG_PRINT_L0(boost::format("not enough money to transfer, available only %s, transaction amount %s = %s + %s (fee)") % LOG_PRINT_L0(boost::format("not enough money to transfer, available only %s, transaction amount %s = %s + %s (fee)") %
@ -2993,13 +3000,20 @@ bool simple_wallet::sweep_unmixable(const std::vector<std::string> &args_)
{ {
fail_msg_writer() << tr("failed to get random outputs to mix: ") << e.what(); fail_msg_writer() << tr("failed to get random outputs to mix: ") << e.what();
} }
catch (const tools::error::not_enough_money& e) catch (const tools::error::not_enough_unlocked_money& e)
{ {
LOG_PRINT_L0(boost::format("not enough money to transfer, available only %s, sent amount %s") % LOG_PRINT_L0(boost::format("not enough money to transfer, available only %s, sent amount %s") %
print_money(e.available()) % print_money(e.available()) %
print_money(e.tx_amount())); print_money(e.tx_amount()));
fail_msg_writer() << tr("Not enough money in unlocked balance"); fail_msg_writer() << tr("Not enough money in unlocked balance");
} }
catch (const tools::error::not_enough_money& e)
{
LOG_PRINT_L0(boost::format("not enough money to transfer, overall balance only %s, sent amount %s") %
print_money(e.available()) %
print_money(e.tx_amount()));
fail_msg_writer() << tr("Not enough money in overall balance");
}
catch (const tools::error::tx_not_possible& e) catch (const tools::error::tx_not_possible& e)
{ {
LOG_PRINT_L0(boost::format("not enough money to transfer, available only %s, transaction amount %s = %s + %s (fee)") % LOG_PRINT_L0(boost::format("not enough money to transfer, available only %s, transaction amount %s = %s + %s (fee)") %
@ -3273,13 +3287,20 @@ bool simple_wallet::sweep_main(uint64_t below, const std::vector<std::string> &a
{ {
fail_msg_writer() << tr("failed to get random outputs to mix: ") << e.what(); fail_msg_writer() << tr("failed to get random outputs to mix: ") << e.what();
} }
catch (const tools::error::not_enough_money& e) catch (const tools::error::not_enough_unlocked_money& e)
{ {
LOG_PRINT_L0(boost::format("not enough money to transfer, available only %s, sent amount %s") % LOG_PRINT_L0(boost::format("not enough money to transfer, available only %s, sent amount %s") %
print_money(e.available()) % print_money(e.available()) %
print_money(e.tx_amount())); print_money(e.tx_amount()));
fail_msg_writer() << tr("Not enough money in unlocked balance"); fail_msg_writer() << tr("Not enough money in unlocked balance");
} }
catch (const tools::error::not_enough_money& e)
{
LOG_PRINT_L0(boost::format("not enough money to transfer, overall balance only %s, sent amount %s") %
print_money(e.available()) %
print_money(e.tx_amount()));
fail_msg_writer() << tr("Not enough money in overall balance");
}
catch (const tools::error::tx_not_possible& e) catch (const tools::error::tx_not_possible& e)
{ {
LOG_PRINT_L0(boost::format("not enough money to transfer, available only %s, transaction amount %s = %s + %s (fee)") % LOG_PRINT_L0(boost::format("not enough money to transfer, available only %s, transaction amount %s = %s + %s (fee)") %
@ -3623,13 +3644,20 @@ bool simple_wallet::submit_transfer(const std::vector<std::string> &args_)
{ {
fail_msg_writer() << tr("failed to get random outputs to mix: ") << e.what(); fail_msg_writer() << tr("failed to get random outputs to mix: ") << e.what();
} }
catch (const tools::error::not_enough_money& e) catch (const tools::error::not_enough_unlocked_money& e)
{ {
LOG_PRINT_L0(boost::format("not enough money to transfer, available only %s, sent amount %s") % LOG_PRINT_L0(boost::format("not enough money to transfer, available only %s, sent amount %s") %
print_money(e.available()) % print_money(e.available()) %
print_money(e.tx_amount())); print_money(e.tx_amount()));
fail_msg_writer() << tr("Not enough money in unlocked balance"); fail_msg_writer() << tr("Not enough money in unlocked balance");
} }
catch (const tools::error::not_enough_money& e)
{
LOG_PRINT_L0(boost::format("not enough money to transfer, overall balance only %s, sent amount %s") %
print_money(e.available()) %
print_money(e.tx_amount()));
fail_msg_writer() << tr("Not enough money in overall balance");
}
catch (const tools::error::tx_not_possible& e) catch (const tools::error::tx_not_possible& e)
{ {
LOG_PRINT_L0(boost::format("not enough money to transfer, available only %s, transaction amount %s = %s + %s (fee)") % LOG_PRINT_L0(boost::format("not enough money to transfer, available only %s, transaction amount %s = %s + %s (fee)") %

View File

@ -1147,7 +1147,7 @@ PendingTransaction *WalletImpl::createTransaction(const string &dst_addr, const
m_errorString = (boost::format(tr("failed to get random outputs to mix: %s")) % e.what()).str(); m_errorString = (boost::format(tr("failed to get random outputs to mix: %s")) % e.what()).str();
m_status = Status_Error; m_status = Status_Error;
} catch (const tools::error::not_enough_money& e) { } catch (const tools::error::not_enough_unlocked_money& e) {
m_status = Status_Error; m_status = Status_Error;
std::ostringstream writer; std::ostringstream writer;
@ -1156,6 +1156,15 @@ PendingTransaction *WalletImpl::createTransaction(const string &dst_addr, const
print_money(e.tx_amount()); print_money(e.tx_amount());
m_errorString = writer.str(); m_errorString = writer.str();
} catch (const tools::error::not_enough_money& e) {
m_status = Status_Error;
std::ostringstream writer;
writer << boost::format(tr("not enough money to transfer, overall balance only %s, sent amount %s")) %
print_money(e.available()) %
print_money(e.tx_amount());
m_errorString = writer.str();
} catch (const tools::error::tx_not_possible& e) { } catch (const tools::error::tx_not_possible& e) {
m_status = Status_Error; m_status = Status_Error;
std::ostringstream writer; std::ostringstream writer;
@ -1241,7 +1250,7 @@ PendingTransaction *WalletImpl::createSweepUnmixableTransaction()
m_errorString = tr("failed to get random outputs to mix"); m_errorString = tr("failed to get random outputs to mix");
m_status = Status_Error; m_status = Status_Error;
} catch (const tools::error::not_enough_money& e) { } catch (const tools::error::not_enough_unlocked_money& e) {
m_status = Status_Error; m_status = Status_Error;
std::ostringstream writer; std::ostringstream writer;
@ -1250,6 +1259,15 @@ PendingTransaction *WalletImpl::createSweepUnmixableTransaction()
print_money(e.tx_amount()); print_money(e.tx_amount());
m_errorString = writer.str(); m_errorString = writer.str();
} catch (const tools::error::not_enough_money& e) {
m_status = Status_Error;
std::ostringstream writer;
writer << boost::format(tr("not enough money to transfer, overall balance only %s, sent amount %s")) %
print_money(e.available()) %
print_money(e.tx_amount());
m_errorString = writer.str();
} catch (const tools::error::tx_not_possible& e) { } catch (const tools::error::tx_not_possible& e) {
m_status = Status_Error; m_status = Status_Error;
std::ostringstream writer; std::ostringstream writer;

View File

@ -4441,7 +4441,7 @@ void wallet2::transfer_selected(const std::vector<cryptonote::tx_destination_ent
} }
LOG_PRINT_L2("wanted " << print_money(needed_money) << ", found " << print_money(found_money) << ", fee " << print_money(fee)); LOG_PRINT_L2("wanted " << print_money(needed_money) << ", found " << print_money(found_money) << ", fee " << print_money(fee));
THROW_WALLET_EXCEPTION_IF(found_money < needed_money, error::not_enough_money, found_money, needed_money - fee, fee); THROW_WALLET_EXCEPTION_IF(found_money < needed_money, error::not_enough_unlocked_money, found_money, needed_money - fee, fee);
uint32_t subaddr_account = m_transfers[*selected_transfers.begin()].m_subaddr_index.major; uint32_t subaddr_account = m_transfers[*selected_transfers.begin()].m_subaddr_index.major;
for (auto i = ++selected_transfers.begin(); i != selected_transfers.end(); ++i) for (auto i = ++selected_transfers.begin(); i != selected_transfers.end(); ++i)
@ -4598,7 +4598,7 @@ void wallet2::transfer_selected_rct(std::vector<cryptonote::tx_destination_entry
} }
LOG_PRINT_L2("wanted " << print_money(needed_money) << ", found " << print_money(found_money) << ", fee " << print_money(fee)); LOG_PRINT_L2("wanted " << print_money(needed_money) << ", found " << print_money(found_money) << ", fee " << print_money(fee));
THROW_WALLET_EXCEPTION_IF(found_money < needed_money, error::not_enough_money, found_money, needed_money - fee, fee); THROW_WALLET_EXCEPTION_IF(found_money < needed_money, error::not_enough_unlocked_money, found_money, needed_money - fee, fee);
uint32_t subaddr_account = m_transfers[*selected_transfers.begin()].m_subaddr_index.major; uint32_t subaddr_account = m_transfers[*selected_transfers.begin()].m_subaddr_index.major;
for (auto i = ++selected_transfers.begin(); i != selected_transfers.end(); ++i) for (auto i = ++selected_transfers.begin(); i != selected_transfers.end(); ++i)
@ -5475,6 +5475,15 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
} }
} }
// early out if we know we can't make it anyway
// we could also check for being within FEE_PER_KB, but if the fee calculation
// ever changes, this might be missed, so let this go through
// first check overall balance is enough, then unlocked one, so we throw distinct exceptions
THROW_WALLET_EXCEPTION_IF(needed_money > balance(), error::not_enough_money,
unlocked_balance(), needed_money, 0);
THROW_WALLET_EXCEPTION_IF(needed_money > unlocked_balance(), error::not_enough_unlocked_money,
unlocked_balance(), needed_money, 0);
// shuffle & sort output indices // shuffle & sort output indices
{ {
std::random_device rd; std::random_device rd;

View File

@ -1249,10 +1249,10 @@ namespace tools
} }
// randomly select inputs for transaction // randomly select inputs for transaction
// throw if requested send amount is greater than amount available to send // throw if requested send amount is greater than (unlocked) amount available to send
std::list<size_t> selected_transfers; std::list<size_t> selected_transfers;
uint64_t found_money = select_transfers(needed_money, unused_transfers_indices, selected_transfers, trusted_daemon); uint64_t found_money = select_transfers(needed_money, unused_transfers_indices, selected_transfers, trusted_daemon);
THROW_WALLET_EXCEPTION_IF(found_money < needed_money, error::not_enough_money, found_money, needed_money - fee, fee); THROW_WALLET_EXCEPTION_IF(found_money < needed_money, error::not_enough_unlocked_money, found_money, needed_money - fee, fee);
uint32_t subaddr_account = m_transfers[*selected_transfers.begin()].m_subaddr_index.major; uint32_t subaddr_account = m_transfers[*selected_transfers.begin()].m_subaddr_index.major;
for (auto i = ++selected_transfers.begin(); i != selected_transfers.end(); ++i) for (auto i = ++selected_transfers.begin(); i != selected_transfers.end(); ++i)

View File

@ -68,6 +68,7 @@ namespace tools
// get_tx_pool_error // get_tx_pool_error
// transfer_error * // transfer_error *
// get_random_outs_general_error // get_random_outs_general_error
// not_enough_unlocked_money
// not_enough_money // not_enough_money
// tx_not_possible // tx_not_possible
// not_enough_outs_to_mix // not_enough_outs_to_mix
@ -356,11 +357,37 @@ namespace tools
//---------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------
typedef failed_rpc_request<transfer_error, get_random_outs_error_message_index> get_random_outs_error; typedef failed_rpc_request<transfer_error, get_random_outs_error_message_index> get_random_outs_error;
//---------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------
struct not_enough_unlocked_money : public transfer_error
{
explicit not_enough_unlocked_money(std::string&& loc, uint64_t available, uint64_t tx_amount, uint64_t fee)
: transfer_error(std::move(loc), "not enough unlocked money")
, m_available(available)
, m_tx_amount(tx_amount)
{
}
uint64_t available() const { return m_available; }
uint64_t tx_amount() const { return m_tx_amount; }
std::string to_string() const
{
std::ostringstream ss;
ss << transfer_error::to_string() <<
", available = " << cryptonote::print_money(m_available) <<
", tx_amount = " << cryptonote::print_money(m_tx_amount);
return ss.str();
}
private:
uint64_t m_available;
uint64_t m_tx_amount;
};
//----------------------------------------------------------------------------------------------------
struct not_enough_money : public transfer_error struct not_enough_money : public transfer_error
{ {
explicit not_enough_money(std::string&& loc, uint64_t availbable, uint64_t tx_amount, uint64_t fee) explicit not_enough_money(std::string&& loc, uint64_t available, uint64_t tx_amount, uint64_t fee)
: transfer_error(std::move(loc), "not enough money") : transfer_error(std::move(loc), "not enough money")
, m_available(availbable) , m_available(available)
, m_tx_amount(tx_amount) , m_tx_amount(tx_amount)
{ {
} }
@ -384,9 +411,9 @@ namespace tools
//---------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------
struct tx_not_possible : public transfer_error struct tx_not_possible : public transfer_error
{ {
explicit tx_not_possible(std::string&& loc, uint64_t availbable, uint64_t tx_amount, uint64_t fee) explicit tx_not_possible(std::string&& loc, uint64_t available, uint64_t tx_amount, uint64_t fee)
: transfer_error(std::move(loc), "tx not possible") : transfer_error(std::move(loc), "tx not possible")
, m_available(availbable) , m_available(available)
, m_tx_amount(tx_amount) , m_tx_amount(tx_amount)
, m_fee(fee) , m_fee(fee)
{ {