aboutsummaryrefslogtreecommitdiff
path: root/src/simplewallet
diff options
context:
space:
mode:
Diffstat (limited to 'src/simplewallet')
-rw-r--r--src/simplewallet/simplewallet.cpp196
-rw-r--r--src/simplewallet/simplewallet.h1
2 files changed, 32 insertions, 165 deletions
diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp
index e747ee5e1..8ceb583be 100644
--- a/src/simplewallet/simplewallet.cpp
+++ b/src/simplewallet/simplewallet.cpp
@@ -786,169 +786,6 @@ bool simple_wallet::show_blockchain_height(const std::vector<std::string>& args)
return true;
}
-// split_amounts(vector<cryptonote::tx_destination_entry> dsts, size_t num_splits)
-//
-// split amount for each dst in dsts into num_splits parts
-// and make num_splits new vector<crypt...> instances to hold these new amounts
-std::vector<std::vector<cryptonote::tx_destination_entry>> simple_wallet::split_amounts(
- std::vector<cryptonote::tx_destination_entry> dsts, size_t num_splits)
-{
- std::vector<std::vector<cryptonote::tx_destination_entry>> retVal;
-
- if (num_splits <= 1)
- {
- retVal.push_back(dsts);
- return retVal;
- }
-
- // for each split required
- for (size_t i=0; i < num_splits; i++)
- {
- std::vector<cryptonote::tx_destination_entry> new_dsts;
-
- // for each destination
- for (size_t j=0; j < dsts.size(); j++)
- {
- cryptonote::tx_destination_entry de;
- uint64_t amount;
-
- amount = dsts[j].amount;
- amount = amount / num_splits;
-
- // if last split, add remainder
- if (i + 1 == num_splits)
- {
- amount += dsts[j].amount % num_splits;
- }
-
- de.addr = dsts[j].addr;
- de.amount = amount;
-
- new_dsts.push_back(de);
- }
-
- retVal.push_back(new_dsts);
- }
-
- return retVal;
-}
-
-//----------------------------------------------------------------------------------------------------
-// separated the call(s) to wallet2::transfer into their own function
-//
-// this function will make multiple calls to wallet2::transfer if multiple
-// transactions will be required
-void simple_wallet::create_transactions(std::vector<cryptonote::tx_destination_entry> dsts, const size_t fake_outs_count, const uint64_t unlock_time, const uint64_t fee, const std::vector<uint8_t> extra)
-{
- // for now, limit to 30 attempts. TODO: discuss a good number to limit to.
- const size_t MAX_ATTEMPTS = 30;
-
- // failsafe split attempt counter
- size_t attempt_count = 0;
-
- for(attempt_count = 1; ;attempt_count++)
- {
- auto split_values = split_amounts(dsts, attempt_count);
-
- // Throw if split_amounts comes back with a vector of size different than it should
- if (split_values.size() != attempt_count)
- {
- throw std::runtime_error("Splitting transactions returned a number of potential tx not equal to what was requested");
- }
-
- std::vector<tools::wallet2::pending_tx> ptx_vector;
- try
- {
- // for each new destination vector (i.e. for each new tx)
- for (auto & dst_vector : split_values)
- {
- cryptonote::transaction tx;
- tools::wallet2::pending_tx ptx;
- m_wallet->transfer(dst_vector, fake_outs_count, unlock_time, fee, extra, tx, ptx);
- ptx_vector.push_back(ptx);
-
- // mark transfers to be used as "spent"
- BOOST_FOREACH(tools::wallet2::transfer_container::iterator it, ptx.selected_transfers)
- it->m_spent = true;
- }
-
- // if we made it this far, we've selected our transactions. committing them will mark them spent,
- // so this is a failsafe in case they don't go through
- // unmark pending tx transfers as spent
- for (auto & ptx : ptx_vector)
- {
- // mark transfers to be used as not spent
- BOOST_FOREACH(tools::wallet2::transfer_container::iterator it2, ptx.selected_transfers)
- it2->m_spent = false;
-
- }
-
- // prompt user to confirm splits (if needed)
- if (attempt_count > 1)
- {
- std::string prompt_str = "Your transaction needs to be split into ";
- prompt_str += std::to_string(attempt_count);
- prompt_str += " transactions. This will result in a fee of ";
- prompt_str += print_money(attempt_count * DEFAULT_FEE);
- prompt_str += ". Is this okay? (Y/Yes/N/No)";
- std::string accepted = command_line::input_line(prompt_str);
- if (accepted != "Y" && accepted != "y" && accepted != "Yes" && accepted != "yes")
- {
- fail_msg_writer() << "Transaction cancelled.";
- return;
- }
- }
-
- // if we made it this far, we're OK to actually send the transactions
- while (!ptx_vector.empty())
- {
- auto & ptx = ptx_vector.back();
- m_wallet->commit_tx(ptx);
- success_msg_writer(true) << "Money successfully sent, transaction " << get_transaction_hash(ptx.tx);
- // if no exception, remove element from vector
- ptx_vector.pop_back();
- }
-
- return;
-
- }
- // only catch this here, other exceptions need to pass through to the calling function
- catch (const tools::error::tx_too_big& e)
- {
-
- // unmark pending tx transfers as spent
- for (auto & ptx : ptx_vector)
- {
- // mark transfers to be used as not spent
- BOOST_FOREACH(tools::wallet2::transfer_container::iterator it2, ptx.selected_transfers)
- it2->m_spent = false;
-
- }
-
- if (attempt_count >= MAX_ATTEMPTS)
- {
- throw;
- }
- }
- catch (...)
- {
- // in case of some other exception, make sure any tx in queue are marked unspent again
-
- // unmark pending tx transfers as spent
- for (auto & ptx : ptx_vector)
- {
- // mark transfers to be used as not spent
- BOOST_FOREACH(tools::wallet2::transfer_container::iterator it2, ptx.selected_transfers)
- it2->m_spent = false;
-
- }
-
- throw;
- }
- }
- //success_msg_writer(true) << "Money successfully sent, transaction " << get_transaction_hash(tx);
-}
-
//----------------------------------------------------------------------------------------------------
bool simple_wallet::transfer(const std::vector<std::string> &args_)
{
@@ -1015,7 +852,38 @@ bool simple_wallet::transfer(const std::vector<std::string> &args_)
try
{
- create_transactions(dsts, fake_outs_count, 0 /* unlock_time */, DEFAULT_FEE, extra);
+ // figure out what tx will be necessary
+ auto ptx_vector = m_wallet->create_transactions(dsts, fake_outs_count, 0 /* unlock_time */, DEFAULT_FEE, extra);
+
+ // if more than one tx necessary, prompt user to confirm
+ if (ptx_vector.size() > 1)
+ {
+ std::string prompt_str = "Your transaction needs to be split into ";
+ prompt_str += std::to_string(ptx_vector.size());
+ prompt_str += " transactions. This will result in a fee of ";
+ prompt_str += print_money(ptx_vector.size() * DEFAULT_FEE);
+ prompt_str += ". Is this okay? (Y/Yes/N/No)";
+ std::string accepted = command_line::input_line(prompt_str);
+ if (accepted != "Y" && accepted != "y" && accepted != "Yes" && accepted != "yes")
+ {
+ fail_msg_writer() << "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;
+ }
+ }
+
+ // actually commit the transactions
+ while (!ptx_vector.empty())
+ {
+ auto & ptx = ptx_vector.back();
+ m_wallet->commit_tx(ptx);
+ success_msg_writer(true) << "Money successfully sent, transaction " << get_transaction_hash(ptx.tx);
+
+ // if no exception, remove element from vector
+ ptx_vector.pop_back();
+ }
}
catch (const tools::error::daemon_busy&)
{
diff --git a/src/simplewallet/simplewallet.h b/src/simplewallet/simplewallet.h
index 8a6ac389a..e919cfeda 100644
--- a/src/simplewallet/simplewallet.h
+++ b/src/simplewallet/simplewallet.h
@@ -57,7 +57,6 @@ namespace cryptonote
std::vector<std::vector<cryptonote::tx_destination_entry>> split_amounts(
std::vector<cryptonote::tx_destination_entry> dsts, size_t num_splits
);
- void create_transactions(std::vector<cryptonote::tx_destination_entry> dsts, const size_t fake_outs_count, const uint64_t unlock_time, const uint64_t fee, const std::vector<uint8_t> extra);
bool print_address(const std::vector<std::string> &args = std::vector<std::string>());
bool save(const std::vector<std::string> &args);
bool set_log(const std::vector<std::string> &args);