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();
}
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") %
print_money(e.available()) %
print_money(e.tx_amount()));
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)
{
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();
}
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") %
print_money(e.available()) %
print_money(e.tx_amount()));
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)
{
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();
}
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") %
print_money(e.available()) %
print_money(e.tx_amount()));
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)
{
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();
}
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") %
print_money(e.available()) %
print_money(e.tx_amount()));
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)
{
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_status = Status_Error;
} catch (const tools::error::not_enough_money& e) {
} catch (const tools::error::not_enough_unlocked_money& e) {
m_status = Status_Error;
std::ostringstream writer;
@ -1156,6 +1156,15 @@ PendingTransaction *WalletImpl::createTransaction(const string &dst_addr, const
print_money(e.tx_amount());
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) {
m_status = Status_Error;
std::ostringstream writer;
@ -1241,7 +1250,7 @@ PendingTransaction *WalletImpl::createSweepUnmixableTransaction()
m_errorString = tr("failed to get random outputs to mix");
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;
std::ostringstream writer;
@ -1250,6 +1259,15 @@ PendingTransaction *WalletImpl::createSweepUnmixableTransaction()
print_money(e.tx_amount());
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) {
m_status = Status_Error;
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));
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;
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));
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;
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
{
std::random_device rd;

View file

@ -1249,10 +1249,10 @@ namespace tools
}
// 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;
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;
for (auto i = ++selected_transfers.begin(); i != selected_transfers.end(); ++i)

View file

@ -68,6 +68,7 @@ namespace tools
// get_tx_pool_error
// transfer_error *
// get_random_outs_general_error
// not_enough_unlocked_money
// not_enough_money
// tx_not_possible
// 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;
//----------------------------------------------------------------------------------------------------
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
{
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")
, m_available(availbable)
, m_available(available)
, m_tx_amount(tx_amount)
{
}
@ -384,9 +411,9 @@ namespace tools
//----------------------------------------------------------------------------------------------------
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")
, m_available(availbable)
, m_available(available)
, m_tx_amount(tx_amount)
, m_fee(fee)
{