aboutsummaryrefslogtreecommitdiff
path: root/src/wallet
diff options
context:
space:
mode:
Diffstat (limited to 'src/wallet')
-rw-r--r--src/wallet/api/wallet.cpp142
-rw-r--r--src/wallet/api/wallet.h8
-rw-r--r--src/wallet/api/wallet_manager.cpp57
-rw-r--r--src/wallet/api/wallet_manager.h7
-rw-r--r--src/wallet/node_rpc_proxy.cpp28
-rw-r--r--src/wallet/node_rpc_proxy.h6
-rw-r--r--src/wallet/wallet2.cpp93
-rw-r--r--src/wallet/wallet2.h26
-rw-r--r--src/wallet/wallet2_api.h21
-rw-r--r--src/wallet/wallet_rpc_server.cpp2
10 files changed, 278 insertions, 112 deletions
diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp
index 52ecc2e6a..9e40d2e02 100644
--- a/src/wallet/api/wallet.cpp
+++ b/src/wallet/api/wallet.cpp
@@ -197,6 +197,44 @@ bool Wallet::addressValid(const std::string &str, bool testnet)
return get_account_integrated_address_from_str(address, has_payment_id, pid, testnet, str);
}
+bool Wallet::keyValid(const std::string &secret_key_string, const std::string &address_string, bool isViewKey, bool testnet, std::string &error)
+{
+ bool has_payment_id;
+ cryptonote::account_public_address address;
+ crypto::hash8 pid;
+ if(!get_account_integrated_address_from_str(address, has_payment_id, pid, testnet, address_string)) {
+ error = tr("Failed to parse address");
+ return false;
+ }
+
+ cryptonote::blobdata key_data;
+ if(!epee::string_tools::parse_hexstr_to_binbuff(secret_key_string, key_data) || key_data.size() != sizeof(crypto::secret_key))
+ {
+ error = tr("Failed to parse key");
+ return false;
+ }
+ crypto::secret_key key = *reinterpret_cast<const crypto::secret_key*>(key_data.data());
+
+ // check the key match the given address
+ crypto::public_key pkey;
+ if (!crypto::secret_key_to_public_key(key, pkey)) {
+ error = tr("failed to verify key");
+ return false;
+ }
+ bool matchAddress = false;
+ if(isViewKey)
+ matchAddress = address.m_view_public_key == pkey;
+ else
+ matchAddress = address.m_spend_public_key == pkey;
+
+ if(!matchAddress) {
+ error = tr("key does not match address");
+ return false;
+ }
+
+ return true;
+}
+
std::string Wallet::paymentIdFromAddress(const std::string &str, bool testnet)
{
bool has_payment_id;
@@ -337,6 +375,98 @@ bool WalletImpl::createWatchOnly(const std::string &path, const std::string &pas
return true;
}
+bool WalletImpl::recoverFromKeys(const std::string &path,
+ const std::string &language,
+ const std::string &address_string,
+ const std::string &viewkey_string,
+ const std::string &spendkey_string)
+{
+ cryptonote::account_public_address address;
+ bool has_payment_id;
+ crypto::hash8 new_payment_id;
+ if(!get_account_integrated_address_from_str(address, has_payment_id, new_payment_id, m_wallet->testnet(), address_string))
+ {
+ m_errorString = tr("failed to parse address");
+ m_status = Status_Error;
+ return false;
+ }
+
+ // parse optional spend key
+ crypto::secret_key spendkey;
+ bool has_spendkey = false;
+ if (!spendkey_string.empty()) {
+ cryptonote::blobdata spendkey_data;
+ if(!epee::string_tools::parse_hexstr_to_binbuff(spendkey_string, spendkey_data) || spendkey_data.size() != sizeof(crypto::secret_key))
+ {
+ m_errorString = tr("failed to parse secret spend key");
+ m_status = Status_Error;
+ return false;
+ }
+ has_spendkey = true;
+ spendkey = *reinterpret_cast<const crypto::secret_key*>(spendkey_data.data());
+ }
+
+ // parse view secret key
+ if (viewkey_string.empty()) {
+ m_errorString = tr("No view key supplied, cancelled");
+ m_status = Status_Error;
+ return false;
+ }
+ cryptonote::blobdata viewkey_data;
+ if(!epee::string_tools::parse_hexstr_to_binbuff(viewkey_string, viewkey_data) || viewkey_data.size() != sizeof(crypto::secret_key))
+ {
+ m_errorString = tr("failed to parse secret view key");
+ m_status = Status_Error;
+ return false;
+ }
+ crypto::secret_key viewkey = *reinterpret_cast<const crypto::secret_key*>(viewkey_data.data());
+
+ // check the spend and view keys match the given address
+ crypto::public_key pkey;
+ if(has_spendkey) {
+ if (!crypto::secret_key_to_public_key(spendkey, pkey)) {
+ m_errorString = tr("failed to verify secret spend key");
+ m_status = Status_Error;
+ return false;
+ }
+ if (address.m_spend_public_key != pkey) {
+ m_errorString = tr("spend key does not match address");
+ m_status = Status_Error;
+ return false;
+ }
+ }
+ if (!crypto::secret_key_to_public_key(viewkey, pkey)) {
+ m_errorString = tr("failed to verify secret view key");
+ m_status = Status_Error;
+ return false;
+ }
+ if (address.m_view_public_key != pkey) {
+ m_errorString = tr("view key does not match address");
+ m_status = Status_Error;
+ return false;
+ }
+
+ try
+ {
+ if (has_spendkey) {
+ m_wallet->generate(path, "", address, spendkey, viewkey);
+ LOG_PRINT_L1("Generated new wallet from keys");
+ }
+ else {
+ m_wallet->generate(path, "", address, viewkey);
+ LOG_PRINT_L1("Generated new view only wallet from keys");
+ }
+
+ }
+ catch (const std::exception& e) {
+ m_errorString = string(tr("failed to generate new wallet: ")) + e.what();
+ m_status = Status_Error;
+ return false;
+ }
+ return true;
+}
+
+
bool WalletImpl::open(const std::string &path, const std::string &password)
{
clearStatus();
@@ -516,12 +646,12 @@ string WalletImpl::keysFilename() const
bool WalletImpl::init(const std::string &daemon_address, uint64_t upper_transaction_size_limit)
{
clearStatus();
- doInit(daemon_address, upper_transaction_size_limit);
+ if (!doInit(daemon_address, upper_transaction_size_limit))
+ return false;
bool result = this->refresh();
// enabling background refresh thread
startRefresh();
return result;
-
}
void WalletImpl::initAsync(const string &daemon_address, uint64_t upper_transaction_size_limit)
@@ -1232,9 +1362,10 @@ bool WalletImpl::isNewWallet() const
return !(blockChainHeight() > 1 || m_recoveringFromSeed || m_rebuildWalletCache) && !watchOnly();
}
-void WalletImpl::doInit(const string &daemon_address, uint64_t upper_transaction_size_limit)
+bool WalletImpl::doInit(const string &daemon_address, uint64_t upper_transaction_size_limit)
{
- m_wallet->init(daemon_address, upper_transaction_size_limit);
+ if (!m_wallet->init(daemon_address, upper_transaction_size_limit))
+ return false;
// in case new wallet, this will force fast-refresh (pulling hashes instead of blocks)
// If daemon isn't synced a calculated block height will be used instead
@@ -1253,8 +1384,7 @@ void WalletImpl::doInit(const string &daemon_address, uint64_t upper_transaction
this->setTrustedDaemon(false);
m_refreshIntervalMillis = DEFAULT_REMOTE_NODE_REFRESH_INTERVAL_MILLIS;
}
-
-
+ return true;
}
bool WalletImpl::parse_uri(const std::string &uri, std::string &address, std::string &payment_id, uint64_t &amount, std::string &tx_description, std::string &recipient_name, std::vector<std::string> &unknown_parameters, std::string &error)
diff --git a/src/wallet/api/wallet.h b/src/wallet/api/wallet.h
index e3df7fd01..7daf63e43 100644
--- a/src/wallet/api/wallet.h
+++ b/src/wallet/api/wallet.h
@@ -58,6 +58,11 @@ public:
const std::string &language) const;
bool open(const std::string &path, const std::string &password);
bool recover(const std::string &path, const std::string &seed);
+ bool recoverFromKeys(const std::string &path,
+ const std::string &language,
+ const std::string &address_string,
+ const std::string &viewkey_string,
+ const std::string &spendkey_string = "");
bool close();
std::string seed() const;
std::string getSeedLanguage() const;
@@ -94,6 +99,7 @@ public:
void setRecoveringFromSeed(bool recoveringFromSeed);
bool watchOnly() const;
bool rescanSpent();
+ bool testnet() const {return m_wallet->testnet();}
PendingTransaction * createTransaction(const std::string &dst_addr, const std::string &payment_id,
@@ -127,7 +133,7 @@ private:
bool daemonSynced() const;
void stopRefresh();
bool isNewWallet() const;
- void doInit(const std::string &daemon_address, uint64_t upper_transaction_size_limit);
+ bool doInit(const std::string &daemon_address, uint64_t upper_transaction_size_limit);
private:
diff --git a/src/wallet/api/wallet_manager.cpp b/src/wallet/api/wallet_manager.cpp
index 904338a72..c761cc6d2 100644
--- a/src/wallet/api/wallet_manager.cpp
+++ b/src/wallet/api/wallet_manager.cpp
@@ -43,6 +43,15 @@ namespace epee {
unsigned int g_test_dbg_lock_sleep = 0;
}
+namespace {
+ template<typename Request, typename Response>
+ bool connect_and_invoke(const std::string& address, const std::string& path, const Request& request, Response& response)
+ {
+ epee::net_utils::http::http_simple_client client{};
+ return client.set_server(address) && epee::net_utils::invoke_http_json(path, request, response, client);
+ }
+}
+
namespace Monero {
Wallet *WalletManagerImpl::createWallet(const std::string &path, const std::string &password,
@@ -72,6 +81,22 @@ Wallet *WalletManagerImpl::recoveryWallet(const std::string &path, const std::st
return wallet;
}
+Wallet *WalletManagerImpl::createWalletFromKeys(const std::string &path,
+ const std::string &language,
+ bool testnet,
+ uint64_t restoreHeight,
+ const std::string &addressString,
+ const std::string &viewKeyString,
+ const std::string &spendKeyString)
+{
+ WalletImpl * wallet = new WalletImpl(testnet);
+ if(restoreHeight > 0){
+ wallet->setRefreshFromBlockHeight(restoreHeight);
+ }
+ wallet->recoverFromKeys(path, language, addressString, viewKeyString, spendKeyString);
+ return wallet;
+}
+
bool WalletManagerImpl::closeWallet(Wallet *wallet)
{
WalletImpl * wallet_ = dynamic_cast<WalletImpl*>(wallet);
@@ -145,9 +170,7 @@ bool WalletManagerImpl::connected(uint32_t *version) const
req_t.jsonrpc = "2.0";
req_t.id = epee::serialization::storage_entry(0);
req_t.method = "get_version";
- epee::net_utils::http::http_simple_client http_client;
- bool r = epee::net_utils::invoke_http_json_remote_command2(m_daemonAddress + "/json_rpc", req_t, resp_t, http_client);
- if (!r)
+ if (!connect_and_invoke(m_daemonAddress, "/json_rpc", req_t, resp_t))
return false;
if (version)
@@ -193,8 +216,7 @@ bool WalletManagerImpl::checkPayment(const std::string &address_text, const std:
cryptonote::COMMAND_RPC_GET_TRANSACTIONS::request req;
cryptonote::COMMAND_RPC_GET_TRANSACTIONS::response res;
req.txs_hashes.push_back(epee::string_tools::pod_to_hex(txid));
- epee::net_utils::http::http_simple_client http_client;
- if (!epee::net_utils::invoke_http_json_remote_command2(daemon_address + "/gettransactions", req, res, http_client) ||
+ if (!connect_and_invoke(m_daemonAddress, "/gettransactions", req, res) ||
(res.txs.size() != 1 && res.txs_as_hex.size() != 1))
{
error = tr("failed to get transaction from daemon");
@@ -312,8 +334,7 @@ uint64_t WalletManagerImpl::blockchainHeight() const
cryptonote::COMMAND_RPC_GET_INFO::request ireq;
cryptonote::COMMAND_RPC_GET_INFO::response ires;
- epee::net_utils::http::http_simple_client http_client;
- if (!epee::net_utils::invoke_http_json_remote_command2(m_daemonAddress + "/getinfo", ireq, ires, http_client))
+ if (!connect_and_invoke(m_daemonAddress, "/getinfo", ireq, ires))
return 0;
return ires.height;
}
@@ -323,8 +344,7 @@ uint64_t WalletManagerImpl::blockchainTargetHeight() const
cryptonote::COMMAND_RPC_GET_INFO::request ireq;
cryptonote::COMMAND_RPC_GET_INFO::response ires;
- epee::net_utils::http::http_simple_client http_client;
- if (!epee::net_utils::invoke_http_json_remote_command2(m_daemonAddress + "/getinfo", ireq, ires, http_client))
+ if (!connect_and_invoke(m_daemonAddress, "/getinfo", ireq, ires))
return 0;
return ires.target_height >= ires.height ? ires.target_height : ires.height;
}
@@ -334,8 +354,7 @@ uint64_t WalletManagerImpl::networkDifficulty() const
cryptonote::COMMAND_RPC_GET_INFO::request ireq;
cryptonote::COMMAND_RPC_GET_INFO::response ires;
- epee::net_utils::http::http_simple_client http_client;
- if (!epee::net_utils::invoke_http_json_remote_command2(m_daemonAddress + "/getinfo", ireq, ires, http_client))
+ if (!connect_and_invoke(m_daemonAddress, "/getinfo", ireq, ires))
return 0;
return ires.difficulty;
}
@@ -346,7 +365,7 @@ double WalletManagerImpl::miningHashRate() const
cryptonote::COMMAND_RPC_MINING_STATUS::response mres;
epee::net_utils::http::http_simple_client http_client;
- if (!epee::net_utils::invoke_http_json_remote_command2(m_daemonAddress + "/mining_status", mreq, mres, http_client))
+ if (!connect_and_invoke(m_daemonAddress, "/mining_status", mreq, mres))
return 0.0;
if (!mres.active)
return 0.0;
@@ -366,7 +385,7 @@ void WalletManagerImpl::hardForkInfo(uint8_t &version, uint64_t &earliest_height
req_t.id = epee::serialization::storage_entry(0);
req_t.method = "hard_fork_info";
req_t.params.version = 0;
- bool r = epee::net_utils::invoke_http_json_remote_command2(m_daemonAddress + "/json_rpc", req_t, resp_t, http_client);
+ bool r = connect_and_invoke(m_daemonAddress, "/json_rpc", req_t, resp_t);
if (!r || resp_t.result.status != CORE_RPC_STATUS_OK)
return;
version = resp_t.result.version;
@@ -378,8 +397,7 @@ uint64_t WalletManagerImpl::blockTarget() const
cryptonote::COMMAND_RPC_GET_INFO::request ireq;
cryptonote::COMMAND_RPC_GET_INFO::response ires;
- epee::net_utils::http::http_simple_client http_client;
- if (!epee::net_utils::invoke_http_json_remote_command2(m_daemonAddress + "/getinfo", ireq, ires, http_client))
+ if (!connect_and_invoke(m_daemonAddress, "/getinfo", ireq, ires))
return 0;
return ires.target;
}
@@ -389,8 +407,7 @@ bool WalletManagerImpl::isMining() const
cryptonote::COMMAND_RPC_MINING_STATUS::request mreq;
cryptonote::COMMAND_RPC_MINING_STATUS::response mres;
- epee::net_utils::http::http_simple_client http_client;
- if (!epee::net_utils::invoke_http_json_remote_command2(m_daemonAddress + "/mining_status", mreq, mres, http_client))
+ if (!connect_and_invoke(m_daemonAddress, "/mining_status", mreq, mres))
return false;
return mres.active;
}
@@ -403,8 +420,7 @@ bool WalletManagerImpl::startMining(const std::string &address, uint32_t threads
mreq.miner_address = address;
mreq.threads_count = threads;
- epee::net_utils::http::http_simple_client http_client;
- if (!epee::net_utils::invoke_http_json_remote_command2(m_daemonAddress + "/start_mining", mreq, mres, http_client))
+ if (!connect_and_invoke(m_daemonAddress, "/start_mining", mreq, mres))
return false;
return mres.status == CORE_RPC_STATUS_OK;
}
@@ -414,8 +430,7 @@ bool WalletManagerImpl::stopMining()
cryptonote::COMMAND_RPC_STOP_MINING::request mreq;
cryptonote::COMMAND_RPC_STOP_MINING::response mres;
- epee::net_utils::http::http_simple_client http_client;
- if (!epee::net_utils::invoke_http_json_remote_command2(m_daemonAddress + "/stop_mining", mreq, mres, http_client))
+ if (!connect_and_invoke(m_daemonAddress, "/stop_mining", mreq, mres))
return false;
return mres.status == CORE_RPC_STATUS_OK;
}
diff --git a/src/wallet/api/wallet_manager.h b/src/wallet/api/wallet_manager.h
index ca9570254..ce9b70e96 100644
--- a/src/wallet/api/wallet_manager.h
+++ b/src/wallet/api/wallet_manager.h
@@ -41,6 +41,13 @@ public:
const std::string &language, bool testnet);
Wallet * openWallet(const std::string &path, const std::string &password, bool testnet);
virtual Wallet * recoveryWallet(const std::string &path, const std::string &memo, bool testnet, uint64_t restoreHeight);
+ virtual Wallet * createWalletFromKeys(const std::string &path,
+ const std::string &language,
+ bool testnet,
+ uint64_t restoreHeight,
+ const std::string &addressString,
+ const std::string &viewKeyString,
+ const std::string &spendKeyString = "");
virtual bool closeWallet(Wallet *wallet);
bool walletExists(const std::string &path);
std::vector<std::string> findWallets(const std::string &path);
diff --git a/src/wallet/node_rpc_proxy.cpp b/src/wallet/node_rpc_proxy.cpp
index d7f755e36..cc249b5cc 100644
--- a/src/wallet/node_rpc_proxy.cpp
+++ b/src/wallet/node_rpc_proxy.cpp
@@ -36,18 +36,16 @@ using namespace epee;
namespace tools
{
-void NodeRPCProxy::init(const std::string &daemon_address)
-{
- m_daemon_address = daemon_address;
-
- m_height = 0;
- m_height_time = 0;
- for (auto &slot: m_earliest_height)
- slot = 0;
- m_dynamic_per_kb_fee_estimate = 0;
- m_dynamic_per_kb_fee_estimate_cached_height = 0;
- m_dynamic_per_kb_fee_estimate_grace_blocks = 0;
-}
+NodeRPCProxy::NodeRPCProxy(epee::net_utils::http::http_simple_client &http_client, boost::mutex &mutex)
+ : m_http_client(http_client)
+ , m_daemon_rpc_mutex(mutex)
+ , m_height(0)
+ , m_height_time(0)
+ , m_earliest_height()
+ , m_dynamic_per_kb_fee_estimate(0)
+ , m_dynamic_per_kb_fee_estimate_cached_height(0)
+ , m_dynamic_per_kb_fee_estimate_grace_blocks(0)
+{}
boost::optional<std::string> NodeRPCProxy::get_height(uint64_t &height)
{
@@ -58,7 +56,7 @@ boost::optional<std::string> NodeRPCProxy::get_height(uint64_t &height)
cryptonote::COMMAND_RPC_GET_HEIGHT::response res = AUTO_VAL_INIT(res);
m_daemon_rpc_mutex.lock();
- bool r = net_utils::invoke_http_json_remote_command2(m_daemon_address + "/getheight", req, res, m_http_client);
+ bool r = net_utils::invoke_http_json("/getheight", req, res, m_http_client);
m_daemon_rpc_mutex.unlock();
CHECK_AND_ASSERT_MES(r, std::string(), "Failed to connect to daemon");
CHECK_AND_ASSERT_MES(res.status != CORE_RPC_STATUS_BUSY, res.status, "Failed to connect to daemon");
@@ -87,7 +85,7 @@ boost::optional<std::string> NodeRPCProxy::get_earliest_height(uint8_t version,
req_t.id = epee::serialization::storage_entry(0);
req_t.method = "hard_fork_info";
req_t.params.version = version;
- bool r = net_utils::invoke_http_json_remote_command2(m_daemon_address + "/json_rpc", req_t, resp_t, m_http_client);
+ bool r = net_utils::invoke_http_json("/json_rpc", req_t, resp_t, m_http_client);
m_daemon_rpc_mutex.unlock();
CHECK_AND_ASSERT_MES(r, std::string(), "Failed to connect to daemon");
CHECK_AND_ASSERT_MES(resp_t.result.status != CORE_RPC_STATUS_BUSY, resp_t.result.status, "Failed to connect to daemon");
@@ -117,7 +115,7 @@ boost::optional<std::string> NodeRPCProxy::get_dynamic_per_kb_fee_estimate(uint6
req_t.id = epee::serialization::storage_entry(0);
req_t.method = "get_fee_estimate";
req_t.params.grace_blocks = grace_blocks;
- bool r = net_utils::invoke_http_json_remote_command2(m_daemon_address + "/json_rpc", req_t, resp_t, m_http_client);
+ bool r = net_utils::invoke_http_json("/json_rpc", req_t, resp_t, m_http_client);
m_daemon_rpc_mutex.unlock();
CHECK_AND_ASSERT_MES(r, std::string(), "Failed to connect to daemon");
CHECK_AND_ASSERT_MES(resp_t.result.status != CORE_RPC_STATUS_BUSY, resp_t.result.status, "Failed to connect to daemon");
diff --git a/src/wallet/node_rpc_proxy.h b/src/wallet/node_rpc_proxy.h
index 1ae716dab..e2f42d541 100644
--- a/src/wallet/node_rpc_proxy.h
+++ b/src/wallet/node_rpc_proxy.h
@@ -39,10 +39,7 @@ namespace tools
class NodeRPCProxy
{
public:
- NodeRPCProxy(epee::net_utils::http::http_simple_client &http_client, boost::mutex &mutex):
- m_http_client(http_client), m_daemon_rpc_mutex(mutex) { init(""); }
-
- void init(const std::string &daemon_address);
+ NodeRPCProxy(epee::net_utils::http::http_simple_client &http_client, boost::mutex &mutex);
boost::optional<std::string> get_height(uint64_t &height);
void set_height(uint64_t h);
@@ -50,7 +47,6 @@ public:
boost::optional<std::string> get_dynamic_per_kb_fee_estimate(uint64_t grace_blocks, uint64_t &fee);
private:
- std::string m_daemon_address;
epee::net_utils::http::http_simple_client &m_http_client;
boost::mutex &m_daemon_rpc_mutex;
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
index 2f06be450..9fd98056a 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
@@ -164,7 +164,7 @@ std::unique_ptr<tools::wallet2> make_basic(const boost::program_options::variabl
daemon_address = std::string("http://") + daemon_host + ":" + std::to_string(daemon_port);
std::unique_ptr<tools::wallet2> wallet(new tools::wallet2(testnet, restricted));
- wallet->init(daemon_address);
+ wallet->init(std::move(daemon_address));
return wallet;
}
@@ -418,6 +418,7 @@ namespace tools
// for now, limit to 30 attempts. TODO: discuss a good number to limit to.
const size_t MAX_SPLIT_ATTEMPTS = 30;
+constexpr const std::chrono::seconds wallet2::rpc_timeout;
const char* wallet2::tr(const char* str) { return i18n_translate(str, "tools::wallet2"); }
bool wallet2::has_testnet_option(const boost::program_options::variables_map& vm)
@@ -484,11 +485,11 @@ std::pair<std::unique_ptr<wallet2>, password_container> wallet2::make_new(const
}
//----------------------------------------------------------------------------------------------------
-void wallet2::init(const std::string& daemon_address, uint64_t upper_transaction_size_limit)
+bool wallet2::init(std::string daemon_address, uint64_t upper_transaction_size_limit)
{
m_upper_transaction_size_limit = upper_transaction_size_limit;
- m_daemon_address = daemon_address;
- m_node_rpc_proxy.init(m_daemon_address);
+ m_daemon_address = std::move(daemon_address);
+ return m_http_client.set_server(get_daemon_address());
}
//----------------------------------------------------------------------------------------------------
bool wallet2::is_deterministic() const
@@ -841,7 +842,7 @@ void wallet2::process_new_transaction(const cryptonote::transaction& tx, const s
" not match with daemon response size=" + std::to_string(o_indices.size()));
}
- BOOST_FOREACH(size_t o, outs)
+ for(size_t o: outs)
{
THROW_WALLET_EXCEPTION_IF(tx.vout.size() <= o, error::wallet_internal_error, "wrong out in transaction: internal index=" +
std::to_string(o) + ", total_outs=" + std::to_string(tx.vout.size()));
@@ -945,7 +946,7 @@ void wallet2::process_new_transaction(const cryptonote::transaction& tx, const s
uint64_t tx_money_spent_in_ins = 0;
// check all outputs for spending (compare key images)
- BOOST_FOREACH(auto& in, tx.vin)
+ for(auto& in: tx.vin)
{
if(in.type() != typeid(cryptonote::txin_to_key))
continue;
@@ -1106,7 +1107,7 @@ void wallet2::process_new_blockchain_entry(const cryptonote::block& b, const cry
TIME_MEASURE_FINISH(miner_tx_handle_time);
TIME_MEASURE_START(txs_handle_time);
- BOOST_FOREACH(auto& txblob, bche.txs)
+ for(auto& txblob: bche.txs)
{
cryptonote::transaction tx;
bool r = parse_and_validate_tx_from_blob(txblob, tx);
@@ -1169,7 +1170,7 @@ void wallet2::pull_blocks(uint64_t start_height, uint64_t &blocks_start_height,
req.start_height = start_height;
m_daemon_rpc_mutex.lock();
- bool r = net_utils::invoke_http_bin_remote_command2(m_daemon_address + "/getblocks.bin", req, res, m_http_client, WALLET_RCP_CONNECTION_TIMEOUT);
+ bool r = net_utils::invoke_http_bin("/getblocks.bin", req, res, m_http_client, rpc_timeout);
m_daemon_rpc_mutex.unlock();
THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "getblocks.bin");
THROW_WALLET_EXCEPTION_IF(res.status == CORE_RPC_STATUS_BUSY, error::daemon_busy, "getblocks.bin");
@@ -1191,7 +1192,7 @@ void wallet2::pull_hashes(uint64_t start_height, uint64_t &blocks_start_height,
req.start_height = start_height;
m_daemon_rpc_mutex.lock();
- bool r = net_utils::invoke_http_bin_remote_command2(m_daemon_address + "/gethashes.bin", req, res, m_http_client, WALLET_RCP_CONNECTION_TIMEOUT);
+ bool r = net_utils::invoke_http_bin("/gethashes.bin", req, res, m_http_client, rpc_timeout);
m_daemon_rpc_mutex.unlock();
THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "gethashes.bin");
THROW_WALLET_EXCEPTION_IF(res.status == CORE_RPC_STATUS_BUSY, error::daemon_busy, "gethashes.bin");
@@ -1275,7 +1276,7 @@ void wallet2::process_blocks(uint64_t start_height, const std::list<cryptonote::
}
else
{
- BOOST_FOREACH(auto& bl_entry, blocks)
+ for(auto& bl_entry: blocks)
{
cryptonote::block bl;
bool r = cryptonote::parse_and_validate_block_from_blob(bl_entry.block, bl);
@@ -1353,7 +1354,7 @@ void wallet2::update_pool_state()
cryptonote::COMMAND_RPC_GET_TRANSACTION_POOL::request req;
cryptonote::COMMAND_RPC_GET_TRANSACTION_POOL::response res;
m_daemon_rpc_mutex.lock();
- bool r = epee::net_utils::invoke_http_json_remote_command2(m_daemon_address + "/get_transaction_pool", req, res, m_http_client, 200000);
+ bool r = epee::net_utils::invoke_http_json("/get_transaction_pool", req, res, m_http_client, rpc_timeout);
m_daemon_rpc_mutex.unlock();
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");
@@ -1461,7 +1462,7 @@ void wallet2::update_pool_state()
req.txs_hashes.push_back(it.id_hash);
req.decode_as_json = false;
m_daemon_rpc_mutex.lock();
- bool r = epee::net_utils::invoke_http_json_remote_command2(m_daemon_address + "/gettransactions", req, res, m_http_client, 200000);
+ bool r = epee::net_utils::invoke_http_json("/gettransactions", req, res, m_http_client, rpc_timeout);
m_daemon_rpc_mutex.unlock();
if (r && res.status == CORE_RPC_STATUS_OK)
{
@@ -1556,7 +1557,7 @@ void wallet2::fast_refresh(uint64_t stop_height, uint64_t &blocks_start_height,
}
}
current_index = blocks_start_height;
- BOOST_FOREACH(auto& bl_id, hashes)
+ for(auto& bl_id: hashes)
{
if(current_index >= m_blockchain.size())
{
@@ -2262,15 +2263,7 @@ bool wallet2::check_connection(uint32_t *version, uint32_t timeout)
if(!m_http_client.is_connected())
{
- net_utils::http::url_content u;
- net_utils::parse_url(m_daemon_address, u);
-
- if(!u.port)
- {
- u.port = m_testnet ? config::testnet::RPC_DEFAULT_PORT : config::RPC_DEFAULT_PORT;
- }
-
- if (!m_http_client.connect(u.host, std::to_string(u.port), timeout))
+ if (!m_http_client.connect(std::chrono::milliseconds(timeout)))
return false;
}
@@ -2281,7 +2274,7 @@ bool wallet2::check_connection(uint32_t *version, uint32_t timeout)
req_t.jsonrpc = "2.0";
req_t.id = epee::serialization::storage_entry(0);
req_t.method = "get_version";
- bool r = net_utils::invoke_http_json_remote_command2(m_daemon_address + "/json_rpc", req_t, resp_t, m_http_client);
+ bool r = net_utils::invoke_http_json("/json_rpc", req_t, resp_t, m_http_client);
if (!r || resp_t.result.status != CORE_RPC_STATUS_OK)
*version = 0;
else
@@ -2514,7 +2507,7 @@ void wallet2::store_to(const std::string &path, const std::string &password)
uint64_t wallet2::unlocked_balance() const
{
uint64_t amount = 0;
- BOOST_FOREACH(const transfer_details& td, m_transfers)
+ for(const transfer_details& td: m_transfers)
if(!td.m_spent && is_transfer_unlocked(td))
amount += td.amount();
@@ -2524,12 +2517,12 @@ uint64_t wallet2::unlocked_balance() const
uint64_t wallet2::balance() const
{
uint64_t amount = 0;
- BOOST_FOREACH(auto& td, m_transfers)
+ for(auto& td: m_transfers)
if(!td.m_spent)
amount += td.amount();
- BOOST_FOREACH(auto& utx, m_unconfirmed_txs)
+ for(auto& utx: m_unconfirmed_txs)
if (utx.second.m_state != wallet2::unconfirmed_transfer_details::failed)
amount+= utx.second.m_change;
@@ -2602,7 +2595,7 @@ void wallet2::rescan_spent()
COMMAND_RPC_IS_KEY_IMAGE_SPENT::response daemon_resp = AUTO_VAL_INIT(daemon_resp);
req.key_images = key_images;
m_daemon_rpc_mutex.lock();
- bool r = epee::net_utils::invoke_http_json_remote_command2(m_daemon_address + "/is_key_image_spent", req, daemon_resp, m_http_client, 200000);
+ bool r = epee::net_utils::invoke_http_json("/is_key_image_spent", req, daemon_resp, m_http_client, rpc_timeout);
m_daemon_rpc_mutex.unlock();
THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "is_key_image_spent");
THROW_WALLET_EXCEPTION_IF(daemon_resp.status == CORE_RPC_STATUS_BUSY, error::daemon_busy, "is_key_image_spent");
@@ -2976,7 +2969,7 @@ void wallet2::commit_tx(pending_tx& ptx)
req.do_not_relay = false;
COMMAND_RPC_SEND_RAW_TX::response daemon_send_resp;
m_daemon_rpc_mutex.lock();
- bool r = epee::net_utils::invoke_http_json_remote_command2(m_daemon_address + "/sendrawtransaction", req, daemon_send_resp, m_http_client, 200000);
+ bool r = epee::net_utils::invoke_http_json("/sendrawtransaction", req, daemon_send_resp, m_http_client, rpc_timeout);
m_daemon_rpc_mutex.unlock();
THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "sendrawtransaction");
THROW_WALLET_EXCEPTION_IF(daemon_send_resp.status == CORE_RPC_STATUS_BUSY, error::daemon_busy, "sendrawtransaction");
@@ -2997,7 +2990,7 @@ void wallet2::commit_tx(pending_tx& ptx)
{
payment_id = get_payment_id(ptx);
dests = ptx.dests;
- BOOST_FOREACH(size_t idx, ptx.selected_transfers)
+ for(size_t idx: ptx.selected_transfers)
amount_in += m_transfers[idx].amount();
}
add_unconfirmed_tx(ptx.tx, amount_in, dests, payment_id, ptx.change_dts.amount);
@@ -3008,7 +3001,7 @@ void wallet2::commit_tx(pending_tx& ptx)
LOG_PRINT_L2("transaction " << txid << " generated ok and sent to daemon, key_images: [" << ptx.key_images << "]");
- BOOST_FOREACH(size_t idx, ptx.selected_transfers)
+ for(size_t idx: ptx.selected_transfers)
{
set_spent(idx, 0);
}
@@ -3356,7 +3349,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions(std::vector<crypto
ptx_vector.push_back(ptx);
// mark transfers to be used as "spent"
- BOOST_FOREACH(size_t idx, ptx.selected_transfers)
+ for(size_t idx: ptx.selected_transfers)
{
set_spent(idx, 0);
}
@@ -3368,7 +3361,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions(std::vector<crypto
for (auto & ptx : ptx_vector)
{
// mark transfers to be used as not spent
- BOOST_FOREACH(size_t idx2, ptx.selected_transfers)
+ for(size_t idx2: ptx.selected_transfers)
{
set_unspent(idx2);
}
@@ -3387,7 +3380,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions(std::vector<crypto
for (auto & ptx : ptx_vector)
{
// mark transfers to be used as not spent
- BOOST_FOREACH(size_t idx2, ptx.selected_transfers)
+ for(size_t idx2: ptx.selected_transfers)
{
set_unspent(idx2);
}
@@ -3406,7 +3399,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions(std::vector<crypto
for (auto & ptx : ptx_vector)
{
// mark transfers to be used as not spent
- BOOST_FOREACH(size_t idx2, ptx.selected_transfers)
+ for(size_t idx2: ptx.selected_transfers)
{
set_unspent(idx2);
}
@@ -3437,7 +3430,7 @@ void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>>
req_t.params.amounts.resize(std::distance(req_t.params.amounts.begin(), end));
req_t.params.unlocked = true;
req_t.params.recent_cutoff = time(NULL) - RECENT_OUTPUT_ZONE;
- bool r = net_utils::invoke_http_json_remote_command2(m_daemon_address + "/json_rpc", req_t, resp_t, m_http_client);
+ bool r = net_utils::invoke_http_json("/json_rpc", req_t, resp_t, m_http_client);
m_daemon_rpc_mutex.unlock();
THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "transfer_selected");
THROW_WALLET_EXCEPTION_IF(resp_t.result.status == CORE_RPC_STATUS_BUSY, error::daemon_busy, "get_output_histogram");
@@ -3564,7 +3557,7 @@ void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>>
// get the keys for those
m_daemon_rpc_mutex.lock();
- r = epee::net_utils::invoke_http_bin_remote_command2(m_daemon_address + "/get_outs.bin", req, daemon_resp, m_http_client, 200000);
+ r = epee::net_utils::invoke_http_bin("/get_outs.bin", req, daemon_resp, m_http_client, rpc_timeout);
m_daemon_rpc_mutex.unlock();
THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "get_outs.bin");
THROW_WALLET_EXCEPTION_IF(daemon_resp.status == CORE_RPC_STATUS_BUSY, error::daemon_busy, "get_outs.bin");
@@ -3667,7 +3660,7 @@ void wallet2::transfer_selected(const std::vector<cryptonote::tx_destination_ent
// calculate total amount being sent to all destinations
// throw if total amount overflows uint64_t
- BOOST_FOREACH(auto& dt, dsts)
+ for(auto& dt: dsts)
{
THROW_WALLET_EXCEPTION_IF(0 == dt.amount, error::zero_destination);
needed_money += dt.amount;
@@ -3676,7 +3669,7 @@ void wallet2::transfer_selected(const std::vector<cryptonote::tx_destination_ent
}
uint64_t found_money = 0;
- BOOST_FOREACH(size_t idx, selected_transfers)
+ for(size_t idx: selected_transfers)
{
found_money += m_transfers[idx].amount();
}
@@ -3692,7 +3685,7 @@ void wallet2::transfer_selected(const std::vector<cryptonote::tx_destination_ent
typedef cryptonote::tx_source_entry::output_entry tx_output_entry;
size_t i = 0, out_index = 0;
std::vector<cryptonote::tx_source_entry> sources;
- BOOST_FOREACH(size_t idx, selected_transfers)
+ for(size_t idx: selected_transfers)
{
sources.resize(sources.size()+1);
cryptonote::tx_source_entry& src = sources.back();
@@ -3743,11 +3736,11 @@ void wallet2::transfer_selected(const std::vector<cryptonote::tx_destination_ent
std::vector<cryptonote::tx_destination_entry> splitted_dsts, dust_dsts;
uint64_t dust = 0;
destination_split_strategy(dsts, change_dts, dust_policy.dust_threshold, splitted_dsts, dust_dsts);
- BOOST_FOREACH(auto& d, dust_dsts) {
+ for(auto& d: dust_dsts) {
THROW_WALLET_EXCEPTION_IF(dust_policy.dust_threshold < d.amount, error::wallet_internal_error, "invalid dust value: dust = " +
std::to_string(d.amount) + ", dust_threshold = " + std::to_string(dust_policy.dust_threshold));
}
- BOOST_FOREACH(auto& d, dust_dsts) {
+ for(auto& d: dust_dsts) {
if (!dust_policy.add_to_fee)
splitted_dsts.push_back(cryptonote::tx_destination_entry(d.amount, dust_policy.addr_for_dust));
dust += d.amount;
@@ -3812,7 +3805,7 @@ void wallet2::transfer_selected_rct(std::vector<cryptonote::tx_destination_entry
// calculate total amount being sent to all destinations
// throw if total amount overflows uint64_t
- BOOST_FOREACH(auto& dt, dsts)
+ for(auto& dt: dsts)
{
THROW_WALLET_EXCEPTION_IF(0 == dt.amount, error::zero_destination);
needed_money += dt.amount;
@@ -3821,7 +3814,7 @@ void wallet2::transfer_selected_rct(std::vector<cryptonote::tx_destination_entry
}
uint64_t found_money = 0;
- BOOST_FOREACH(size_t idx, selected_transfers)
+ for(size_t idx: selected_transfers)
{
found_money += m_transfers[idx].amount();
}
@@ -3836,7 +3829,7 @@ void wallet2::transfer_selected_rct(std::vector<cryptonote::tx_destination_entry
LOG_PRINT_L2("preparing outputs");
size_t i = 0, out_index = 0;
std::vector<cryptonote::tx_source_entry> sources;
- BOOST_FOREACH(size_t idx, selected_transfers)
+ for(size_t idx: selected_transfers)
{
sources.resize(sources.size()+1);
cryptonote::tx_source_entry& src = sources.back();
@@ -4107,7 +4100,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
// calculate total amount being sent to all destinations
// throw if total amount overflows uint64_t
needed_money = 0;
- BOOST_FOREACH(auto& dt, dsts)
+ for(auto& dt: dsts)
{
THROW_WALLET_EXCEPTION_IF(0 == dt.amount, error::zero_destination);
needed_money += dt.amount;
@@ -4636,7 +4629,7 @@ std::vector<size_t> wallet2::select_available_outputs_from_histogram(uint64_t co
req_t.params.min_count = count;
req_t.params.max_count = 0;
req_t.params.unlocked = unlocked;
- bool r = net_utils::invoke_http_json_remote_command2(m_daemon_address + "/json_rpc", req_t, resp_t, m_http_client);
+ bool r = net_utils::invoke_http_json("/json_rpc", req_t, resp_t, m_http_client);
m_daemon_rpc_mutex.unlock();
THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "select_available_unmixable_outputs");
THROW_WALLET_EXCEPTION_IF(resp_t.result.status == CORE_RPC_STATUS_BUSY, error::daemon_busy, "get_output_histogram");
@@ -4675,7 +4668,7 @@ uint64_t wallet2::get_num_rct_outputs()
req_t.params.amounts.push_back(0);
req_t.params.min_count = 0;
req_t.params.max_count = 0;
- bool r = net_utils::invoke_http_json_remote_command2(m_daemon_address + "/json_rpc", req_t, resp_t, m_http_client);
+ bool r = net_utils::invoke_http_json("/json_rpc", req_t, resp_t, m_http_client);
m_daemon_rpc_mutex.unlock();
THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "get_num_rct_outputs");
THROW_WALLET_EXCEPTION_IF(resp_t.result.status == CORE_RPC_STATUS_BUSY, error::daemon_busy, "get_output_histogram");
@@ -4784,7 +4777,7 @@ uint64_t wallet2::get_daemon_blockchain_target_height(string &err)
req_t.jsonrpc = "2.0";
req_t.id = epee::serialization::storage_entry(0);
req_t.method = "get_info";
- bool ok = net_utils::invoke_http_json_remote_command2(m_daemon_address + "/json_rpc", req_t, resp_t, m_http_client);
+ bool ok = net_utils::invoke_http_json("/json_rpc", req_t, resp_t, m_http_client);
m_daemon_rpc_mutex.unlock();
if (ok)
{
@@ -5097,7 +5090,7 @@ uint64_t wallet2::import_key_images(const std::vector<std::pair<crypto::key_imag
}
m_daemon_rpc_mutex.lock();
- bool r = epee::net_utils::invoke_http_json_remote_command2(m_daemon_address + "/is_key_image_spent", req, daemon_resp, m_http_client, 200000);
+ bool r = epee::net_utils::invoke_http_json("/is_key_image_spent", req, daemon_resp, m_http_client, rpc_timeout);
m_daemon_rpc_mutex.unlock();
THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "is_key_image_spent");
THROW_WALLET_EXCEPTION_IF(daemon_resp.status == CORE_RPC_STATUS_BUSY, error::daemon_busy, "is_key_image_spent");
@@ -5407,7 +5400,7 @@ uint64_t wallet2::get_blockchain_height_by_date(uint16_t year, uint8_t month, ui
height_mid,
height_max
};
- bool r = net_utils::invoke_http_bin_remote_command2(get_daemon_address() + "/getblocks_by_height.bin", req, res, m_http_client);
+ bool r = net_utils::invoke_http_bin("/getblocks_by_height.bin", req, res, m_http_client);
if (!r || res.status != CORE_RPC_STATUS_OK)
{
std::ostringstream oss;
diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h
index 629011800..91d4db47e 100644
--- a/src/wallet/wallet2.h
+++ b/src/wallet/wallet2.h
@@ -61,8 +61,6 @@
#undef MONERO_DEFAULT_LOG_CATEGORY
#define MONERO_DEFAULT_LOG_CATEGORY "wallet.wallet2"
-#define WALLET_RCP_CONNECTION_TIMEOUT 200000
-
class Serialization_portability_wallet_Test;
namespace tools
@@ -96,6 +94,8 @@ namespace tools
{
friend class ::Serialization_portability_wallet_Test;
public:
+ static constexpr const std::chrono::seconds rpc_timeout = std::chrono::minutes(3) + std::chrono::seconds(30);
+
enum RefreshType {
RefreshFull,
RefreshOptimizeCoinbase,
@@ -107,7 +107,7 @@ namespace tools
wallet2(const wallet2&) : m_run(true), m_callback(0), m_testnet(false), m_always_confirm_transfers(true), m_print_ring_members(false), m_store_tx_info(true), m_default_mixin(0), m_default_priority(0), m_refresh_type(RefreshOptimizeCoinbase), m_auto_refresh(true), m_refresh_from_block_height(0), m_confirm_missing_payment_id(true), m_node_rpc_proxy(m_http_client, m_daemon_rpc_mutex) {}
public:
- static const char* tr(const char* str);// { return i18n_translate(str, "cryptonote::simple_wallet"); }
+ static const char* tr(const char* str);
static bool has_testnet_option(const boost::program_options::variables_map& vm);
static void init_options(boost::program_options::options_description& desc_params);
@@ -342,8 +342,8 @@ namespace tools
// free block size. TODO: fix this so that it actually takes
// into account the current median block size rather than
// the minimum block size.
- void init(const std::string& daemon_address = "http://localhost:8080", uint64_t upper_transaction_size_limit = 0);
bool deinit();
+ bool init(std::string daemon_address = "http://localhost:8080", uint64_t upper_transaction_size_limit = 0);
void stop() { m_run.store(false, std::memory_order_relaxed); }
@@ -924,7 +924,7 @@ namespace tools
splitted_dsts.clear();
dust_dsts.clear();
- BOOST_FOREACH(auto& de, dsts)
+ for(auto& de: dsts)
{
cryptonote::decompose_amount_into_digits(de.amount, 0,
[&](uint64_t chunk) { splitted_dsts.push_back(cryptonote::tx_destination_entry(chunk, de.addr)); },
@@ -987,7 +987,7 @@ namespace tools
// calculate total amount being sent to all destinations
// throw if total amount overflows uint64_t
- BOOST_FOREACH(auto& dt, dsts)
+ for(auto& dt: dsts)
{
THROW_WALLET_EXCEPTION_IF(0 == dt.amount, error::zero_destination);
needed_money += dt.amount;
@@ -1008,7 +1008,7 @@ namespace tools
{
COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::request req = AUTO_VAL_INIT(req);
req.outs_count = fake_outputs_count + 1;// add one to make possible (if need) to skip real output key
- BOOST_FOREACH(size_t idx, selected_transfers)
+ for(size_t idx: selected_transfers)
{
const transfer_container::const_iterator it = m_transfers.begin() + idx;
THROW_WALLET_EXCEPTION_IF(it->m_tx.vout.size() <= it->m_internal_output_index, error::wallet_internal_error,
@@ -1018,7 +1018,7 @@ namespace tools
}
m_daemon_rpc_mutex.lock();
- bool r = epee::net_utils::invoke_http_bin_remote_command2(m_daemon_address + "/getrandom_outs.bin", req, daemon_resp, m_http_client, 200000);
+ bool r = epee::net_utils::invoke_http_bin("/getrandom_outs.bin", req, daemon_resp, m_http_client, rpc_timeout);
m_daemon_rpc_mutex.unlock();
THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "getrandom_outs.bin");
THROW_WALLET_EXCEPTION_IF(daemon_resp.status == CORE_RPC_STATUS_BUSY, error::daemon_busy, "getrandom_outs.bin");
@@ -1028,7 +1028,7 @@ namespace tools
std::to_string(daemon_resp.outs.size()) + ", expected " + std::to_string(selected_transfers.size()));
std::unordered_map<uint64_t, uint64_t> scanty_outs;
- BOOST_FOREACH(COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount& amount_outs, daemon_resp.outs)
+ for(COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount& amount_outs: daemon_resp.outs)
{
if (amount_outs.outs.size() < fake_outputs_count)
{
@@ -1041,7 +1041,7 @@ namespace tools
//prepare inputs
size_t i = 0;
std::vector<cryptonote::tx_source_entry> sources;
- BOOST_FOREACH(size_t idx, selected_transfers)
+ for(size_t idx: selected_transfers)
{
sources.resize(sources.size()+1);
cryptonote::tx_source_entry& src = sources.back();
@@ -1052,7 +1052,7 @@ namespace tools
if(daemon_resp.outs.size())
{
daemon_resp.outs[i].outs.sort([](const out_entry& a, const out_entry& b){return a.global_amount_index < b.global_amount_index;});
- BOOST_FOREACH(out_entry& daemon_oe, daemon_resp.outs[i].outs)
+ for(out_entry& daemon_oe: daemon_resp.outs[i].outs)
{
if(td.m_global_output_index == daemon_oe.global_amount_index)
continue;
@@ -1094,11 +1094,11 @@ namespace tools
std::vector<cryptonote::tx_destination_entry> splitted_dsts, dust_dsts;
uint64_t dust = 0;
destination_split_strategy(dsts, change_dts, dust_policy.dust_threshold, splitted_dsts, dust_dsts);
- BOOST_FOREACH(auto& d, dust_dsts) {
+ for(auto& d: dust_dsts) {
THROW_WALLET_EXCEPTION_IF(dust_policy.dust_threshold < d.amount, error::wallet_internal_error, "invalid dust value: dust = " +
std::to_string(d.amount) + ", dust_threshold = " + std::to_string(dust_policy.dust_threshold));
}
- BOOST_FOREACH(auto& d, dust_dsts) {
+ for(auto& d: dust_dsts) {
if (!dust_policy.add_to_fee)
splitted_dsts.push_back(cryptonote::tx_destination_entry(d.amount, dust_policy.addr_for_dust));
dust += d.amount;
diff --git a/src/wallet/wallet2_api.h b/src/wallet/wallet2_api.h
index 78caddc0b..563f16eaa 100644
--- a/src/wallet/wallet2_api.h
+++ b/src/wallet/wallet2_api.h
@@ -295,6 +295,7 @@ struct Wallet
virtual bool setPassword(const std::string &password) = 0;
virtual std::string address() const = 0;
virtual std::string path() const = 0;
+ virtual bool testnet() const = 0;
/*!
* \brief integratedAddress - returns integrated address for current wallet address and given payment_id.
@@ -434,6 +435,7 @@ struct Wallet
static std::string genPaymentId();
static bool paymentIdValid(const std::string &paiment_id);
static bool addressValid(const std::string &str, bool testnet);
+ static bool keyValid(const std::string &secret_key_string, const std::string &address_string, bool isViewKey, bool testnet, std::string &error);
static std::string paymentIdFromAddress(const std::string &str, bool testnet);
static uint64_t maximumAllowedAmount();
@@ -613,6 +615,25 @@ struct WalletManager
*/
virtual Wallet * recoveryWallet(const std::string &path, const std::string &memo, bool testnet = false, uint64_t restoreHeight = 0) = 0;
+ /*!
+ * \brief recovers existing wallet using keys. Creates a view only wallet if spend key is omitted
+ * \param path Name of wallet file to be created
+ * \param language language
+ * \param testnet testnet
+ * \param restoreHeight restore from start height
+ * \param addressString public address
+ * \param viewKeyString view key
+ * \param spendKeyString spend key (optional)
+ * \return Wallet instance (Wallet::status() needs to be called to check if recovered successfully)
+ */
+ virtual Wallet * createWalletFromKeys(const std::string &path,
+ const std::string &language,
+ bool testnet,
+ uint64_t restoreHeight,
+ const std::string &addressString,
+ const std::string &viewKeyString,
+ const std::string &spendKeyString = "") = 0;
+
/*!
* \brief Closes wallet. In case operation succeded, wallet object deleted. in case operation failed, wallet object not deleted
* \param wallet previously opened / created wallet instance
diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp
index 33e099ceb..d35e51068 100644
--- a/src/wallet/wallet_rpc_server.cpp
+++ b/src/wallet/wallet_rpc_server.cpp
@@ -369,7 +369,7 @@ namespace tools
cryptonote::set_payment_id_to_tx_extra_nonce(extra_nonce, long_payment_id);
}
/* or short payment ID */
- else if (!wallet2::parse_short_payment_id(payment_id_str, short_payment_id)) {
+ else if (wallet2::parse_short_payment_id(payment_id_str, short_payment_id)) {
cryptonote::set_encrypted_payment_id_to_tx_extra_nonce(extra_nonce, short_payment_id);
}
else {