aboutsummaryrefslogtreecommitdiff
path: root/src/wallet
diff options
context:
space:
mode:
Diffstat (limited to 'src/wallet')
-rw-r--r--src/wallet/wallet2.cpp65
-rw-r--r--src/wallet/wallet2.h9
2 files changed, 68 insertions, 6 deletions
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
index e81b946cb..dce1ee9de 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
@@ -1381,6 +1381,8 @@ void wallet2::pull_next_blocks(uint64_t start_height, uint64_t &blocks_start_hei
//----------------------------------------------------------------------------------------------------
void wallet2::update_pool_state()
{
+ MDEBUG("update_pool_state start");
+
// get the pool state
cryptonote::COMMAND_RPC_GET_TRANSACTION_POOL::request req;
cryptonote::COMMAND_RPC_GET_TRANSACTION_POOL::response res;
@@ -1390,6 +1392,7 @@ void wallet2::update_pool_state()
THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "get_transaction_pool");
THROW_WALLET_EXCEPTION_IF(res.status == CORE_RPC_STATUS_BUSY, error::daemon_busy, "get_transaction_pool");
THROW_WALLET_EXCEPTION_IF(res.status != CORE_RPC_STATUS_OK, error::get_tx_pool_error);
+ MDEBUG("update_pool_state got pool");
// remove any pending tx that's not in the pool
std::unordered_map<crypto::hash, wallet2::unconfirmed_transfer_details>::iterator it = m_unconfirmed_txs.begin();
@@ -1444,6 +1447,7 @@ void wallet2::update_pool_state()
}
}
}
+ MDEBUG("update_pool_state done first loop");
// remove pool txes to us that aren't in the pool anymore
std::unordered_map<crypto::hash, wallet2::payment_details>::iterator uit = m_unconfirmed_payments.begin();
@@ -1465,6 +1469,7 @@ void wallet2::update_pool_state()
m_unconfirmed_payments.erase(pit);
}
}
+ MDEBUG("update_pool_state done second loop");
// add new pool txes to us
for (auto it: res.transactions)
@@ -1473,6 +1478,11 @@ void wallet2::update_pool_state()
if(epee::string_tools::parse_hexstr_to_binbuff(it.id_hash, txid_data) && txid_data.size() == sizeof(crypto::hash))
{
const crypto::hash txid = *reinterpret_cast<const crypto::hash*>(txid_data.data());
+ if (m_scanned_pool_txs[0].find(txid) != m_scanned_pool_txs[0].end() || m_scanned_pool_txs[1].find(txid) != m_scanned_pool_txs[1].end())
+ {
+ LOG_PRINT_L2("Already seen " << txid << ", skipped");
+ continue;
+ }
if (m_unconfirmed_payments.find(txid) == m_unconfirmed_payments.end())
{
LOG_PRINT_L1("Found new pool tx: " << txid);
@@ -1491,9 +1501,11 @@ void wallet2::update_pool_state()
cryptonote::COMMAND_RPC_GET_TRANSACTIONS::request req;
cryptonote::COMMAND_RPC_GET_TRANSACTIONS::response res;
req.txs_hashes.push_back(it.id_hash);
+ MDEBUG("asking for " << it.id_hash);
req.decode_as_json = false;
m_daemon_rpc_mutex.lock();
bool r = epee::net_utils::invoke_http_json("/gettransactions", req, res, m_http_client, rpc_timeout);
+ MDEBUG("asked for " << it.id_hash << ", got " << r << " and " << res.status);
m_daemon_rpc_mutex.unlock();
if (r && res.status == CORE_RPC_STATUS_OK)
{
@@ -1512,6 +1524,12 @@ void wallet2::update_pool_state()
if (tx_hash == txid)
{
process_new_transaction(txid, tx, std::vector<uint64_t>(), 0, time(NULL), false, true);
+ m_scanned_pool_txs[0].insert(txid);
+ if (m_scanned_pool_txs[0].size() > 5000)
+ {
+ std::swap(m_scanned_pool_txs[0], m_scanned_pool_txs[1]);
+ m_scanned_pool_txs[0].clear();
+ }
}
else
{
@@ -1550,7 +1568,7 @@ void wallet2::update_pool_state()
}
else
{
- LOG_PRINT_L1("Already saw that one");
+ LOG_PRINT_L1("Already saw that one, it's for us");
}
}
else
@@ -1558,6 +1576,7 @@ void wallet2::update_pool_state()
LOG_PRINT_L0("Failed to parse txid");
}
}
+ MDEBUG("update_pool_state end");
}
//----------------------------------------------------------------------------------------------------
void wallet2::fast_refresh(uint64_t stop_height, uint64_t &blocks_start_height, std::list<crypto::hash> &short_chain_history)
@@ -4120,7 +4139,7 @@ std::vector<size_t> wallet2::pick_preferred_rct_inputs(uint64_t needed_money) co
return picks;
}
-static bool should_pick_a_second_output(bool use_rct, size_t n_transfers, const std::vector<size_t> &unused_transfers_indices, const std::vector<size_t> &unused_dust_indices)
+bool wallet2::should_pick_a_second_output(bool use_rct, size_t n_transfers, const std::vector<size_t> &unused_transfers_indices, const std::vector<size_t> &unused_dust_indices) const
{
if (!use_rct)
return false;
@@ -4128,9 +4147,43 @@ static bool should_pick_a_second_output(bool use_rct, size_t n_transfers, const
return false;
if (unused_dust_indices.empty() && unused_transfers_indices.empty())
return false;
+ // we want at least one free rct output to avoid a corner case where
+ // we'd choose a non rct output which doesn't have enough "siblings"
+ // value-wise on the chain, and thus can't be mixed
+ bool found = false;
+ for (auto i: unused_dust_indices)
+ {
+ if (m_transfers[i].is_rct())
+ {
+ found = true;
+ break;
+ }
+ }
+ if (!found) for (auto i: unused_transfers_indices)
+ {
+ if (m_transfers[i].is_rct())
+ {
+ found = true;
+ break;
+ }
+ }
+ if (!found)
+ return false;
return true;
}
+std::vector<size_t> wallet2::get_only_rct(const std::vector<size_t> &unused_dust_indices, const std::vector<size_t> &unused_transfers_indices) const
+{
+ std::vector<size_t> indices;
+ for (size_t n: unused_dust_indices)
+ if (m_transfers[n].is_rct())
+ indices.push_back(n);
+ for (size_t n: unused_transfers_indices)
+ if (m_transfers[n].is_rct())
+ indices.push_back(n);
+ return indices;
+}
+
// Another implementation of transaction creation that is hopefully better
// While there is anything left to pay, it goes through random outputs and tries
// to fill the next destination/amount. If it fully fills it, it will use the
@@ -4195,8 +4248,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
THROW_WALLET_EXCEPTION_IF(needed_money == 0, error::zero_destination);
// gather all our dust and non dust outputs
- const std::vector<size_t> unused_indices = select_available_outputs_from_histogram(fake_outs_count + 1, true, true, true, trusted_daemon);
- for (size_t i: unused_indices)
+ for (size_t i = 0; i < m_transfers.size(); ++i)
{
const transfer_details& td = m_transfers[i];
if (!td.m_spent && (use_rct ? true : !td.is_rct()) && is_transfer_unlocked(td))
@@ -4279,7 +4331,8 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
size_t idx;
if ((dsts.empty() || dsts[0].amount == 0) && !adding_fee) {
// the "make rct txes 2/2" case - we pick a small value output to "clean up" the wallet too
- idx = pop_best_value(unused_dust_indices.empty() ? unused_transfers_indices : unused_dust_indices, tx.selected_transfers, true);
+ std::vector<size_t> indices = get_only_rct(unused_dust_indices, unused_transfers_indices);
+ idx = pop_best_value(indices, tx.selected_transfers, true);
// since we're trying to add a second output which is not strictly needed,
// we only add it if it's unrelated enough to the first one
@@ -4289,6 +4342,8 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
LOG_PRINT_L2("Second outout was not strictly needed, and relatedness " << relatedness << ", not adding");
break;
}
+ pop_if_present(unused_transfers_indices, idx);
+ pop_if_present(unused_dust_indices, idx);
} else if (!prefered_inputs.empty()) {
idx = pop_back(prefered_inputs);
pop_if_present(unused_transfers_indices, idx);
diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h
index 5c8d0ae86..565cd9870 100644
--- a/src/wallet/wallet2.h
+++ b/src/wallet/wallet2.h
@@ -485,6 +485,10 @@ namespace tools
if(ver < 17)
return;
a & m_unconfirmed_payments;
+ if(ver < 18)
+ return;
+ a & m_scanned_pool_txs[0];
+ a & m_scanned_pool_txs[1];
}
/*!
@@ -633,6 +637,8 @@ namespace tools
void get_outs(std::vector<std::vector<get_outs_entry>> &outs, const std::list<size_t> &selected_transfers, size_t fake_outputs_count);
bool wallet_generate_key_image_helper(const cryptonote::account_keys& ack, const crypto::public_key& tx_public_key, size_t real_output_index, cryptonote::keypair& in_ephemeral, crypto::key_image& ki);
crypto::public_key get_tx_pub_key_from_received_outs(const tools::wallet2::transfer_details &td) const;
+ bool should_pick_a_second_output(bool use_rct, size_t n_transfers, const std::vector<size_t> &unused_transfers_indices, const std::vector<size_t> &unused_dust_indices) const;
+ std::vector<size_t> get_only_rct(const std::vector<size_t> &unused_dust_indices, const std::vector<size_t> &unused_transfers_indices) const;
cryptonote::account_base m_account;
boost::optional<epee::net_utils::http::login> m_daemon_login;
@@ -677,9 +683,10 @@ namespace tools
bool m_confirm_missing_payment_id;
bool m_ask_password;
NodeRPCProxy m_node_rpc_proxy;
+ std::unordered_set<crypto::hash> m_scanned_pool_txs[2];
};
}
-BOOST_CLASS_VERSION(tools::wallet2, 17)
+BOOST_CLASS_VERSION(tools::wallet2, 18)
BOOST_CLASS_VERSION(tools::wallet2::transfer_details, 7)
BOOST_CLASS_VERSION(tools::wallet2::payment_details, 1)
BOOST_CLASS_VERSION(tools::wallet2::unconfirmed_transfer_details, 6)