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.cpp93
1 files changed, 70 insertions, 23 deletions
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
index 8f3f30da1..9782e4b1e 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
@@ -217,6 +217,8 @@ namespace
add_reason(reason, "invalid input");
if (res.invalid_output)
add_reason(reason, "invalid output");
+ if (res.too_few_outputs)
+ add_reason(reason, "too few outputs");
if (res.too_big)
add_reason(reason, "too big");
if (res.overspend)
@@ -1140,7 +1142,8 @@ wallet2::wallet2(network_type nettype, uint64_t kdf_rounds, bool unattended):
m_devices_registered(false),
m_device_last_key_image_sync(0),
m_use_dns(true),
- m_offline(false)
+ m_offline(false),
+ m_rpc_version(0)
{
}
@@ -5157,6 +5160,7 @@ bool wallet2::check_connection(uint32_t *version, bool *ssl, uint32_t timeout)
if (m_offline)
{
+ m_rpc_version = 0;
if (version)
*version = 0;
if (ssl)
@@ -5166,6 +5170,7 @@ bool wallet2::check_connection(uint32_t *version, bool *ssl, uint32_t timeout)
// TODO: Add light wallet version check.
if(m_light_wallet) {
+ m_rpc_version = 0;
if (version)
*version = 0;
if (ssl)
@@ -5177,6 +5182,7 @@ bool wallet2::check_connection(uint32_t *version, bool *ssl, uint32_t timeout)
boost::lock_guard<boost::recursive_mutex> lock(m_daemon_rpc_mutex);
if(!m_http_client.is_connected(ssl))
{
+ m_rpc_version = 0;
m_node_rpc_proxy.invalidate();
if (!m_http_client.connect(std::chrono::milliseconds(timeout)))
return false;
@@ -5185,20 +5191,21 @@ bool wallet2::check_connection(uint32_t *version, bool *ssl, uint32_t timeout)
}
}
- if (version)
+ if (!m_rpc_version)
{
cryptonote::COMMAND_RPC_GET_VERSION::request req_t = AUTO_VAL_INIT(req_t);
cryptonote::COMMAND_RPC_GET_VERSION::response resp_t = AUTO_VAL_INIT(resp_t);
bool r = invoke_http_json_rpc("/json_rpc", "get_version", req_t, resp_t);
if(!r) {
- *version = 0;
+ if(version)
+ *version = 0;
return false;
}
- if (resp_t.status != CORE_RPC_STATUS_OK)
- *version = 0;
- else
- *version = resp_t.version;
+ if (resp_t.status == CORE_RPC_STATUS_OK)
+ m_rpc_version = resp_t.version;
}
+ if (version)
+ *version = m_rpc_version;
return true;
}
@@ -6118,7 +6125,7 @@ void wallet2::commit_tx(pending_tx& ptx)
amount_in += m_transfers[idx].amount();
}
add_unconfirmed_tx(ptx.tx, amount_in, dests, payment_id, ptx.change_dts.amount, ptx.construction_data.subaddr_account, ptx.construction_data.subaddr_indices);
- if (store_tx_info())
+ if (store_tx_info() && ptx.tx_key != crypto::null_skey)
{
m_tx_keys.insert(std::make_pair(txid, ptx.tx_key));
m_additional_tx_keys.insert(std::make_pair(txid, ptx.additional_tx_keys));
@@ -6307,7 +6314,7 @@ bool wallet2::sign_tx(unsigned_tx_set &exported_txs, std::vector<wallet2::pendin
// normally, the tx keys are saved in commit_tx, when the tx is actually sent to the daemon.
// we can't do that here since the tx will be sent from the compromised wallet, which we don't want
// to see that info, so we save it here
- if (store_tx_info())
+ if (store_tx_info() && ptx.tx_key != crypto::null_skey)
{
const crypto::hash txid = get_transaction_hash(ptx.tx);
m_tx_keys.insert(std::make_pair(txid, tx_key));
@@ -6931,7 +6938,7 @@ uint64_t wallet2::get_base_fee() const
else
return m_light_wallet_per_kb_fee;
}
- bool use_dyn_fee = use_fork_rules(HF_VERSION_DYNAMIC_FEE, -720 * 1);
+ bool use_dyn_fee = use_fork_rules(HF_VERSION_DYNAMIC_FEE, -30 * 1);
if (!use_dyn_fee)
return FEE_PER_KB;
@@ -6962,7 +6969,7 @@ int wallet2::get_fee_algorithm() const
return 3;
if (use_fork_rules(5, 0))
return 2;
- if (use_fork_rules(3, -720 * 14))
+ if (use_fork_rules(3, -30 * 14))
return 1;
return 0;
}
@@ -7443,7 +7450,7 @@ void wallet2::light_wallet_get_outs(std::vector<std::vector<tools::wallet2::get_
order.resize(light_wallet_requested_outputs_count);
for (size_t n = 0; n < order.size(); ++n)
order[n] = n;
- std::shuffle(order.begin(), order.end(), std::default_random_engine(crypto::rand<unsigned>()));
+ std::shuffle(order.begin(), order.end(), crypto::random_device{});
LOG_PRINT_L2("Looking for " << (fake_outputs_count+1) << " outputs with amounts " << print_money(td.is_rct() ? 0 : td.amount()));
@@ -7726,7 +7733,6 @@ void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>>
uint64_t num_found = 0;
// if we have a known ring, use it
- bool existing_ring_found = false;
if (td.m_key_image_known && !td.m_key_image_partial)
{
std::vector<uint64_t> ring;
@@ -7738,7 +7744,6 @@ void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>>
std::to_string(ring.size()) + ", it cannot be spent now with ring size " +
std::to_string(fake_outputs_count + 1) + " as it is smaller: use a higher ring size");
bool own_found = false;
- existing_ring_found = true;
for (const auto &out: ring)
{
MINFO("Ring has output " << out);
@@ -7984,7 +7989,6 @@ void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>>
outs.back().push_back(std::make_tuple(td.m_global_output_index, boost::get<txout_to_key>(td.m_tx.vout[td.m_internal_output_index].target).key, mask));
// then pick outs from an existing ring, if any
- bool existing_ring_found = false;
if (td.m_key_image_known && !td.m_key_image_partial)
{
std::vector<uint64_t> ring;
@@ -8021,7 +8025,7 @@ void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>>
order.resize(requested_outputs_count);
for (size_t n = 0; n < order.size(); ++n)
order[n] = n;
- std::shuffle(order.begin(), order.end(), std::default_random_engine(crypto::rand<unsigned>()));
+ std::shuffle(order.begin(), order.end(), crypto::random_device{});
LOG_PRINT_L2("Looking for " << (fake_outputs_count+1) << " outputs of size " << print_money(td.is_rct() ? 0 : td.amount()));
for (size_t o = 0; o < requested_outputs_count && outs.back().size() < fake_outputs_count + 1; ++o)
@@ -8163,6 +8167,7 @@ void wallet2::transfer_selected(const std::vector<cryptonote::tx_destination_ent
if (needed_money < found_money)
{
change_dts.addr = get_subaddress({subaddr_account, 0});
+ change_dts.is_subaddress = subaddr_account != 0;
change_dts.amount = found_money - needed_money;
}
@@ -10051,6 +10056,7 @@ void wallet2::cold_sign_tx(const std::vector<pending_tx>& ptx_vector, signed_tx_
setup_shim(&wallet_shim, this);
aux_data.tx_recipients = dsts_info;
aux_data.bp_version = use_fork_rules(HF_VERSION_SMALLER_BP, -10) ? 2 : 1;
+ aux_data.hard_fork = get_current_hard_fork();
dev_cold->tx_sign(&wallet_shim, txs, exported_txs, aux_data);
tx_device_aux = aux_data.tx_device_aux;
@@ -10078,6 +10084,35 @@ uint64_t wallet2::cold_key_image_sync(uint64_t &spent, uint64_t &unspent) {
return import_res;
}
//----------------------------------------------------------------------------------------------------
+void wallet2::device_show_address(uint32_t account_index, uint32_t address_index, const boost::optional<crypto::hash8> &payment_id)
+{
+ if (!key_on_device())
+ {
+ return;
+ }
+
+ auto & hwdev = get_account().get_device();
+ hwdev.display_address(subaddress_index{account_index, address_index}, payment_id);
+}
+//----------------------------------------------------------------------------------------------------
+uint8_t wallet2::get_current_hard_fork()
+{
+ if (m_offline)
+ return 0;
+
+ cryptonote::COMMAND_RPC_HARD_FORK_INFO::request req_t = AUTO_VAL_INIT(req_t);
+ cryptonote::COMMAND_RPC_HARD_FORK_INFO::response resp_t = AUTO_VAL_INIT(resp_t);
+
+ m_daemon_rpc_mutex.lock();
+ req_t.version = 0;
+ bool r = net_utils::invoke_http_json_rpc("/json_rpc", "hard_fork_info", req_t, resp_t, m_http_client, rpc_timeout);
+ m_daemon_rpc_mutex.unlock();
+ THROW_WALLET_EXCEPTION_IF(!r, tools::error::no_connection_to_daemon, "hard_fork_info");
+ THROW_WALLET_EXCEPTION_IF(resp_t.status == CORE_RPC_STATUS_BUSY, tools::error::daemon_busy, "hard_fork_info");
+ THROW_WALLET_EXCEPTION_IF(resp_t.status != CORE_RPC_STATUS_OK, tools::error::wallet_generic_rpc_error, "hard_fork_info", m_trusted_daemon ? resp_t.status : "daemon error");
+ return resp_t.version;
+}
+//----------------------------------------------------------------------------------------------------
void wallet2::get_hard_fork_info(uint8_t version, uint64_t &earliest_height) const
{
boost::optional<std::string> result = m_node_rpc_proxy.get_earliest_height(version, earliest_height);
@@ -10276,6 +10311,8 @@ bool wallet2::get_tx_key_cached(const crypto::hash &txid, crypto::secret_key &tx
if (i == m_tx_keys.end())
return false;
tx_key = i->second;
+ if (tx_key == crypto::null_skey)
+ return false;
const auto j = m_additional_tx_keys.find(txid);
if (j != m_additional_tx_keys.end())
additional_tx_keys = j->second;
@@ -10287,6 +10324,7 @@ bool wallet2::get_tx_key(const crypto::hash &txid, crypto::secret_key &tx_key, s
bool r = get_tx_key_cached(txid, tx_key, additional_tx_keys);
if (r)
{
+ MDEBUG("tx key cached for txid: " << txid);
return true;
}
@@ -10348,13 +10386,18 @@ bool wallet2::get_tx_key(const crypto::hash &txid, crypto::secret_key &tx_key, s
dev_cold->get_tx_key(tx_keys, tx_key_data, m_account.get_keys().m_view_secret_key);
if (tx_keys.empty())
{
+ MDEBUG("Empty tx keys for txid: " << txid);
+ return false;
+ }
+
+ if (tx_keys[0] == crypto::null_skey)
+ {
return false;
}
tx_key = tx_keys[0];
tx_keys.erase(tx_keys.begin());
additional_tx_keys = tx_keys;
-
return true;
}
//----------------------------------------------------------------------------------------------------
@@ -11387,12 +11430,13 @@ void wallet2::set_attribute(const std::string &key, const std::string &value)
m_attributes[key] = value;
}
-std::string wallet2::get_attribute(const std::string &key) const
+bool wallet2::get_attribute(const std::string &key, std::string &value) const
{
std::unordered_map<std::string, std::string>::const_iterator i = m_attributes.find(key);
if (i == m_attributes.end())
- return std::string();
- return i->second;
+ return false;
+ value = i->second;
+ return true;
}
void wallet2::set_description(const std::string &description)
@@ -11402,7 +11446,10 @@ void wallet2::set_description(const std::string &description)
std::string wallet2::get_description() const
{
- return get_attribute(ATTRIBUTE_DESCRIPTION);
+ std::string s;
+ if (get_attribute(ATTRIBUTE_DESCRIPTION, s))
+ return s;
+ return "";
}
const std::pair<std::map<std::string, std::string>, std::vector<std::string>>& wallet2::get_account_tags()
@@ -11560,10 +11607,10 @@ crypto::public_key wallet2::get_tx_pub_key_from_received_outs(const tools::walle
return tx_pub_key;
}
-bool wallet2::export_key_images(const std::string &filename) const
+bool wallet2::export_key_images(const std::string &filename, bool all) const
{
PERF_TIMER(export_key_images);
- std::pair<size_t, std::vector<std::pair<crypto::key_image, crypto::signature>>> ski = export_key_images();
+ std::pair<size_t, std::vector<std::pair<crypto::key_image, crypto::signature>>> ski = export_key_images(all);
std::string magic(KEY_IMAGE_EXPORT_FILE_MAGIC, strlen(KEY_IMAGE_EXPORT_FILE_MAGIC));
const cryptonote::account_public_address &keys = get_account().get_keys().m_account_address;
const uint32_t offset = ski.first;