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.cpp80
1 files changed, 61 insertions, 19 deletions
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
index 4ad8ea2c1..dc4f4879b 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
@@ -33,6 +33,7 @@
#include <boost/format.hpp>
#include <boost/optional/optional.hpp>
#include <boost/utility/value_init.hpp>
+#include <boost/algorithm/string/join.hpp>
#include "include_base_utils.h"
using namespace epee;
@@ -430,6 +431,20 @@ static void throw_on_rpc_response_error(const boost::optional<std::string> &stat
THROW_WALLET_EXCEPTION_IF(*status != CORE_RPC_STATUS_OK, tools::error::wallet_generic_rpc_error, method, *status);
}
+std::string strjoin(const std::vector<size_t> &V, const char *sep)
+{
+ std::stringstream ss;
+ bool first = true;
+ for (const auto &v: V)
+ {
+ if (!first)
+ ss << sep;
+ ss << std::to_string(v);
+ first = false;
+ }
+ return ss.str();
+}
+
} //namespace
namespace tools
@@ -643,16 +658,10 @@ static uint64_t decodeRct(const rct::rctSig & rv, const crypto::public_key &pub,
}
}
//----------------------------------------------------------------------------------------------------
-bool wallet2::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)
-{
- if (!cryptonote::generate_key_image_helper(ack, tx_public_key, real_output_index, in_ephemeral, ki))
- return false;
- return true;
-}
-//----------------------------------------------------------------------------------------------------
void wallet2::scan_output(const cryptonote::account_keys &keys, const cryptonote::transaction &tx, const crypto::public_key &tx_pub_key, size_t i, tx_scan_info_t &tx_scan_info, int &num_vouts_received, uint64_t &tx_money_got_in_outs, std::vector<size_t> &outs)
{
- wallet_generate_key_image_helper(keys, tx_pub_key, i, tx_scan_info.in_ephemeral, tx_scan_info.ki);
+ bool r = cryptonote::generate_key_image_helper(keys, tx_pub_key, i, tx_scan_info.in_ephemeral, tx_scan_info.ki);
+ THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "Failed to generate key image");
THROW_WALLET_EXCEPTION_IF(tx_scan_info.in_ephemeral.pub != boost::get<cryptonote::txout_to_key>(tx.vout[i].target).key,
error::wallet_internal_error, "key_image generated ephemeral public key not matched with output_key");
@@ -1100,7 +1109,10 @@ void wallet2::get_short_chain_history(std::list<crypto::hash>& ids) const
size_t current_multiplier = 1;
size_t sz = m_blockchain.size() - m_blockchain.offset();
if(!sz)
+ {
+ ids.push_back(m_blockchain.genesis());
return;
+ }
size_t current_back_offset = 1;
bool base_included = false;
while(current_back_offset < sz)
@@ -1205,6 +1217,7 @@ void wallet2::process_blocks(uint64_t start_height, const std::list<cryptonote::
size_t tx_o_indices_idx = 0;
THROW_WALLET_EXCEPTION_IF(blocks.size() != o_indices.size(), error::wallet_internal_error, "size mismatch");
+ THROW_WALLET_EXCEPTION_IF(!m_blockchain.is_in_bounds(current_index), error::wallet_internal_error, "Index out of bounds of hashchain");
tools::threadpool& tpool = tools::threadpool::getInstance();
int threads = tpool.get_max_concurrency();
@@ -1920,6 +1933,9 @@ bool wallet2::store_keys(const std::string& keys_file_name, const std::string& p
value2.SetInt(m_confirm_backlog ? 1 :0);
json.AddMember("confirm_backlog", value2, json.GetAllocator());
+ value2.SetUint(m_confirm_backlog_threshold);
+ json.AddMember("confirm_backlog_threshold", value2, json.GetAllocator());
+
value2.SetInt(m_testnet ? 1 :0);
json.AddMember("testnet", value2, json.GetAllocator());
@@ -1995,6 +2011,7 @@ bool wallet2::load_keys(const std::string& keys_file_name, const std::string& pa
m_min_output_value = 0;
m_merge_destinations = false;
m_confirm_backlog = true;
+ m_confirm_backlog_threshold = 0;
}
else
{
@@ -2067,6 +2084,8 @@ bool wallet2::load_keys(const std::string& keys_file_name, const std::string& pa
m_merge_destinations = field_merge_destinations;
GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, confirm_backlog, int, Int, false, true);
m_confirm_backlog = field_confirm_backlog;
+ GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, confirm_backlog_threshold, uint32_t, Uint, false, 0);
+ m_confirm_backlog_threshold = field_confirm_backlog_threshold;
GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, testnet, int, Int, false, m_testnet);
// Wallet is being opened with testnet flag, but is saved as a mainnet wallet
THROW_WALLET_EXCEPTION_IF(m_testnet && !field_testnet, error::wallet_internal_error, "Mainnet wallet can not be opened as testnet wallet");
@@ -2547,7 +2566,30 @@ void wallet2::load(const std::string& wallet_, const std::string& password)
void wallet2::trim_hashchain()
{
uint64_t height = m_checkpoints.get_max_height();
- if (height > 0)
+ if (!m_blockchain.empty() && m_blockchain.size() == m_blockchain.offset())
+ {
+ MINFO("Fixing empty hashchain");
+ epee::json_rpc::request<cryptonote::COMMAND_RPC_GET_BLOCK_HEADER_BY_HEIGHT::request> req = AUTO_VAL_INIT(req);
+ epee::json_rpc::response<cryptonote::COMMAND_RPC_GET_BLOCK_HEADER_BY_HEIGHT::response, std::string> res = AUTO_VAL_INIT(res);
+ m_daemon_rpc_mutex.lock();
+ req.jsonrpc = "2.0";
+ req.id = epee::serialization::storage_entry(0);
+ req.method = "getblockheaderbyheight";
+ req.params.height = m_blockchain.size() - 1;
+ bool r = net_utils::invoke_http_json("/json_rpc", req, res, m_http_client, rpc_timeout);
+ m_daemon_rpc_mutex.unlock();
+ if (r && res.result.status == CORE_RPC_STATUS_OK)
+ {
+ crypto::hash hash;
+ epee::string_tools::hex_to_pod(res.result.block_header.hash, hash);
+ m_blockchain.refill(hash);
+ }
+ else
+ {
+ MERROR("Failed to request block header from daemon, hash chain may be unable to sync till the wallet is loaded with a usable daemon");
+ }
+ }
+ if (height > 0 && m_blockchain.size() > height)
{
--height;
MDEBUG("trimming to " << height << ", offset " << m_blockchain.offset());
@@ -3292,7 +3334,7 @@ bool wallet2::sign_tx(unsigned_tx_set &exported_txs, const std::string &signed_f
signed_tx_set signed_txes;
for (size_t n = 0; n < exported_txs.txes.size(); ++n)
{
- const tools::wallet2::tx_construction_data &sd = exported_txs.txes[n];
+ tools::wallet2::tx_construction_data &sd = exported_txs.txes[n];
LOG_PRINT_L1(" " << (n+1) << ": " << sd.sources.size() << " inputs, ring size " << sd.sources[0].outputs.size());
signed_txes.ptx.push_back(pending_tx());
tools::wallet2::pending_tx &ptx = signed_txes.ptx.back();
@@ -4331,7 +4373,8 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
}
else
{
- THROW_WALLET_EXCEPTION_IF(original_output_index > dsts.size(), error::wallet_internal_error, "original_output_index too large");
+ THROW_WALLET_EXCEPTION_IF(original_output_index > dsts.size(), error::wallet_internal_error,
+ std::string("original_output_index too large: ") + std::to_string(original_output_index) + " > " + std::to_string(dsts.size()));
if (original_output_index == dsts.size())
dsts.push_back(tx_destination_entry(0,addr));
THROW_WALLET_EXCEPTION_IF(memcmp(&dsts[original_output_index].addr, &addr, sizeof(addr)), error::wallet_internal_error, "Mismatched destination address");
@@ -4430,12 +4473,8 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
TX &tx = txes.back();
LOG_PRINT_L2("Start of loop with " << unused_transfers_indices.size() << " " << unused_dust_indices.size());
- LOG_PRINT_L2("unused_transfers_indices:");
- for (auto t: unused_transfers_indices)
- LOG_PRINT_L2(" " << t);
- LOG_PRINT_L2("unused_dust_indices:");
- for (auto t: unused_dust_indices)
- LOG_PRINT_L2(" " << t);
+ LOG_PRINT_L2("unused_transfers_indices: " << strjoin(unused_transfers_indices, " "));
+ LOG_PRINT_L2("unused_dust_indices:" << strjoin(unused_dust_indices, " "));
LOG_PRINT_L2("dsts size " << dsts.size() << ", first " << (dsts.empty() ? -1 : dsts[0].amount));
LOG_PRINT_L2("adding_fee " << adding_fee << ", use_rct " << use_rct);
@@ -4609,6 +4648,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
{
LOG_PRINT_L2("We have more to pay, starting another tx");
txes.push_back(TX());
+ original_output_index = 0;
}
}
}
@@ -5222,7 +5262,8 @@ std::vector<std::pair<crypto::key_image, crypto::signature>> wallet2::export_key
// generate ephemeral secret key
crypto::key_image ki;
cryptonote::keypair in_ephemeral;
- cryptonote::generate_key_image_helper(m_account.get_keys(), tx_pub_key, td.m_internal_output_index, in_ephemeral, ki);
+ bool r = cryptonote::generate_key_image_helper(m_account.get_keys(), tx_pub_key, td.m_internal_output_index, in_ephemeral, ki);
+ THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "Failed to generate key image");
THROW_WALLET_EXCEPTION_IF(td.m_key_image_known && ki != td.m_key_image,
error::wallet_internal_error, "key_image generated not matched with cached key image");
@@ -5618,7 +5659,8 @@ size_t wallet2::import_outputs(const std::vector<tools::wallet2::transfer_detail
"Transaction extra has unsupported format at index " + boost::lexical_cast<std::string>(i));
crypto::public_key tx_pub_key = get_tx_pub_key_from_received_outs(td);
- cryptonote::generate_key_image_helper(m_account.get_keys(), tx_pub_key, td.m_internal_output_index, in_ephemeral, td.m_key_image);
+ bool r = cryptonote::generate_key_image_helper(m_account.get_keys(), tx_pub_key, td.m_internal_output_index, in_ephemeral, td.m_key_image);
+ THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "Failed to generate key image");
td.m_key_image_known = true;
THROW_WALLET_EXCEPTION_IF(in_ephemeral.pub != boost::get<cryptonote::txout_to_key>(td.m_tx.vout[td.m_internal_output_index].target).key,
error::wallet_internal_error, "key_image generated ephemeral public key not matched with output_key at index " + boost::lexical_cast<std::string>(i));