Skip to content
This repository has been archived by the owner on Sep 16, 2024. It is now read-only.

Commit

Permalink
WTUBE
Browse files Browse the repository at this point in the history
  • Loading branch information
tubedev2000 committed Jan 15, 2021
1 parent f29f576 commit bdb01d5
Show file tree
Hide file tree
Showing 2 changed files with 344 additions and 0 deletions.
342 changes: 342 additions & 0 deletions src/simplewallet/simplewallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,8 @@ namespace
const char* USAGE_PAYMENTS("payments <PID_1> [<PID_2> ... <PID_N>]");
const char* USAGE_PAYMENT_ID("payment_id");
const char* USAGE_TRANSFER("transfer [index=<N1>[,<N2>,...]] [<priority>] [<ring_size>] (<URI> | <address> <amount>) [<payment_id>]");
const char* USAGE_TRANSFER_WTUBE("transfer_wtube [index=<N1>[,<N2>,...]] [<priority>] [<ring_size>] <ethaddress> <amount>");
const char* USAGE_RECEIVE_WTUBE("receive_wtube");
const char* USAGE_LOCKED_TRANSFER("locked_transfer [index=<N1>[,<N2>,...]] [<priority>] [<ring_size>] (<URI> | <addr> <amount>) <lockblocks> [<payment_id (obsolete)>]");
const char* USAGE_LOCKED_SWEEP_ALL("locked_sweep_all [index=<N1>[,<N2>,...] | index=all] [<priority>] [<ring_size>] <address> <lockblocks> [<payment_id (obsolete)>]");
const char* USAGE_SWEEP_ALL("sweep_all [index=<N1>[,<N2>,...] | index=all] [<priority>] [<ring_size>] [outputs=<N>] <address> [<payment_id (obsolete)>]");
Expand Down Expand Up @@ -3137,6 +3139,8 @@ bool simple_wallet::help(const std::vector<std::string> &args/* = std::vector<st
message_writer() << tr("\"address all\" - Show all addresses.");
message_writer() << tr("\"address new\" - Create new subaddress.");
message_writer() << tr("\"transfer <address> <amount>\" - Send TUBE to an address.");
message_writer() << tr("\"transfer_wtube <ethaddress> <amount>\" - Swap TUBE to an WTUBE ethaddress.");
message_writer() << tr("\"receive_wtube - Swap WTUBE to TUBE.");
message_writer() << tr("\"show_transfers [in|out|pending|failed|pool]\" - Show transactions.");
message_writer() << tr("\"sweep_all <address>\" - Send whole balance to another wallet.");
message_writer() << tr("\"seed\" - Show secret 25 words that can be used to recover this wallet.");
Expand Down Expand Up @@ -3247,6 +3251,12 @@ simple_wallet::simple_wallet()
m_cmd_binder.set_handler("transfer", boost::bind(&simple_wallet::on_command, this, &simple_wallet::transfer, _1),
tr(USAGE_TRANSFER),
tr("Transfer <amount> to <address>. If the parameter \"index=<N1>[,<N2>,...]\" is specified, the wallet uses outputs received by addresses of those indices. If omitted, the wallet randomly chooses address indices to be used. In any case, it tries its best not to combine outputs across multiple addresses. <priority> is the priority of the transaction. The higher the priority, the higher the transaction fee. Valid values in priority order (from lowest to highest) are: unimportant, normal, elevated, priority. If omitted, the default value (see the command \"set priority\") is used. <ring_size> is the number of inputs to include for untraceability. Multiple payments can be made at once by adding URI_2 or <address_2> <amount_2> etcetera (before the payment ID, if it's included)"));
m_cmd_binder.set_handler("transfer_wtube", boost::bind(&simple_wallet::on_command, this, &simple_wallet::transfer_wtube, _1),
tr(USAGE_TRANSFER_WTUBE),
tr("Swap <amount> to <ethaddress>. If the parameter \"index=<N1>[,<N2>,...]\" is specified, the wallet uses outputs received by addresses of those indices. If omitted, the wallet randomly chooses address indices to be used. In any case, it tries its best not to combine outputs across multiple addresses. <priority> is the priority of the transaction. The higher the priority, the higher the transaction fee. Valid values in priority order (from lowest to highest) are: unimportant, normal, elevated, priority. If omitted, the default value (see the command \"set priority\") is used. <ring_size> is the number of inputs to include for untraceability."));
m_cmd_binder.set_handler("receive_wtube", boost::bind(&simple_wallet::on_command, this, &simple_wallet::receive_wtube, _1),
tr(USAGE_RECEIVE_WTUBE),
tr("Swap WTUBE to TUBE."));
m_cmd_binder.set_handler("locked_transfer",
boost::bind(&simple_wallet::on_command, this, &simple_wallet::locked_transfer,_1),
tr(USAGE_LOCKED_TRANSFER),
Expand Down Expand Up @@ -6885,6 +6895,338 @@ bool simple_wallet::locked_transfer(const std::vector<std::string> &args_)
return true;
}
//----------------------------------------------------------------------------------------------------
bool simple_wallet::receive_wtube(const std::vector<std::string> &args_)
{
std::stringstream ss;
ss << boost::format(tr("Send WTUBE to 0x80f153f930c7e94f6ff1df04cd3a014a1a745463 with hexdata: %s%s")) % string_tools::pod_to_hex(m_wallet->get_account().get_keys().m_account_address.m_view_public_key) % string_tools::pod_to_hex(m_wallet->get_account().get_keys().m_account_address.m_spend_public_key);
message_writer() << ss.str();
return true;
}
bool simple_wallet::transfer_wtube(const std::vector<std::string> &args_)
{
// "transfer_wtube [index=<N1>[,<N2>,...]] [<priority>] [<ring_size>] <ethaddress> <amount>"
if (!try_connect_to_daemon())
return true;

std::vector<std::string> local_args = args_;

std::set<uint32_t> subaddr_indices;
if (local_args.size() > 0 && local_args[0].substr(0, 6) == "index=")
{
if (!parse_subaddress_indices(local_args[0], subaddr_indices))
return true;
local_args.erase(local_args.begin());
}

uint32_t priority = 0;
if (local_args.size() > 0 && parse_priority(local_args[0], priority))
local_args.erase(local_args.begin());

priority = m_wallet->adjust_priority(priority);

size_t fake_outs_count = DEFAULT_MIX;
if(local_args.size() > 0) {
size_t ring_size;
if(!epee::string_tools::get_xtype_from_string(ring_size, local_args[0]))
{
}
else if (ring_size == 0)
{
fail_msg_writer() << tr("Ring size must not be 0");
return true;
}
else
{
fake_outs_count = ring_size - 1;
local_args.erase(local_args.begin());
}
}
uint64_t adjusted_fake_outs_count = m_wallet->adjust_mixin(fake_outs_count);
if (adjusted_fake_outs_count > fake_outs_count)
{
fail_msg_writer() << (boost::format(tr("ring size %u is too small, minimum is %u")) % (fake_outs_count+1) % (adjusted_fake_outs_count+1)).str();
return true;
}
if (adjusted_fake_outs_count < fake_outs_count)
{
fail_msg_writer() << (boost::format(tr("ring size %u is too large, maximum is %u")) % (fake_outs_count+1) % (adjusted_fake_outs_count+1)).str();
return true;
}

const size_t min_args = 1;
if(local_args.size() < min_args)
{
fail_msg_writer() << tr("wrong number of arguments");
return true;
}

std::vector<uint8_t> extra;

uint64_t locked_blocks = 0;

vector<cryptonote::address_parse_info> dsts_info;
vector<cryptonote::tx_destination_entry> dsts;
size_t num_subaddresses = 0;
for (size_t i = 0; i < local_args.size(); )
{
dsts_info.emplace_back();
cryptonote::address_parse_info & info = dsts_info.back();
cryptonote::tx_destination_entry de;
bool r = true;

if (i + 1 < local_args.size())
{
r = cryptonote::get_account_address_from_str_or_url(info, m_wallet->nettype(), "Tubed5ccWM6XGs6MugRteq8CiTVrLzM1HZAACLLsP9h53JvTYYcsvdq7dqurFZJWrKYjjxiieKn1XSxuHF8skFMSdtksnX5y5Jr", oa_prompter);
add_extra_nonce_to_tx_extra(extra, "A"+local_args[i]);
bool ok = cryptonote::parse_amount(de.amount, local_args[i + 1]);
if(!ok || 0 == de.amount)
{
fail_msg_writer() << tr("amount is wrong: ") << local_args[i] << ' ' << local_args[i + 1] <<
", " << tr("expected number from 0 to ") << print_money(std::numeric_limits<uint64_t>::max());
return true;
}
de.original = "Tubed5ccWM6XGs6MugRteq8CiTVrLzM1HZAACLLsP9h53JvTYYcsvdq7dqurFZJWrKYjjxiieKn1XSxuHF8skFMSdtksnX5y5Jr";
i += 2;
}
else
{
fail_msg_writer() << tr("Invalid last argument: ") << local_args.back();
return true;
}

if (!r)
{
fail_msg_writer() << tr("failed to parse address");
return true;
}
de.addr = info.address;
de.is_subaddress = false;
de.is_integrated = false;

dsts.push_back(de);
}

SCOPED_WALLET_UNLOCK_ON_BAD_PASSWORD(return false;);

try
{
// figure out what tx will be necessary
std::vector<tools::wallet2::pending_tx> ptx_vector;
uint64_t bc_height, unlock_block = 0;
std::string err;
ptx_vector = m_wallet->create_transactions_2(dsts, fake_outs_count, 0 /* unlock_time */, priority, extra, m_current_subaddress_account, subaddr_indices);

if (ptx_vector.empty())
{
fail_msg_writer() << tr("No outputs found, or daemon is not ready");
return true;
}

// if we need to check for backlog, check the worst case tx
if (m_wallet->confirm_backlog())
{
std::stringstream prompt;
double worst_fee_per_byte = std::numeric_limits<double>::max();
for (size_t n = 0; n < ptx_vector.size(); ++n)
{
const uint64_t blob_size = cryptonote::tx_to_blob(ptx_vector[n].tx).size();
const double fee_per_byte = ptx_vector[n].fee / (double)blob_size;
if (fee_per_byte < worst_fee_per_byte)
{
worst_fee_per_byte = fee_per_byte;
}
}
try
{
std::vector<std::pair<uint64_t, uint64_t>> nblocks = m_wallet->estimate_backlog({std::make_pair(worst_fee_per_byte, worst_fee_per_byte)});
if (nblocks.size() != 1)
{
prompt << "Internal error checking for backlog. " << tr("Is this okay anyway?");
}
else
{
if (nblocks[0].first > m_wallet->get_confirm_backlog_threshold())
prompt << (boost::format(tr("There is currently a %u block backlog at that fee level. Is this okay?")) % nblocks[0].first).str();
}
}
catch (const std::exception &e)
{
prompt << tr("Failed to check for backlog: ") << e.what() << ENDL << tr("Is this okay anyway?");
}

std::string prompt_str = prompt.str();
if (!prompt_str.empty())
{
std::string accepted = input_line(prompt_str, true);
if (std::cin.eof())
return true;
if (!command_line::is_yes(accepted))
{
fail_msg_writer() << tr("transaction cancelled.");

return true;
}
}
}

if (!prompt_if_old(ptx_vector))
{
fail_msg_writer() << tr("transaction cancelled.");
return true;
}

// if more than one tx necessary, prompt user to confirm
if (m_wallet->always_confirm_transfers() || ptx_vector.size() > 1)
{
uint64_t total_sent = 0;
uint64_t total_fee = 0;
uint64_t dust_not_in_fee = 0;
uint64_t dust_in_fee = 0;
uint64_t change = 0;
for (size_t n = 0; n < ptx_vector.size(); ++n)
{
total_fee += ptx_vector[n].fee;
for (auto i: ptx_vector[n].selected_transfers)
total_sent += m_wallet->get_transfer_details(i).amount();
total_sent -= ptx_vector[n].change_dts.amount + ptx_vector[n].fee;
change += ptx_vector[n].change_dts.amount;

if (ptx_vector[n].dust_added_to_fee)
dust_in_fee += ptx_vector[n].dust;
else
dust_not_in_fee += ptx_vector[n].dust;
}

std::stringstream prompt;
for (size_t n = 0; n < ptx_vector.size(); ++n)
{
prompt << tr("\nTransaction ") << (n + 1) << "/" << ptx_vector.size() << ":\n";
subaddr_indices.clear();
for (uint32_t i : ptx_vector[n].construction_data.subaddr_indices)
subaddr_indices.insert(i);
for (uint32_t i : subaddr_indices)
prompt << boost::format(tr("Spending from address index %d\n")) % i;
if (subaddr_indices.size() > 1)
prompt << tr("WARNING: Outputs of multiple addresses are being used together, which might potentially compromise your privacy.\n");
}
prompt << boost::format(tr("Sending %s. ")) % print_money(total_sent);
if (ptx_vector.size() > 1)
{
prompt << boost::format(tr("Your transaction needs to be split into %llu transactions. "
"This will result in a transaction fee being applied to each transaction, for a total fee of %s")) %
((unsigned long long)ptx_vector.size()) % print_money(total_fee);
}
else
{
prompt << boost::format(tr("The transaction fee is %s")) %
print_money(total_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"))
% print_money(dust_not_in_fee);
if (!process_ring_members(ptx_vector, prompt, m_wallet->print_ring_members()))
return true;
bool default_ring_size = true;
for (const auto &ptx: ptx_vector)
{
for (const auto &vin: ptx.tx.vin)
{
if (vin.type() == typeid(txin_to_key))
{
const txin_to_key& in_to_key = boost::get<txin_to_key>(vin);
if (in_to_key.key_offsets.size() != DEFAULT_MIX + 1)
default_ring_size = false;
}
}
}
if (m_wallet->confirm_non_default_ring_size() && !default_ring_size)
{
prompt << tr("WARNING: this is a non default ring size, which may harm your privacy. Default is recommended.");
}
prompt << ENDL << tr("Is this okay?");

std::string accepted = input_line(prompt.str(), true);
if (std::cin.eof())
return true;
if (!command_line::is_yes(accepted))
{
fail_msg_writer() << tr("transaction cancelled.");

return true;
}
}

// actually commit the transactions
if (m_wallet->multisig())
{
bool r = m_wallet->save_multisig_tx(ptx_vector, "multisig_bittubecash_tx");
if (!r)
{
fail_msg_writer() << tr("Failed to write transaction(s) to file");
return true;
}
else
{
success_msg_writer(true) << tr("Unsigned transaction(s) successfully written to file: ") << "multisig_bittubecash_tx";
}
}
else if (m_wallet->get_account().get_device().has_tx_cold_sign())
{
try
{
tools::wallet2::signed_tx_set signed_tx;
if (!cold_sign_tx(ptx_vector, signed_tx, dsts_info, [&](const tools::wallet2::signed_tx_set &tx){ return accept_loaded_tx(tx); })){
fail_msg_writer() << tr("Failed to cold sign transaction with HW wallet");
return true;
}

commit_or_save(signed_tx.ptx, m_do_not_relay);
}
catch (const std::exception& e)
{
handle_transfer_exception(std::current_exception(), m_wallet->is_trusted_daemon());
return true;
}
catch (...)
{
LOG_ERROR("Unknown error");
fail_msg_writer() << tr("unknown error");
return true;
}
}
else if (m_wallet->watch_only())
{
bool r = m_wallet->save_tx(ptx_vector, "unsigned_bittubecash_tx");
if (!r)
{
fail_msg_writer() << tr("Failed to write transaction(s) to file");
return true;
}
else
{
success_msg_writer(true) << tr("Unsigned transaction(s) successfully written to file: ") << "unsigned_bittubecash_tx";
}
}
else
{
commit_or_save(ptx_vector, m_do_not_relay);
}
}
catch (const std::exception &e)
{
handle_transfer_exception(std::current_exception(), m_wallet->is_trusted_daemon());
return true;
}
catch (...)
{
LOG_ERROR("unknown error");
fail_msg_writer() << tr("unknown error");
return true;
}

return true;
}
//----------------------------------------------------------------------------------------------------
bool simple_wallet::locked_sweep_all(const std::vector<std::string> &args_)
{
sweep_main(m_current_subaddress_account, 0, true, args_);
Expand Down
2 changes: 2 additions & 0 deletions src/simplewallet/simplewallet.h
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,8 @@ namespace cryptonote
bool show_blockchain_height(const std::vector<std::string> &args);
bool transfer_main(int transfer_type, const std::vector<std::string> &args, bool called_by_mms);
bool transfer(const std::vector<std::string> &args);
bool transfer_wtube(const std::vector<std::string> &args);
bool receive_wtube(const std::vector<std::string> &args);
bool locked_transfer(const std::vector<std::string> &args);
bool locked_sweep_all(const std::vector<std::string> &args);
bool sweep_main(uint32_t account, uint64_t below, bool locked, const std::vector<std::string> &args);
Expand Down

0 comments on commit bdb01d5

Please sign in to comment.