Electroneum
wallet_manager.cpp
Go to the documentation of this file.
1 // Copyrights(c) 2017-2021, The Electroneum Project
2 // Copyrights(c) 2014-2019, The Monero Project
3 //
4 // All rights reserved.
5 //
6 // Redistribution and use in source and binary forms, with or without modification, are
7 // permitted provided that the following conditions are met:
8 //
9 // 1. Redistributions of source code must retain the above copyright notice, this list of
10 // conditions and the following disclaimer.
11 //
12 // 2. Redistributions in binary form must reproduce the above copyright notice, this list
13 // of conditions and the following disclaimer in the documentation and/or other
14 // materials provided with the distribution.
15 //
16 // 3. Neither the name of the copyright holder nor the names of its contributors may be
17 // used to endorse or promote products derived from this software without specific
18 // prior written permission.
19 //
20 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
21 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
22 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
23 // THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27 // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
28 // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 //
30 // Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
31 
32 
33 #include "wallet_manager.h"
34 #include "wallet.h"
35 #include "common_defines.h"
36 #include "common/dns_utils.h"
37 #include "common/util.h"
38 #include "common/updates.h"
39 #include "version.h"
40 #include "net/http_client.h"
41 #include <boost/filesystem.hpp>
42 #include <boost/regex.hpp>
43 
44 #undef ELECTRONEUM_DEFAULT_LOG_CATEGORY
45 #define ELECTRONEUM_DEFAULT_LOG_CATEGORY "WalletAPI"
46 
47 namespace epee {
48  unsigned int g_test_dbg_lock_sleep = 0;
49 }
50 
51 namespace Electroneum {
52 
54  const std::string &language, NetworkType nettype, uint64_t kdf_rounds)
55 {
56  WalletImpl * wallet = new WalletImpl(nettype, kdf_rounds);
57  wallet->create(path, password, language);
58  return wallet;
59 }
60 
61 Wallet *WalletManagerImpl::openWallet(const std::string &path, const std::string &password, NetworkType nettype, uint64_t kdf_rounds, WalletListener * listener)
62 {
63  WalletImpl * wallet = new WalletImpl(nettype, kdf_rounds);
64  wallet->setListener(listener);
65  if (listener){
66  listener->onSetWallet(wallet);
67  }
68 
69  wallet->open(path, password);
70  //Refresh addressBook
71  wallet->addressBook()->refresh();
72  return wallet;
73 }
74 
75 Wallet *WalletManagerImpl::recoveryWallet(const std::string &path, const std::string &mnemonic, NetworkType nettype, uint64_t restoreHeight)
76 {
77  return recoveryWallet(path, "", mnemonic, nettype, restoreHeight);
78 }
79 
81  const std::string &language,
82  NetworkType nettype,
83  uint64_t restoreHeight,
84  const std::string &addressString,
85  const std::string &viewKeyString,
86  const std::string &spendKeyString)
87 {
88  return createWalletFromKeys(path, "", language, nettype, restoreHeight,
89  addressString, viewKeyString, spendKeyString);
90 }
91 
93  const std::string &password,
94  const std::string &mnemonic,
95  NetworkType nettype,
96  uint64_t restoreHeight,
97  uint64_t kdf_rounds)
98 {
99  WalletImpl * wallet = new WalletImpl(nettype, kdf_rounds);
100  if(restoreHeight > 0){
101  wallet->setRefreshFromBlockHeight(restoreHeight);
102  }
103  wallet->recover(path, password, mnemonic);
104  return wallet;
105 }
106 
108  const std::string &password,
109  const std::string &language,
110  NetworkType nettype,
111  uint64_t restoreHeight,
112  const std::string &addressString,
113  const std::string &viewKeyString,
114  const std::string &spendKeyString,
115  uint64_t kdf_rounds)
116 {
117  WalletImpl * wallet = new WalletImpl(nettype, kdf_rounds);
118  if(restoreHeight > 0){
119  wallet->setRefreshFromBlockHeight(restoreHeight);
120  }
121  wallet->recoverFromKeysWithPassword(path, password, language, addressString, viewKeyString, spendKeyString);
122  return wallet;
123 }
124 
126  const std::string &password,
127  NetworkType nettype,
128  const std::string &deviceName,
129  uint64_t restoreHeight,
130  const std::string &subaddressLookahead,
131  uint64_t kdf_rounds,
132  WalletListener * listener)
133 {
134  WalletImpl * wallet = new WalletImpl(nettype, kdf_rounds);
135  wallet->setListener(listener);
136  if (listener){
137  listener->onSetWallet(wallet);
138  }
139 
140  if(restoreHeight > 0){
141  wallet->setRefreshFromBlockHeight(restoreHeight);
142  } else {
144  }
145  auto lookahead = tools::parse_subaddress_lookahead(subaddressLookahead);
146  if (lookahead)
147  {
148  wallet->setSubaddressLookahead(lookahead->first, lookahead->second);
149  }
150  wallet->recoverFromDevice(path, password, deviceName);
151  return wallet;
152 }
153 
154 bool WalletManagerImpl::closeWallet(Wallet *wallet, bool store)
155 {
156  WalletImpl * wallet_ = dynamic_cast<WalletImpl*>(wallet);
157  if (!wallet_)
158  return false;
159  bool result = wallet_->close(store);
160  if (!result) {
161  m_errorString = wallet_->errorString();
162  } else {
163  delete wallet_;
164  }
165  return result;
166 }
167 
169 {
170  bool keys_file_exists;
171  bool wallet_file_exists;
172  tools::wallet2::wallet_exists(path, keys_file_exists, wallet_file_exists);
173  if(keys_file_exists){
174  return true;
175  }
176  return false;
177 }
178 
179 bool WalletManagerImpl::verifyWalletPassword(const std::string &keys_file_name, const std::string &password, bool no_spend_key, uint64_t kdf_rounds) const
180 {
181  return tools::wallet2::verify_password(keys_file_name, password, no_spend_key, hw::get_device("default"), kdf_rounds);
182 }
183 
184 bool WalletManagerImpl::queryWalletDevice(Wallet::Device& device_type, const std::string &keys_file_name, const std::string &password, uint64_t kdf_rounds) const
185 {
187  bool r = tools::wallet2::query_device(type, keys_file_name, password, kdf_rounds);
188  device_type = static_cast<Wallet::Device>(type);
189  return r;
190 }
191 
192 std::vector<std::string> WalletManagerImpl::findWallets(const std::string &path)
193 {
194  std::vector<std::string> result;
195  boost::filesystem::path work_dir(path);
196  // return empty result if path doesn't exist
197  if(!boost::filesystem::is_directory(path)){
198  return result;
199  }
200  const boost::regex wallet_rx("(.*)\\.(keys)$"); // searching for <wallet_name>.keys files
201  boost::filesystem::recursive_directory_iterator end_itr; // Default ctor yields past-the-end
202  for (boost::filesystem::recursive_directory_iterator itr(path); itr != end_itr; ++itr) {
203  // Skip if not a file
204  if (!boost::filesystem::is_regular_file(itr->status()))
205  continue;
206  boost::smatch what;
207  std::string filename = itr->path().filename().string();
208 
209  LOG_PRINT_L3("Checking filename: " << filename);
210 
211  bool matched = boost::regex_match(filename, what, wallet_rx);
212  if (matched) {
213  // if keys file found, checking if there's wallet file itself
214  std::string wallet_file = (itr->path().parent_path() /= what[1].str()).string();
215  if (boost::filesystem::exists(wallet_file)) {
216  LOG_PRINT_L3("Found wallet: " << wallet_file);
217  result.push_back(wallet_file);
218  }
219  }
220  }
221  return result;
222 }
223 
225 {
226  return m_errorString;
227 }
228 
230 {
231  m_daemonAddress = address;
232  if(m_http_client.is_connected())
233  m_http_client.disconnect();
234  m_http_client.set_server(address, boost::none);
235 }
236 
238 {
241  req_t.jsonrpc = "2.0";
243  req_t.method = "get_version";
244  if (!epee::net_utils::invoke_http_json("/json_rpc", req_t, resp_t, m_http_client))
245  return false;
246 
247  if (version)
248  *version = resp_t.result.version;
249  return true;
250 }
251 
253 {
256 
257  if (!epee::net_utils::invoke_http_json("/getinfo", ireq, ires, m_http_client))
258  return 0;
259  return ires.height;
260 }
261 
263 {
266 
267  if (!epee::net_utils::invoke_http_json("/getinfo", ireq, ires, m_http_client))
268  return 0;
269  return ires.target_height >= ires.height ? ires.target_height : ires.height;
270 }
271 
273 {
276 
277  if (!epee::net_utils::invoke_http_json("/getinfo", ireq, ires, m_http_client))
278  return 0;
279  return ires.difficulty;
280 }
281 
283 {
286 
288  if (!epee::net_utils::invoke_http_json("/mining_status", mreq, mres, m_http_client))
289  return 0.0;
290  if (!mres.active)
291  return 0.0;
292  return mres.speed;
293 }
294 
296 {
299 
300  if (!epee::net_utils::invoke_http_json("/getinfo", ireq, ires, m_http_client))
301  return 0;
302  return ires.target;
303 }
304 
306 {
309 
310  if (!epee::net_utils::invoke_http_json("/mining_status", mreq, mres, m_http_client))
311  return false;
312  return mres.active;
313 }
314 
315 bool WalletManagerImpl::startMining(const std::string &address, uint32_t threads, bool background_mining, bool ignore_battery)
316 {
319 
320  mreq.miner_address = address;
321  mreq.threads_count = threads;
322  mreq.ignore_battery = ignore_battery;
323  mreq.do_background_mining = background_mining;
324 
325  if (!epee::net_utils::invoke_http_json("/start_mining", mreq, mres, m_http_client))
326  return false;
327  return mres.status == CORE_RPC_STATUS_OK;
328 }
329 
331 {
334 
335  if (!epee::net_utils::invoke_http_json("/stop_mining", mreq, mres, m_http_client))
336  return false;
337  return mres.status == CORE_RPC_STATUS_OK;
338 }
339 
341 {
342  std::vector<std::string> addresses = tools::dns_utils::addresses_from_url(address, dnssec_valid);
343  if (addresses.empty())
344  return "";
345  return addresses.front();
346 }
347 
348 std::tuple<bool, std::string, std::string, std::string, std::string> WalletManager::checkUpdates(const std::string &software, std::string subdir)
349 {
350 #ifdef BUILD_TAG
351  static const char buildtag[] = BOOST_PP_STRINGIZE(BUILD_TAG);
352 #else
353  static const char buildtag[] = "source";
354  // Override the subdir string when built from source
355  subdir = "source";
356 #endif
357 
359  MDEBUG("Checking for a new " << software << " version for " << buildtag);
360  if (!tools::check_updates(software, buildtag, version, hash))
361  return std::make_tuple(false, "", "", "", "");
362 
363  if (tools::vercmp(version.c_str(), ELECTRONEUM_VERSION) > 0)
364  {
365  std::string user_url = tools::get_update_url(software, subdir, buildtag, version, true);
366  std::string auto_url = tools::get_update_url(software, subdir, buildtag, version, false);
367  MGINFO("Version " << version << " of " << software << " for " << buildtag << " is available: " << user_url << ", SHA256 hash " << hash);
368  return std::make_tuple(true, version, hash, user_url, auto_url);
369  }
370  return std::make_tuple(false, "", "", "", "");
371 }
372 
373 
376 {
377 
378  static WalletManagerImpl * g_walletManager = nullptr;
379 
380  if (!g_walletManager) {
381  g_walletManager = new WalletManagerImpl();
382  }
383 
384  return g_walletManager;
385 }
386 
388 {
389  mlog_set_log_level(level);
390 }
391 
393 {
394  mlog_set_log(categories.c_str());
395 }
396 
397 
398 
399 }
400 
401 namespace Bitelectroneum = Electroneum;
bool recoverFromDevice(const std::string &path, const std::string &password, const std::string &device_name)
Definition: wallet.cpp:677
bool set_server(const std::string &address, boost::optional< login > user, ssl_options_t ssl_options=ssl_support_t::e_ssl_support_autodetect)
Definition: http_client.h:302
bool create(const std::string &path, const std::string &password, const std::string &language)
Definition: wallet.cpp:469
static void setLogLevel(int level)
bool isMining() override
returns true iff mining
std::vector< std::string > findWallets(const std::string &path) override
findWallets - searches for the wallet files by given path name recursively
void setDaemonAddress(const std::string &address) override
set the daemon address (hostname and port)
unsigned int g_test_dbg_lock_sleep
virtual Wallet * createWalletFromDevice(const std::string &path, const std::string &password, NetworkType nettype, const std::string &deviceName, uint64_t restoreHeight=0, const std::string &subaddressLookahead="", uint64_t kdf_rounds=1, WalletListener *listener=nullptr) override
creates wallet using hardware device.
static void wallet_exists(const std::string &file_path, bool &keys_file_exists, bool &wallet_file_exists)
Check if wallet keys and bin files exist.
Definition: wallet2.cpp:5697
bool walletExists(const std::string &path) override
TODO: delme walletExists - check if the given filename is the wallet.
epee::serialization::storage_entry id
::std::string string
Definition: gtest-port.h:1097
bool close(bool store=true)
Definition: wallet.cpp:762
static bool query_device(hw::device::device_type &device_type, const std::string &keys_file_name, const epee::wipeable_string &password, uint64_t kdf_rounds=1)
determine the key storage for the specified wallet file
Definition: wallet2.cpp:4807
void mlog_set_log(const char *log)
Definition: mlog.cpp:288
virtual bool closeWallet(Wallet *wallet, bool store=true) override
Closes wallet. In case operation succeeded, wallet object deleted. in case operation failed...
bool invoke_http_json(const boost::string_ref uri, const t_request &out_struct, t_response &result_struct, t_transport &transport, std::chrono::milliseconds timeout=std::chrono::seconds(15), const boost::string_ref method="GET")
bool stopMining() override
stops mining
std::string get_update_url(const std::string &software, const std::string &subdir, const std::string &buildtag, const std::string &version, bool user)
Definition: updates.cpp:101
bool startMining(const std::string &address, uint32_t threads=1, bool background_mining=false, bool ignore_battery=true) override
starts mining with the set number of threads
uint64_t blockchainHeight() override
returns current blockchain height
boost::variant< uint64_t, uint32_t, uint16_t, uint8_t, int64_t, int32_t, int16_t, int8_t, double, bool, std::string, section, array_entry > storage_entry
std::string errorString() const override
in case error status, returns error string
Definition: wallet.cpp:814
uint64_t blockchainTargetHeight() override
returns current blockchain target height
#define MGINFO(x)
Definition: misc_log_ex.h:80
WalletManager - provides functions to manage wallets.
Definition: wallet2_api.h:1017
tuple make_tuple()
Definition: gtest-tuple.h:675
virtual void setListener(WalletListener *l) override
Definition: wallet.cpp:1694
bool open(const std::string &path, const std::string &password)
Definition: wallet.cpp:699
virtual void onSetWallet(Wallet *wallet)
If the listener is created before the wallet this enables to set created wallet object.
Definition: wallet2_api.h:422
virtual Wallet * recoveryWallet(const std::string &path, const std::string &password, const std::string &mnemonic, NetworkType nettype, uint64_t restoreHeight, uint64_t kdf_rounds=1) override
recovers existing wallet using mnemonic (electrum seed)
#define CORE_RPC_STATUS_OK
#define MDEBUG(x)
Definition: misc_log_ex.h:76
uint64_t estimateBlockChainHeight() const override
estimateBlockChainHeight - returns estimate blockchain height. More accurate than approximateBlockCha...
Definition: wallet.cpp:1018
virtual void refresh()=0
static std::tuple< bool, std::string, std::string, std::string, std::string > checkUpdates(const std::string &software, std::string subdir)
checks for an update and returns version, hash and url
bool queryWalletDevice(Wallet::Device &device_type, const std::string &keys_file_name, const std::string &password, uint64_t kdf_rounds=1) const override
determine the key storage for the specified wallet file
Wallet * openWallet(const std::string &path, const std::string &password, NetworkType nettype, uint64_t kdf_rounds=1, WalletListener *listener=nullptr) override
Opens existing wallet.
bool check_updates(const std::string &software, const std::string &buildtag, std::string &version, std::string &hash)
Definition: updates.cpp:41
bool verifyWalletPassword(const std::string &keys_file_name, const std::string &password, bool no_spend_key, uint64_t kdf_rounds=1) const override
verifyWalletPassword - check if the given filename is the wallet
static WalletManager * getWalletManager()
unsigned int uint32_t
Definition: stdint.h:126
virtual Wallet * createWalletFromKeys(const std::string &path, const std::string &password, const std::string &language, NetworkType nettype, uint64_t restoreHeight, const std::string &addressString, const std::string &viewKeyString, const std::string &spendKeyString="", uint64_t kdf_rounds=1) override
recovers existing wallet using keys. Creates a view only wallet if spend key is omitted ...
std::vector< std::string > addresses_from_url(const std::string &url, bool &dnssec_valid)
gets a electroneum address from the TXT record of a DNS entry
Definition: dns_utils.cpp:452
virtual AddressBook * addressBook() override
Definition: wallet.cpp:1679
device & get_device(const std::string &device_descriptor)
Definition: device.cpp:95
static bool verify_password(const std::string &keys_file_name, const epee::wipeable_string &password, bool no_spend_key, hw::device &hwdev, uint64_t kdf_rounds)
verify password for specified wallet keys file.
Definition: wallet2.cpp:4699
bool recover(const std::string &path, const std::string &password, const std::string &seed)
Definition: wallet.cpp:730
unsigned __int64 uint64_t
Definition: stdint.h:136
const char *const ELECTRONEUM_VERSION
uint64_t blockTarget() override
returns current block target
double miningHashRate() override
returns current mining hash rate (0 if not mining)
#define LOG_PRINT_L3(x)
Definition: misc_log_ex.h:102
version
Supported socks variants.
Definition: socks.h:57
std::string resolveOpenAlias(const std::string &address, bool &dnssec_valid) const override
resolves an OpenAlias address to a electroneum address
boost::optional< std::pair< uint32_t, uint32_t > > parse_subaddress_lookahead(const std::string &str)
Definition: util.cpp:977
void setRefreshFromBlockHeight(uint64_t refresh_from_block_height) override
setRefreshFromBlockHeight - start refresh from block height on recover
Definition: wallet.cpp:976
bool recoverFromKeysWithPassword(const std::string &path, const std::string &password, const std::string &language, const std::string &address_string, const std::string &viewkey_string, const std::string &spendkey_string="")
Definition: wallet.cpp:581
static void setLogCategories(const std::string &categories)
#define AUTO_VAL_INIT(v)
Definition: misc_language.h:53
uint64_t networkDifficulty() override
returns current network difficulty
POD_CLASS hash
Definition: hash.h:50
const char * address
Definition: multisig.cpp:37
void setSubaddressLookahead(uint32_t major, uint32_t minor) override
setSubaddressLookahead - set size of subaddress lookahead
Definition: wallet.cpp:991
void mlog_set_log_level(int level)
Definition: mlog.cpp:282
Wallet * createWallet(const std::string &path, const std::string &password, const std::string &language, NetworkType nettype, uint64_t kdf_rounds=1) override
Creates new wallet.
bool connected(uint32_t *version=NULL) override
returns whether the daemon can be reached, and its version number
std::string errorString() const override
returns verbose error string regarding last error;
Interface for wallet operations. TODO: check if /include/IWallet.h is still actual.
Definition: wallet2_api.h:430
int vercmp(const char *v0, const char *v1)
Definition: util.cpp:915