Add locked_transfer

This commit is contained in:
Oyvind Kvanes 2016-09-28 16:27:45 +02:00
parent d5f918a0b1
commit 7d020bde5e
1 changed files with 84 additions and 88 deletions

View File

@ -652,7 +652,7 @@ simple_wallet::simple_wallet()
m_cmd_binder.set_handler("bc_height", boost::bind(&simple_wallet::show_blockchain_height, this, _1), tr("Show blockchain height")); m_cmd_binder.set_handler("bc_height", boost::bind(&simple_wallet::show_blockchain_height, this, _1), tr("Show blockchain height"));
m_cmd_binder.set_handler("transfer_original", boost::bind(&simple_wallet::transfer, this, _1), tr("transfer [<mixin_count>] <addr_1> <amount_1> [<addr_2> <amount_2> ... <addr_N> <amount_N>] [payment_id] - Transfer <amount_1>,... <amount_N> to <address_1>,... <address_N>, respectively. <mixin_count> is the number of extra inputs to include for untraceability (from 0 to maximum available)")); m_cmd_binder.set_handler("transfer_original", boost::bind(&simple_wallet::transfer, this, _1), tr("transfer [<mixin_count>] <addr_1> <amount_1> [<addr_2> <amount_2> ... <addr_N> <amount_N>] [payment_id] - Transfer <amount_1>,... <amount_N> to <address_1>,... <address_N>, respectively. <mixin_count> is the number of extra inputs to include for untraceability (from 0 to maximum available)"));
m_cmd_binder.set_handler("transfer", boost::bind(&simple_wallet::transfer_new, this, _1), tr("Same as transfer_original, but using a new transaction building algorithm")); m_cmd_binder.set_handler("transfer", boost::bind(&simple_wallet::transfer_new, this, _1), tr("Same as transfer_original, but using a new transaction building algorithm"));
m_cmd_binder.set_handler("locked_transfer", boost::bind(&simple_wallet::locked_transfer, this, _1), tr("Make a transfer using unlock_time")); m_cmd_binder.set_handler("locked_transfer", boost::bind(&simple_wallet::locked_transfer, this, _1), tr("transfer [<mixin_count>] <addr> <amount> <locktime>(Number of blocks to lock the transaction for) [payment_id]"));
m_cmd_binder.set_handler("sweep_unmixable", boost::bind(&simple_wallet::sweep_unmixable, this, _1), tr("Send all unmixable outputs to yourself with mixin 0")); m_cmd_binder.set_handler("sweep_unmixable", boost::bind(&simple_wallet::sweep_unmixable, this, _1), tr("Send all unmixable outputs to yourself with mixin 0"));
m_cmd_binder.set_handler("sweep_all", boost::bind(&simple_wallet::sweep_all, this, _1), tr("Send all unlocked balance an address")); m_cmd_binder.set_handler("sweep_all", boost::bind(&simple_wallet::sweep_all, this, _1), tr("Send all unlocked balance an address"));
m_cmd_binder.set_handler("set_log", boost::bind(&simple_wallet::set_log, this, _1), tr("set_log <level> - Change current log detail level, <0-4>")); m_cmd_binder.set_handler("set_log", boost::bind(&simple_wallet::set_log, this, _1), tr("set_log <level> - Change current log detail level, <0-4>"));
@ -836,7 +836,7 @@ bool simple_wallet::ask_wallet_create_if_needed()
bool valid_path = false; bool valid_path = false;
do { do {
wallet_path = command_line::input_line( wallet_path = command_line::input_line(
tr("NOTE: This is my Wallet- Specify wallet file name (e.g., MyWallet). If the wallet doesn't exist, it will be created.\n" tr("Specify wallet file name (e.g., MyWallet). If the wallet doesn't exist, it will be created.\n"
"Wallet file name: ") "Wallet file name: ")
); );
if (std::cin.eof()) if (std::cin.eof())
@ -2582,7 +2582,7 @@ bool simple_wallet::locked_transfer(const std::vector<std::string> &args_)
} }
} }
if(local_args.size() < 2) if(local_args.size() < 3 )
{ {
fail_msg_writer() << tr("wrong number of arguments"); fail_msg_writer() << tr("wrong number of arguments");
return true; return true;
@ -2593,10 +2593,12 @@ bool simple_wallet::locked_transfer(const std::vector<std::string> &args_)
fail_msg_writer() << tr("this is a watch only wallet"); fail_msg_writer() << tr("this is a watch only wallet");
return true; return true;
} }
int given_unlock_time = 10; int given_unlock_time = 0;
std::vector<uint8_t> extra; std::vector<uint8_t> extra;
bool payment_id_seen = false; bool payment_id_seen = false;
if (1 == local_args.size() % 2) if (local_args.size() < 5)
{
if (local_args.size() == 4)
{ {
std::string payment_id_str = local_args.back(); std::string payment_id_str = local_args.back();
local_args.pop_back(); local_args.pop_back();
@ -2624,19 +2626,23 @@ bool simple_wallet::locked_transfer(const std::vector<std::string> &args_)
if(!r) if(!r)
{ {
fail_msg_writer() << tr("payment id has invalid format, expected 16 or 64 character hex string: ") << payment_id_str; fail_msg_writer() << tr("payment id has invalid format, expected 16 or 64 character hex string: ") << payment_id_str;
return true;
std::string err;
int bc_height = get_daemon_blockchain_height(err);
given_unlock_time = bc_height + std::stoi(payment_id_str);
//return true;
payment_id_seen = false;
} }
} }
//std::string unlock_time_string = local_args.back();
given_unlock_time = std::stoi( local_args.back() );
local_args.pop_back();
}
else
{
fail_msg_writer() << tr("wrong number of arguments");
return true;
}
vector<cryptonote::tx_destination_entry> dsts; vector<cryptonote::tx_destination_entry> dsts;
for (size_t i = 0; i < local_args.size(); i += 2) for (size_t i = 0; i < 1; i += 2)
{ {
cryptonote::tx_destination_entry de; cryptonote::tx_destination_entry de;
bool has_payment_id; bool has_payment_id;
@ -2677,12 +2683,12 @@ bool simple_wallet::locked_transfer(const std::vector<std::string> &args_)
{ {
// figure out what tx will be necessary // figure out what tx will be necessary
std::vector<tools::wallet2::pending_tx> ptx_vector; std::vector<tools::wallet2::pending_tx> ptx_vector;
ptx_vector = m_wallet->create_transactions_2(dsts, fake_outs_count, given_unlock_time /* unlock_time */, 0 /* unused fee arg*/, extra, m_trusted_daemon);
std::string err;
int bc_height = get_daemon_blockchain_height(err);
int unlock_time = given_unlock_time + bc_height;
ptx_vector = m_wallet->create_transactions_2(dsts, fake_outs_count, unlock_time , 0 /* unused fee arg*/, extra, m_trusted_daemon);
// if more than one tx necessary, prompt user to confirm
if (m_wallet->always_confirm_transfers() || ptx_vector.size() > 1)
{
uint64_t total_fee = 0; uint64_t total_fee = 0;
uint64_t dust_not_in_fee = 0; uint64_t dust_not_in_fee = 0;
uint64_t dust_in_fee = 0; uint64_t dust_in_fee = 0;
@ -2705,17 +2711,18 @@ bool simple_wallet::locked_transfer(const std::vector<std::string> &args_)
} }
else else
{ {
std::string err;
int bc_height = get_daemon_blockchain_height(err); prompt << boost::format(tr("Transaction fee is %s")) %
float days = (float)(given_unlock_time - bc_height) / 720.0;
prompt << boost::format(tr("The transaction fee is %s")) %
print_money(total_fee); print_money(total_fee);
prompt << boost::format(tr("The unlock time is approximately %s days")) %
days;
} }
if (dust_in_fee != 0) prompt << boost::format(tr(", of which %s is dust from change")) % print_money(dust_in_fee); if (dust_in_fee != 0) prompt << boost::format(tr(", of which %s is dust from change")) % print_money(dust_in_fee);
if (dust_not_in_fee != 0) prompt << tr(".") << ENDL << boost::format(tr("A total of %s from dust change will be sent to dust address")) if (dust_not_in_fee != 0) prompt << tr(".") << ENDL << boost::format(tr("A total of %s from dust change will be sent to dust address"))
% print_money(dust_not_in_fee); % print_money(dust_not_in_fee);
float days = (float)(given_unlock_time) / 720.0;
prompt << boost::format(tr(".\nThe unlock time is approximately %s days")) %
days;
prompt << tr(".") << ENDL << tr("Is this okay? (Y/Yes/N/No)"); prompt << tr(".") << ENDL << tr("Is this okay? (Y/Yes/N/No)");
std::string accepted = command_line::input_line(prompt.str()); std::string accepted = command_line::input_line(prompt.str());
@ -2724,12 +2731,8 @@ bool simple_wallet::locked_transfer(const std::vector<std::string> &args_)
if (accepted != "Y" && accepted != "y" && accepted != "Yes" && accepted != "yes") if (accepted != "Y" && accepted != "y" && accepted != "Yes" && accepted != "yes")
{ {
fail_msg_writer() << tr("transaction cancelled."); fail_msg_writer() << tr("transaction cancelled.");
// would like to return false, because no tx made, but everything else returns true
// and I don't know what returning false might adversely affect. *sigh*
return true; return true;
} }
}
// actually commit the transactions // actually commit the transactions
while (!ptx_vector.empty()) while (!ptx_vector.empty())
@ -2761,18 +2764,11 @@ bool simple_wallet::locked_transfer(const std::vector<std::string> &args_)
} }
catch (const tools::error::not_enough_money& e) catch (const tools::error::not_enough_money& e)
{ {
std::stringstream prompt;
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)") %
print_money(e.available()) % print_money(e.available()) %
print_money(e.tx_amount() + e.fee()) % print_money(e.tx_amount() + e.fee()) %
print_money(e.tx_amount()) % print_money(e.tx_amount()) %
print_money(e.fee())); print_money(e.fee()));
prompt << boost::format(tr("Available %s, transaction amount %s = %s + %s (fee)")) %
print_money(e.available()) %
print_money(e.tx_amount() + e.fee()) %
print_money(e.tx_amount()) %
print_money(e.fee());
std::string accepted = command_line::input_line(prompt.str());
fail_msg_writer() << tr("Failed to find a way to create transactions, too bad. This is usually due to dust which is so small it cannot pay for itself in fees"); fail_msg_writer() << tr("Failed to find a way to create transactions, too bad. This is usually due to dust which is so small it cannot pay for itself in fees");
} }
catch (const tools::error::not_enough_outs_to_mix& e) catch (const tools::error::not_enough_outs_to_mix& e)