Electroneum
Loading...
Searching...
No Matches
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
47namespace epee {
48 unsigned int g_test_dbg_lock_sleep = 0;
49}
50
51namespace Electroneum {
52
53Wallet *WalletManagerImpl::createWallet(const std::string &path, const std::string &password,
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
61Wallet *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
75Wallet *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
154bool 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
168bool WalletManagerImpl::walletExists(const std::string &path)
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
179bool 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
184bool 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
192std::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
315bool 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
340std::string WalletManagerImpl::resolveOpenAlias(const std::string &address, bool &dnssec_valid) const
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
348std::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
358 std::string version, hash;
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
392void WalletManagerFactory::setLogCategories(const std::string &categories)
393{
394 mlog_set_log(categories.c_str());
395}
396
397
398
399}
400
401namespace Bitelectroneum = Electroneum;
uint8_t version
virtual AddressBook * addressBook() override
Definition wallet.cpp:1679
bool open(const std::string &path, const std::string &password)
Definition wallet.cpp:699
bool recover(const std::string &path, const std::string &password, const std::string &seed)
Definition wallet.cpp:730
void setSubaddressLookahead(uint32_t major, uint32_t minor) override
setSubaddressLookahead - set size of subaddress lookahead
Definition wallet.cpp:991
void setRefreshFromBlockHeight(uint64_t refresh_from_block_height) override
setRefreshFromBlockHeight - start refresh from block height on recover
Definition wallet.cpp:976
std::string errorString() const override
in case error status, returns error string
Definition wallet.cpp:814
uint64_t estimateBlockChainHeight() const override
estimateBlockChainHeight - returns estimate blockchain height. More accurate than approximateBlockCha...
Definition wallet.cpp:1018
virtual void setListener(WalletListener *l) override
Definition wallet.cpp:1694
bool recoverFromDevice(const std::string &path, const std::string &password, const std::string &device_name)
Definition wallet.cpp:677
bool close(bool store=true)
Definition wallet.cpp:762
bool create(const std::string &path, const std::string &password, const std::string &language)
Definition wallet.cpp:469
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
Wallet * openWallet(const std::string &path, const std::string &password, NetworkType nettype, uint64_t kdf_rounds=1, WalletListener *listener=nullptr) override
Opens existing wallet.
double miningHashRate() override
returns current mining hash rate (0 if not mining)
void setDaemonAddress(const std::string &address) override
set the daemon address (hostname and port)
virtual bool closeWallet(Wallet *wallet, bool store=true) override
Closes wallet. In case operation succeeded, wallet object deleted. in case operation failed,...
std::string errorString() const override
returns verbose error string regarding last error;
bool connected(uint32_t *version=NULL) override
returns whether the daemon can be reached, and its version number
uint64_t blockchainTargetHeight() override
returns current blockchain target height
std::vector< std::string > findWallets(const std::string &path) override
findWallets - searches for the wallet files by given path name recursively
bool isMining() override
returns true iff mining
uint64_t blockTarget() override
returns current block target
std::string resolveOpenAlias(const std::string &address, bool &dnssec_valid) const override
resolves an OpenAlias address to a electroneum address
bool walletExists(const std::string &path) override
TODO: delme walletExists - check if the given filename is the wallet.
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
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
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
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.
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
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.
uint64_t blockchainHeight() override
returns current blockchain height
uint64_t networkDifficulty() override
returns current network difficulty
bool stopMining() override
stops mining
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)
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
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
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
#define CORE_RPC_STATUS_OK
#define AUTO_VAL_INIT(v)
#define LOG_PRINT_L3(x)
#define MDEBUG(x)
Definition misc_log_ex.h:76
void mlog_set_log(const char *log)
Definition mlog.cpp:288
void mlog_set_log_level(int level)
Definition mlog.cpp:282
#define MGINFO(x)
Definition misc_log_ex.h:80
http_simple_client_template< blocked_mode_client > http_simple_client
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")
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
unsigned int g_test_dbg_lock_sleep
device & get_device(const std::string &device_descriptor)
Definition device.cpp:95
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
int vercmp(const char *v0, const char *v1)
Definition util.cpp:915
boost::optional< std::pair< uint32_t, uint32_t > > parse_subaddress_lookahead(const std::string &str)
Definition util.cpp:977
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 check_updates(const std::string &software, const std::string &buildtag, std::string &version, std::string &hash)
Definition updates.cpp:41
unsigned int uint32_t
Definition stdint.h:126
unsigned __int64 uint64_t
Definition stdint.h:136
virtual void refresh()=0
Interface for wallet operations. TODO: check if /include/IWallet.h is still actual.
virtual void onSetWallet(Wallet *wallet)
If the listener is created before the wallet this enables to set created wallet object.
static WalletManager * getWalletManager()
static void setLogCategories(const std::string &categories)
WalletManager - provides functions to manage wallets.
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
epee::misc_utils::struct_init< response_t > response
epee::misc_utils::struct_init< request_t > request
epee::misc_utils::struct_init< request_t > request
epee::misc_utils::struct_init< response_t > response
epee::misc_utils::struct_init< request_t > request
epee::misc_utils::struct_init< response_t > response
epee::misc_utils::struct_init< response_t > response
epee::misc_utils::struct_init< request_t > request
epee::serialization::storage_entry id
const char * address
Definition multisig.cpp:37
const char *const ELECTRONEUM_VERSION