aboutsummaryrefslogtreecommitdiff
path: root/src/wallet/wallet2.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/wallet/wallet2.cpp')
-rw-r--r--src/wallet/wallet2.cpp71
1 files changed, 65 insertions, 6 deletions
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
index 75178845a..299b4afeb 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
@@ -66,6 +66,7 @@ using namespace epee;
#include "memwipe.h"
#include "common/base58.h"
#include "common/dns_utils.h"
+#include "common/notify.h"
#include "ringct/rctSigs.h"
#include "ringdb.h"
@@ -162,6 +163,7 @@ struct options {
};
const command_line::arg_descriptor<uint64_t> kdf_rounds = {"kdf-rounds", tools::wallet2::tr("Number of rounds for the key derivation function"), 1};
const command_line::arg_descriptor<std::string> hw_device = {"hw-device", tools::wallet2::tr("HW device to use"), ""};
+ const command_line::arg_descriptor<std::string> tx_notify = { "tx-notify" , "Run a program for each new incoming transaction, '%s' will be replaced by the transaction hash" , "" };
};
void do_prepare_file_names(const std::string& file_path, std::string& keys_file, std::string& wallet_file)
@@ -268,6 +270,17 @@ std::unique_ptr<tools::wallet2> make_basic(const boost::program_options::variabl
boost::filesystem::path ringdb_path = command_line::get_arg(vm, opts.shared_ringdb_dir);
wallet->set_ring_database(ringdb_path.string());
wallet->device_name(device_name);
+
+ try
+ {
+ if (!command_line::is_arg_defaulted(vm, opts.tx_notify))
+ wallet->set_tx_notify(std::shared_ptr<tools::Notify>(new tools::Notify(command_line::get_arg(vm, opts.tx_notify).c_str())));
+ }
+ catch (const std::exception &e)
+ {
+ MERROR("Failed to parse tx notify spec");
+ }
+
return wallet;
}
@@ -838,6 +851,7 @@ void wallet2::init_options(boost::program_options::options_description& desc_par
command_line::add_arg(desc_params, opts.shared_ringdb_dir);
command_line::add_arg(desc_params, opts.kdf_rounds);
command_line::add_arg(desc_params, opts.hw_device);
+ command_line::add_arg(desc_params, opts.tx_notify);
}
std::unique_ptr<wallet2> wallet2::make_from_json(const boost::program_options::variables_map& vm, bool unattended, const std::string& json_file, const std::function<boost::optional<tools::password_container>(const char *, bool)> &password_prompter)
@@ -1328,6 +1342,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
std::vector<size_t> outs;
std::unordered_map<cryptonote::subaddress_index, uint64_t> tx_money_got_in_outs; // per receiving subaddress index
crypto::public_key tx_pub_key = null_pkey;
+ bool notify = false;
std::vector<tx_extra_field> local_tx_extra_fields;
if (tx_cache_data.tx_extra_fields.empty())
@@ -1567,6 +1582,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
m_callback->on_money_received(height, txid, tx, td.m_amount, td.m_subaddr_index);
}
total_received_1 += amount;
+ notify = true;
}
else if (m_transfers[kit->second].m_spent || m_transfers[kit->second].amount() >= tx_scan_info[o].amount)
{
@@ -1634,6 +1650,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
m_callback->on_money_received(height, txid, tx, td.m_amount, td.m_subaddr_index);
}
total_received_1 += extra_amount;
+ notify = true;
}
}
}
@@ -1707,10 +1724,14 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
}
// remove change sent to the spending subaddress account from the list of received funds
+ uint64_t sub_change = 0;
for (auto i = tx_money_got_in_outs.begin(); i != tx_money_got_in_outs.end();)
{
if (subaddr_account && i->first.major == *subaddr_account)
+ {
+ sub_change += i->second;
i = tx_money_got_in_outs.erase(i);
+ }
else
++i;
}
@@ -1755,7 +1776,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
}
}
- uint64_t total_received_2 = 0;
+ uint64_t total_received_2 = sub_change;
for (const auto& i : tx_money_got_in_outs)
total_received_2 += i.second;
if (total_received_1 != total_received_2)
@@ -1790,6 +1811,13 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
LOG_PRINT_L2("Payment found in " << (pool ? "pool" : "block") << ": " << payment_id << " / " << payment.m_tx_hash << " / " << payment.m_amount);
}
}
+
+ if (notify)
+ {
+ std::shared_ptr<tools::Notify> tx_notify = m_tx_notify;
+ if (tx_notify)
+ tx_notify->notify(epee::string_tools::pod_to_hex(txid).c_str());
+ }
}
//----------------------------------------------------------------------------------------------------
void wallet2::process_unconfirmed(const crypto::hash &txid, const cryptonote::transaction& tx, uint64_t height)
@@ -3282,9 +3310,16 @@ bool wallet2::load_keys(const std::string& keys_file_name, const epee::wipeable_
encrypted_secret_keys = field_encrypted_secret_keys;
GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, device_name, std::string, String, false, std::string());
- if (m_device_name.empty() && field_device_name_found)
+ if (m_device_name.empty())
{
- m_device_name = field_device_name;
+ if (field_device_name_found)
+ {
+ m_device_name = field_device_name;
+ }
+ else
+ {
+ m_device_name = m_key_device_type == hw::device::device_type::LEDGER ? "Ledger" : "default";
+ }
}
}
else
@@ -6723,11 +6758,23 @@ void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>>
}
// while we still need more mixins
+ uint64_t num_usable_outs = num_outs;
+ bool allow_blackballed = false;
while (num_found < requested_outputs_count)
{
// if we've gone through every possible output, we've gotten all we can
- if (seen_indices.size() == num_outs)
- break;
+ if (seen_indices.size() == num_usable_outs)
+ {
+ // there is a first pass which rejects blackballed outputs, then a second pass
+ // which allows them if we don't have enough non blackballed outputs to reach
+ // the required amount of outputs (since consensus does not care about blackballed
+ // outputs, we still need to reach the minimum ring size)
+ if (allow_blackballed)
+ break;
+ MINFO("Not enough non blackballed outputs, we'll allow blackballed ones");
+ allow_blackballed = true;
+ num_usable_outs = num_outs;
+ }
// get a random output index from the DB. If we've already seen it,
// return to the top of the loop and try again, otherwise add it to the
@@ -6801,14 +6848,26 @@ void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>>
if (seen_indices.count(i))
continue;
- if (is_output_blackballed(std::make_pair(amount, i))) // don't add blackballed outputs
+ if (!allow_blackballed && is_output_blackballed(std::make_pair(amount, i))) // don't add blackballed outputs
+ {
+ --num_usable_outs;
continue;
+ }
seen_indices.emplace(i);
LOG_PRINT_L2("picking " << i << " as " << type);
req.outputs.push_back({amount, i});
++num_found;
}
+
+ // if we had enough unusable outputs, we might fall off here and still
+ // have too few outputs, so we stuff with one to keep counts good, and
+ // we'll error out later
+ while (num_found < requested_outputs_count)
+ {
+ req.outputs.push_back({amount, 0});
+ ++num_found;
+ }
}
// sort the subsection, to ensure the daemon doesn't know which output is ours