Electroneum
wallet.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.h"
34 #include "pending_transaction.h"
35 #include "unsigned_transaction.h"
36 #include "transaction_history.h"
37 #include "address_book.h"
38 #include "subaddress.h"
39 #include "subaddress_account.h"
40 #include "common_defines.h"
41 #include "common/util.h"
42 
44 #include "mnemonics/english.h"
45 #include <boost/format.hpp>
46 #include <sstream>
47 #include <unordered_map>
48 #include <string>
49 
50 #ifdef WIN32
51 #include <boost/locale.hpp>
52 #include <boost/filesystem.hpp>
53 #endif
54 
55 using namespace std;
56 using namespace cryptonote;
57 
58 #undef ELECTRONEUM_DEFAULT_LOG_CATEGORY
59 #define ELECTRONEUM_DEFAULT_LOG_CATEGORY "WalletAPI"
60 
61 namespace Electroneum {
62 
63 namespace {
64  // copy-pasted from simplewallet
65  static const size_t DEFAULT_MIXIN = DEFAULT_MIX;
66  static const int DEFAULT_REFRESH_INTERVAL_MILLIS = 1000 * 10;
67  // limit maximum refresh interval as one minute
68  static const int MAX_REFRESH_INTERVAL_MILLIS = 1000 * 60 * 1;
69  // Default refresh interval when connected to remote node
70  static const int DEFAULT_REMOTE_NODE_REFRESH_INTERVAL_MILLIS = 1000 * 10;
71  // Connection timeout 30 sec
72  static const int DEFAULT_CONNECTION_TIMEOUT_MILLIS = 1000 * 30;
73 
74  std::string get_default_ringdb_path(cryptonote::network_type nettype)
75  {
76  boost::filesystem::path dir = tools::get_default_data_dir();
77  // remove .electroneum, replace with .shared-ringdb
78  dir = dir.remove_filename();
79  dir /= ".shared-ringdb";
80  if (nettype == cryptonote::TESTNET)
81  dir /= "testnet";
82  else if (nettype == cryptonote::STAGENET)
83  dir /= "stagenet";
84  return dir.string();
85  }
86 
87  void checkMultisigWalletReady(const tools::wallet2* wallet) {
88  if (!wallet) {
89  throw runtime_error("Wallet is not initialized yet");
90  }
91 
92  bool ready;
93  if (!wallet->multisig(&ready)) {
94  throw runtime_error("Wallet is not multisig");
95  }
96 
97  if (!ready) {
98  throw runtime_error("Multisig wallet is not finalized yet");
99  }
100  }
101  void checkMultisigWalletReady(const std::unique_ptr<tools::wallet2> &wallet) {
102  return checkMultisigWalletReady(wallet.get());
103  }
104 
105  void checkMultisigWalletNotReady(const tools::wallet2* wallet) {
106  if (!wallet) {
107  throw runtime_error("Wallet is not initialized yet");
108  }
109 
110  bool ready;
111  if (!wallet->multisig(&ready)) {
112  throw runtime_error("Wallet is not multisig");
113  }
114 
115  if (ready) {
116  throw runtime_error("Multisig wallet is already finalized");
117  }
118  }
119  void checkMultisigWalletNotReady(const std::unique_ptr<tools::wallet2> &wallet) {
120  return checkMultisigWalletNotReady(wallet.get());
121  }
122 }
123 
125 {
126 
128  : m_listener(nullptr)
129  , m_wallet(wallet)
130  {
131 
132  }
133 
135  {
136 
137  }
138 
139  void setListener(WalletListener * listener)
140  {
141  m_listener = listener;
142  }
143 
145  {
146  return m_listener;
147  }
148 
150  {
151  // Don't flood the GUI with signals. On fast refresh - send signal every 1000th block
152  // get_refresh_from_block_height() returns the blockheight from when the wallet was
153  // created or the restore height specified when wallet was recovered
154  if(height >= m_wallet->m_wallet->get_refresh_from_block_height() || height % 1000 == 0) {
155  // LOG_PRINT_L3(__FUNCTION__ << ": new block. height: " << height);
156  if (m_listener) {
157  m_listener->newBlock(height);
158  }
159  }
160  }
161 
162  virtual void on_etn_received(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& tx, uint64_t amount, const cryptonote::subaddress_index& subaddr_index, uint64_t unlock_time)
163  {
164 
166 
167  LOG_PRINT_L3(__FUNCTION__ << ": ETN received. height: " << height
168  << ", tx: " << tx_hash
169  << ", amount: " << print_etn(amount)
170  << ", idx: " << subaddr_index);
171  // do not signal on received tx if wallet is not syncronized completely
172  if (m_listener && m_wallet->synchronized()) {
173  m_listener->etnReceived(tx_hash, amount);
174  m_listener->updated();
175  }
176  }
177 
179  {
180 
182 
183  LOG_PRINT_L3(__FUNCTION__ << ": unconfirmed ETN received. height: " << height
184  << ", tx: " << tx_hash
185  << ", amount: " << print_etn(amount)
186  << ", idx: " << subaddr_index);
187  // do not signal on received tx if wallet is not syncronized completely
188  if (m_listener && m_wallet->synchronized()) {
189  m_listener->unconfirmedETNReceived(tx_hash, amount);
190  m_listener->updated();
191  }
192  }
193 
194  virtual void on_etn_spent(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& in_tx,
195  uint64_t amount, const cryptonote::transaction& spend_tx, const cryptonote::subaddress_index& subaddr_index)
196  {
197  // TODO;
199  LOG_PRINT_L3(__FUNCTION__ << ": ETN spent. height: " << height
200  << ", tx: " << tx_hash
201  << ", amount: " << print_etn(amount)
202  << ", idx: " << subaddr_index);
203  // do not signal on sent tx if wallet is not syncronized completely
204  if (m_listener && m_wallet->synchronized()) {
205  m_listener->etnSpent(tx_hash, amount);
206  m_listener->updated();
207  }
208  }
209 
211  {
212  // TODO;
213  }
214 
215  // Light wallet callbacks
217  {
218  if (m_listener) {
219  m_listener->newBlock(height);
220  }
221  }
222 
223  virtual void on_lw_etn_received(uint64_t height, const crypto::hash &txid, uint64_t amount)
224  {
225  if (m_listener) {
227  m_listener->etnReceived(tx_hash, amount);
228  }
229  }
230 
232  {
233  if (m_listener) {
235  m_listener->unconfirmedETNReceived(tx_hash, amount);
236  }
237  }
238 
239  virtual void on_lw_etn_spent(uint64_t height, const crypto::hash &txid, uint64_t amount)
240  {
241  if (m_listener) {
243  m_listener->etnSpent(tx_hash, amount);
244  }
245  }
246 
248  {
249  if (m_listener) {
250  m_listener->onDeviceButtonRequest(code);
251  }
252  }
253 
255  {
256  if (m_listener) {
257  m_listener->onDeviceButtonPressed();
258  }
259  }
260 
261  virtual boost::optional<epee::wipeable_string> on_device_pin_request()
262  {
263  if (m_listener) {
264  auto pin = m_listener->onDevicePinRequest();
265  if (pin){
266  return boost::make_optional(epee::wipeable_string((*pin).data(), (*pin).size()));
267  }
268  }
269  return boost::none;
270  }
271 
272  virtual boost::optional<epee::wipeable_string> on_device_passphrase_request(bool on_device)
273  {
274  if (m_listener) {
275  auto passphrase = m_listener->onDevicePassphraseRequest(on_device);
276  if (!on_device && passphrase) {
277  return boost::make_optional(epee::wipeable_string((*passphrase).data(), (*passphrase).size()));
278  }
279  }
280  return boost::none;
281  }
282 
283  virtual void on_device_progress(const hw::device_progress & event)
284  {
285  if (m_listener) {
286  m_listener->onDeviceProgress(DeviceProgress(event.progress(), event.indeterminate()));
287  }
288  }
289 
292 };
293 
294 Wallet::~Wallet() {}
295 
296 WalletListener::~WalletListener() {}
297 
298 
299 string Wallet::displayAmount(uint64_t amount)
300 {
301  return cryptonote::print_etn(amount);
302 }
303 
304 uint64_t Wallet::amountFromString(const string &amount)
305 {
306  uint64_t result = 0;
307  cryptonote::parse_amount(result, amount);
308  return result;
309 }
310 
311 uint64_t Wallet::amountFromDouble(double amount)
312 {
313  std::stringstream ss;
314  ss << std::fixed << std::setprecision(CRYPTONOTE_DISPLAY_DECIMAL_POINT) << amount;
315  return amountFromString(ss.str());
316 }
317 
318 std::string Wallet::genPaymentId()
319 {
320  crypto::hash8 payment_id = crypto::rand<crypto::hash8>();
321  return epee::string_tools::pod_to_hex(payment_id);
322 
323 }
324 
325 bool Wallet::paymentIdValid(const string &paiment_id)
326 {
327  crypto::hash8 pid8;
328  if (tools::wallet2::parse_short_payment_id(paiment_id, pid8))
329  return true;
330  crypto::hash pid;
331  if (tools::wallet2::parse_long_payment_id(paiment_id, pid))
332  return true;
333  return false;
334 }
335 
336 bool Wallet::addressValid(const std::string &str, NetworkType nettype)
337 {
339  return get_account_address_from_str(info, static_cast<cryptonote::network_type>(nettype), str);
340 }
341 
342 bool Wallet::keyValid(const std::string &secret_key_string, const std::string &address_string, bool isViewKey, NetworkType nettype, std::string &error)
343 {
345  if(!get_account_address_from_str(info, static_cast<cryptonote::network_type>(nettype), address_string)) {
346  error = tr("Failed to parse address");
347  return false;
348  }
349 
350  cryptonote::blobdata key_data;
351  if(!epee::string_tools::parse_hexstr_to_binbuff(secret_key_string, key_data) || key_data.size() != sizeof(crypto::secret_key))
352  {
353  error = tr("Failed to parse key");
354  return false;
355  }
356  crypto::secret_key key = *reinterpret_cast<const crypto::secret_key*>(key_data.data());
357 
358  // check the key match the given address
359  crypto::public_key pkey;
361  error = tr("failed to verify key");
362  return false;
363  }
364  bool matchAddress = false;
365  if(isViewKey)
366  matchAddress = info.address.m_view_public_key == pkey;
367  else
368  matchAddress = info.address.m_spend_public_key == pkey;
369 
370  if(!matchAddress) {
371  error = tr("key does not match address");
372  return false;
373  }
374 
375  return true;
376 }
377 
378 std::string Wallet::paymentIdFromAddress(const std::string &str, NetworkType nettype)
379 {
381  if (!get_account_address_from_str(info, static_cast<cryptonote::network_type>(nettype), str))
382  return "";
383  if (!info.has_payment_id)
384  return "";
385  return epee::string_tools::pod_to_hex(info.payment_id);
386 }
387 
388 uint64_t Wallet::maximumAllowedAmount()
389 {
390  return std::numeric_limits<uint64_t>::max();
391 }
392 
393 void Wallet::init(const char *argv0, const char *default_log_base_name, const std::string &log_path, bool console) {
394 #ifdef WIN32
395  // Activate UTF-8 support for Boost filesystem classes on Windows
396  std::locale::global(boost::locale::generator().generate(""));
397  boost::filesystem::path::imbue(std::locale());
398 #endif
400  mlog_configure(log_path.empty() ? mlog_get_default_log_path(default_log_base_name) : log_path.c_str(), console);
401 }
402 
403 void Wallet::debug(const std::string &category, const std::string &str) {
404  MCDEBUG(category.empty() ? ELECTRONEUM_DEFAULT_LOG_CATEGORY : category.c_str(), str);
405 }
406 
407 void Wallet::info(const std::string &category, const std::string &str) {
408  MCINFO(category.empty() ? ELECTRONEUM_DEFAULT_LOG_CATEGORY : category.c_str(), str);
409 }
410 
411 void Wallet::warning(const std::string &category, const std::string &str) {
412  MCWARNING(category.empty() ? ELECTRONEUM_DEFAULT_LOG_CATEGORY : category.c_str(), str);
413 }
414 
415 void Wallet::error(const std::string &category, const std::string &str) {
416  MCERROR(category.empty() ? ELECTRONEUM_DEFAULT_LOG_CATEGORY : category.c_str(), str);
417 }
418 
420 WalletImpl::WalletImpl(NetworkType nettype, uint64_t kdf_rounds)
421  :m_wallet(nullptr)
422  , m_status(Wallet::Status_Ok)
423  , m_wallet2Callback(nullptr)
424  , m_recoveringFromSeed(false)
425  , m_recoveringFromDevice(false)
426  , m_synchronized(false)
427  , m_rebuildWalletCache(false)
428  , m_is_connected(false)
429  , m_refreshShouldRescan(false)
430 {
431  m_wallet.reset(new tools::wallet2(static_cast<cryptonote::network_type>(nettype), kdf_rounds, true));
432  m_history.reset(new TransactionHistoryImpl(this));
433  m_wallet2Callback.reset(new Wallet2CallbackImpl(this));
434  m_wallet->callback(m_wallet2Callback.get());
435  m_refreshThreadDone = false;
436  m_refreshEnabled = false;
437  m_addressBook.reset(new AddressBookImpl(this));
438  m_subaddress.reset(new SubaddressImpl(this));
439  m_subaddressAccount.reset(new SubaddressAccountImpl(this));
440 
441 
442  m_refreshIntervalMillis = DEFAULT_REFRESH_INTERVAL_MILLIS;
443 
444  m_refreshThread = boost::thread([this] () {
445  this->refreshThreadFunc();
446  });
447 
448 }
449 
451 {
452 
453  LOG_PRINT_L1(__FUNCTION__);
454  m_wallet->callback(NULL);
455  // Pause refresh thread - prevents refresh from starting again
456  pauseRefresh();
457  // Close wallet - stores cache and stops ongoing refresh operation
458  close(false); // do not store wallet as part of the closing activities
459  // Stop refresh thread
460  stopRefresh();
461 
462  if (m_wallet2Callback->getListener()) {
463  m_wallet2Callback->getListener()->onSetWallet(nullptr);
464  }
465 
466  LOG_PRINT_L1(__FUNCTION__ << " finished");
467 }
468 
469 bool WalletImpl::create(const std::string &path, const std::string &password, const std::string &language)
470 {
471 
472  clearStatus();
473  m_recoveringFromSeed = false;
474  m_recoveringFromDevice = false;
475  bool keys_file_exists;
476  bool wallet_file_exists;
477  tools::wallet2::wallet_exists(path, keys_file_exists, wallet_file_exists);
478  LOG_PRINT_L3("wallet_path: " << path << "");
479  LOG_PRINT_L3("keys_file_exists: " << std::boolalpha << keys_file_exists << std::noboolalpha
480  << " wallet_file_exists: " << std::boolalpha << wallet_file_exists << std::noboolalpha);
481 
482 
483  // add logic to error out if new wallet requested but named wallet file exists
484  if (keys_file_exists || wallet_file_exists) {
485  std::string error = "attempting to generate or restore wallet, but specified file(s) exist. Exiting to not risk overwriting.";
486  LOG_ERROR(error);
487  setStatusCritical(error);
488  return false;
489  }
490  // TODO: validate language
491  m_wallet->set_seed_language(language);
492  crypto::secret_key recovery_val, secret_key;
493  try {
494  recovery_val = m_wallet->generate(path, password, secret_key, false, false);
495  m_password = password;
496  clearStatus();
497  } catch (const std::exception &e) {
498  LOG_ERROR("Error creating wallet: " << e.what());
499  setStatusCritical(e.what());
500  return false;
501  }
502 
503  return true;
504 }
505 
506 bool WalletImpl::createWatchOnly(const std::string &path, const std::string &password, const std::string &language) const
507 {
508  clearStatus();
509  std::unique_ptr<tools::wallet2> view_wallet(new tools::wallet2(m_wallet->nettype()));
510 
511  // Store same refresh height as original wallet
512  view_wallet->set_refresh_from_block_height(m_wallet->get_refresh_from_block_height());
513 
514  bool keys_file_exists;
515  bool wallet_file_exists;
516  tools::wallet2::wallet_exists(path, keys_file_exists, wallet_file_exists);
517  LOG_PRINT_L3("wallet_path: " << path << "");
518  LOG_PRINT_L3("keys_file_exists: " << std::boolalpha << keys_file_exists << std::noboolalpha
519  << " wallet_file_exists: " << std::boolalpha << wallet_file_exists << std::noboolalpha);
520 
521  // add logic to error out if new wallet requested but named wallet file exists
522  if (keys_file_exists || wallet_file_exists) {
523  std::string error = "attempting to generate view only wallet, but specified file(s) exist. Exiting to not risk overwriting.";
524  LOG_ERROR(error);
525  setStatusError(error);
526  return false;
527  }
528  // TODO: validate language
529  view_wallet->set_seed_language(language);
530 
531  const crypto::secret_key viewkey = m_wallet->get_account().get_keys().m_view_secret_key;
532  const cryptonote::account_public_address address = m_wallet->get_account().get_keys().m_account_address;
533 
534  try {
535  // Generate view only wallet
536  view_wallet->generate(path, password, address, viewkey);
537 
538  // Export/Import outputs
539  auto outputs = m_wallet->export_outputs();
540  view_wallet->import_outputs(outputs);
541 
542  // Copy scanned blockchain
543  auto bc = m_wallet->export_blockchain();
544  view_wallet->import_blockchain(bc);
545 
546  // copy payments
547  auto payments = m_wallet->export_payments();
548  view_wallet->import_payments(payments);
549 
550  // copy confirmed outgoing payments
551  std::list<std::pair<crypto::hash, tools::wallet2::confirmed_transfer_details>> out_payments;
552  m_wallet->get_payments_out(out_payments, 0);
553  view_wallet->import_payments_out(out_payments);
554 
555  // Export/Import key images
556  // We already know the spent status from the outputs we exported, thus no need to check them again
557  auto key_images = m_wallet->export_key_images();
558  uint64_t spent = 0;
559  uint64_t unspent = 0;
560  view_wallet->import_key_images(key_images.second, key_images.first, spent, unspent, false);
561  clearStatus();
562  } catch (const std::exception &e) {
563  LOG_ERROR("Error creating view only wallet: " << e.what());
564  setStatusError(e.what());
565  return false;
566  }
567  // Store wallet
568  view_wallet->store();
569  return true;
570 }
571 
573  const std::string &language,
574  const std::string &address_string,
575  const std::string &viewkey_string,
576  const std::string &spendkey_string)
577 {
578  return recoverFromKeysWithPassword(path, "", language, address_string, viewkey_string, spendkey_string);
579 }
580 
582  const std::string &password,
583  const std::string &language,
584  const std::string &address_string,
585  const std::string &viewkey_string,
586  const std::string &spendkey_string)
587 {
589  if(!get_account_address_from_str(info, m_wallet->nettype(), address_string))
590  {
591  setStatusError(tr("failed to parse address"));
592  return false;
593  }
594 
595  // parse optional spend key
597  bool has_spendkey = false;
598  if (!spendkey_string.empty()) {
599  cryptonote::blobdata spendkey_data;
600  if(!epee::string_tools::parse_hexstr_to_binbuff(spendkey_string, spendkey_data) || spendkey_data.size() != sizeof(crypto::secret_key))
601  {
602  setStatusError(tr("failed to parse secret spend key"));
603  return false;
604  }
605  has_spendkey = true;
606  spendkey = *reinterpret_cast<const crypto::secret_key*>(spendkey_data.data());
607  }
608 
609  // parse view secret key
610  bool has_viewkey = true;
611  crypto::secret_key viewkey;
612  if (viewkey_string.empty()) {
613  if(has_spendkey) {
614  has_viewkey = false;
615  }
616  else {
617  setStatusError(tr("Neither view key nor spend key supplied, cancelled"));
618  return false;
619  }
620  }
621  if(has_viewkey) {
622  cryptonote::blobdata viewkey_data;
623  if(!epee::string_tools::parse_hexstr_to_binbuff(viewkey_string, viewkey_data) || viewkey_data.size() != sizeof(crypto::secret_key))
624  {
625  setStatusError(tr("failed to parse secret view key"));
626  return false;
627  }
628  viewkey = *reinterpret_cast<const crypto::secret_key*>(viewkey_data.data());
629  }
630  // check the spend and view keys match the given address
631  crypto::public_key pkey;
632  if(has_spendkey) {
634  setStatusError(tr("failed to verify secret spend key"));
635  return false;
636  }
637  if (info.address.m_spend_public_key != pkey) {
638  setStatusError(tr("spend key does not match address"));
639  return false;
640  }
641  }
642  if(has_viewkey) {
643  if (!crypto::secret_key_to_public_key(viewkey, pkey)) {
644  setStatusError(tr("failed to verify secret view key"));
645  return false;
646  }
647  if (info.address.m_view_public_key != pkey) {
648  setStatusError(tr("view key does not match address"));
649  return false;
650  }
651  }
652 
653  try
654  {
655  if (has_spendkey && has_viewkey) {
656  m_wallet->generate(path, password, info.address, spendkey, viewkey);
657  LOG_PRINT_L1("Generated new wallet from spend key and view key");
658  }
659  if(!has_spendkey && has_viewkey) {
660  m_wallet->generate(path, password, info.address, viewkey);
661  LOG_PRINT_L1("Generated new view only wallet from keys");
662  }
663  if(has_spendkey && !has_viewkey) {
664  m_wallet->generate(path, password, spendkey, true, false);
665  setSeedLanguage(language);
666  LOG_PRINT_L1("Generated deterministic wallet from spend key with seed language: " + language);
667  }
668 
669  }
670  catch (const std::exception& e) {
671  setStatusError(string(tr("failed to generate new wallet: ")) + e.what());
672  return false;
673  }
674  return true;
675 }
676 
677 bool WalletImpl::recoverFromDevice(const std::string &path, const std::string &password, const std::string &device_name)
678 {
679  clearStatus();
680  m_recoveringFromSeed = false;
681  m_recoveringFromDevice = true;
682  try
683  {
684  m_wallet->restore(path, password, device_name);
685  LOG_PRINT_L1("Generated new wallet from device: " + device_name);
686  }
687  catch (const std::exception& e) {
688  setStatusError(string(tr("failed to generate new wallet: ")) + e.what());
689  return false;
690  }
691  return true;
692 }
693 
695 {
696  return static_cast<Wallet::Device>(m_wallet->get_device_type());
697 }
698 
699 bool WalletImpl::open(const std::string &path, const std::string &password)
700 {
701  clearStatus();
702  m_recoveringFromSeed = false;
703  m_recoveringFromDevice = false;
704  try {
705  // TODO: handle "deprecated"
706  // Check if wallet cache exists
707  bool keys_file_exists;
708  bool wallet_file_exists;
709  tools::wallet2::wallet_exists(path, keys_file_exists, wallet_file_exists);
710  if(!wallet_file_exists){
711  // Rebuilding wallet cache, using refresh height from .keys file
712  m_rebuildWalletCache = true;
713  }
714  m_wallet->set_ring_database(get_default_ringdb_path(m_wallet->nettype()));
715  m_wallet->load(path, password);
716 
717  m_password = password;
718  } catch (const std::exception &e) {
719  LOG_ERROR("Error opening wallet: " << e.what());
720  setStatusCritical(e.what());
721  }
722  return status() == Status_Ok;
723 }
724 
725 bool WalletImpl::recover(const std::string &path, const std::string &seed)
726 {
727  return recover(path, "", seed);
728 }
729 
730 bool WalletImpl::recover(const std::string &path, const std::string &password, const std::string &seed)
731 {
732  clearStatus();
733  m_errorString.clear();
734  if (seed.empty()) {
735  LOG_ERROR("Electrum seed is empty");
736  setStatusError(tr("Electrum seed is empty"));
737  return false;
738  }
739 
740  m_recoveringFromSeed = true;
741  m_recoveringFromDevice = false;
742  crypto::secret_key recovery_key;
743  std::string old_language;
744  if (!crypto::ElectrumWords::words_to_bytes(seed, recovery_key, old_language)) {
745  setStatusError(tr("Electrum-style word list failed verification"));
746  return false;
747  }
748 
749  if (old_language == crypto::ElectrumWords::old_language_name)
750  old_language = Language::English().get_language_name();
751 
752  try {
753  m_wallet->set_seed_language(old_language);
754  m_wallet->generate(path, password, recovery_key, true, false);
755 
756  } catch (const std::exception &e) {
757  setStatusCritical(e.what());
758  }
759  return status() == Status_Ok;
760 }
761 
762 bool WalletImpl::close(bool store)
763 {
764 
765  bool result = false;
766  LOG_PRINT_L1("closing wallet...");
767  try {
768  if (store) {
769  // Do not store wallet with invalid status
770  // Status Critical refers to errors on opening or creating wallets.
771  if (status() != Status_Critical)
772  m_wallet->store();
773  else
774  LOG_ERROR("Status_Critical - not saving wallet");
775  LOG_PRINT_L1("wallet::store done");
776  }
777  LOG_PRINT_L1("Calling wallet::stop...");
778  m_wallet->stop();
779  LOG_PRINT_L1("wallet::stop done");
780  m_wallet->deinit();
781  result = true;
782  clearStatus();
783  } catch (const std::exception &e) {
784  setStatusCritical(e.what());
785  LOG_ERROR("Error closing wallet: " << e.what());
786  }
787  return result;
788 }
789 
791 {
793  if (m_wallet)
794  m_wallet->get_seed(seed);
795  return std::string(seed.data(), seed.size()); // TODO
796 }
797 
799 {
800  return m_wallet->get_seed_language();
801 }
802 
804 {
805  m_wallet->set_seed_language(arg);
806 }
807 
809 {
810  boost::lock_guard<boost::mutex> l(m_statusMutex);
811  return m_status;
812 }
813 
815 {
816  boost::lock_guard<boost::mutex> l(m_statusMutex);
817  return m_errorString;
818 }
819 
820 void WalletImpl::statusWithErrorString(int& status, std::string& errorString) const {
821  boost::lock_guard<boost::mutex> l(m_statusMutex);
822  status = m_status;
823  errorString = m_errorString;
824 }
825 
827 {
828  clearStatus();
829  try {
830  m_wallet->change_password(m_wallet->get_wallet_file(), m_password, password);
831  m_password = password;
832  } catch (const std::exception &e) {
833  setStatusError(e.what());
834  }
835  return status() == Status_Ok;
836 }
837 
839 {
840  clearStatus();
841  try {
842  m_wallet->get_account().get_device().set_pin(epee::wipeable_string(pin.data(), pin.size()));
843  } catch (const std::exception &e) {
844  setStatusError(e.what());
845  }
846  return status() == Status_Ok;
847 }
848 
850 {
851  clearStatus();
852  try {
853  m_wallet->get_account().get_device().set_passphrase(epee::wipeable_string(passphrase.data(), passphrase.size()));
854  } catch (const std::exception &e) {
855  setStatusError(e.what());
856  }
857  return status() == Status_Ok;
858 }
859 
860 std::string WalletImpl::address(uint32_t accountIndex, uint32_t addressIndex) const
861 {
862  return m_wallet->get_subaddress_as_str({accountIndex, addressIndex});
863 }
864 
866 {
867  crypto::hash8 pid;
868  if (!tools::wallet2::parse_short_payment_id(payment_id, pid)) {
869  return "";
870  }
871  return m_wallet->get_integrated_address_as_str(pid);
872 }
873 
875 {
876  return epee::string_tools::pod_to_hex(m_wallet->get_account().get_keys().m_view_secret_key);
877 }
878 
880 {
881  return epee::string_tools::pod_to_hex(m_wallet->get_account().get_keys().m_account_address.m_view_public_key);
882 }
883 
885 {
886  return epee::string_tools::pod_to_hex(m_wallet->get_account().get_keys().m_spend_secret_key);
887 }
888 
890 {
891  return epee::string_tools::pod_to_hex(m_wallet->get_account().get_keys().m_account_address.m_spend_public_key);
892 }
893 
895 {
896  try {
897  crypto::public_key signer = m_wallet->get_multisig_signer_public_key();
898  return epee::string_tools::pod_to_hex(signer);
899  } catch (const std::exception&) {
900  return "";
901  }
902 }
903 
905 {
906  return m_wallet->path();
907 }
908 
910 {
911  clearStatus();
912  try {
913  if (path.empty()) {
914  m_wallet->store();
915  } else {
916  m_wallet->store_to(path, m_password);
917  }
918  } catch (const std::exception &e) {
919  LOG_ERROR("Error saving wallet: " << e.what());
920  setStatusError(e.what());
921  return false;
922  }
923 
924  return true;
925 }
926 
927 string WalletImpl::filename() const
928 {
929  return m_wallet->get_wallet_file();
930 }
931 
933 {
934  return m_wallet->get_keys_file();
935 }
936 
937 bool WalletImpl::init(const std::string &daemon_address, uint64_t upper_transaction_size_limit, const std::string &daemon_username, const std::string &daemon_password, bool use_ssl, bool lightWallet)
938 {
939  clearStatus();
940  m_wallet->set_light_wallet(lightWallet);
941  if(daemon_username != "")
942  m_daemon_login.emplace(daemon_username, daemon_password);
943  return doInit(daemon_address, upper_transaction_size_limit, use_ssl);
944 }
945 
946 bool WalletImpl::lightWalletLogin(bool &isNewWallet) const
947 {
948  return m_wallet->light_wallet_login(isNewWallet);
949 }
950 
951 bool WalletImpl::lightWalletImportWalletRequest(std::string &payment_id, uint64_t &fee, bool &new_request, bool &request_fulfilled, std::string &payment_address, std::string &status)
952 {
953  try
954  {
956  if(!m_wallet->light_wallet_import_wallet_request(response)){
957  setStatusError(tr("Failed to send import wallet request"));
958  return false;
959  }
960  fee = response.import_fee;
961  payment_id = response.payment_id;
962  new_request = response.new_request;
963  request_fulfilled = response.request_fulfilled;
964  payment_address = response.payment_address;
965  status = response.status;
966  }
967  catch (const std::exception &e)
968  {
969  LOG_ERROR("Error sending import wallet request: " << e.what());
970  setStatusError(e.what());
971  return false;
972  }
973  return true;
974 }
975 
976 void WalletImpl::setRefreshFromBlockHeight(uint64_t refresh_from_block_height)
977 {
978  m_wallet->set_refresh_from_block_height(refresh_from_block_height);
979 }
980 
981 void WalletImpl::setRecoveringFromSeed(bool recoveringFromSeed)
982 {
983  m_recoveringFromSeed = recoveringFromSeed;
984 }
985 
986 void WalletImpl::setRecoveringFromDevice(bool recoveringFromDevice)
987 {
988  m_recoveringFromDevice = recoveringFromDevice;
989 }
990 
992 {
993  m_wallet->set_subaddress_lookahead(major, minor);
994 }
995 
996 uint64_t WalletImpl::balance(uint32_t accountIndex, bool public_blockchain) const
997 {
998  return m_wallet->balance(accountIndex, public_blockchain);
999 }
1000 
1001 uint64_t WalletImpl::unlockedBalance(uint32_t accountIndex, bool public_blockchain) const
1002 {
1003  return m_wallet->unlocked_balance(accountIndex, public_blockchain);
1004 }
1005 
1007 {
1008  if(m_wallet->light_wallet()) {
1009  return m_wallet->get_light_wallet_scanned_block_height();
1010  }
1011  return m_wallet->get_blockchain_current_height();
1012 }
1014 {
1015  return m_wallet->get_approximate_blockchain_height();
1016 }
1017 
1019 {
1020  return m_wallet->estimate_blockchain_height();
1021 }
1022 
1024 {
1025  if(m_wallet->light_wallet()) {
1026  return m_wallet->get_light_wallet_scanned_block_height();
1027  }
1028  if (!m_is_connected)
1029  return 0;
1030  std::string err;
1031  uint64_t result = m_wallet->get_daemon_blockchain_height(err);
1032  if (!err.empty()) {
1033  LOG_ERROR(__FUNCTION__ << ": " << err);
1034  result = 0;
1035  setStatusError(err);
1036  } else {
1037  clearStatus();
1038  }
1039  return result;
1040 }
1041 
1043 {
1044  if(m_wallet->light_wallet()) {
1045  return m_wallet->get_light_wallet_blockchain_height();
1046  }
1047  if (!m_is_connected)
1048  return 0;
1049  std::string err;
1050  uint64_t result = m_wallet->get_daemon_blockchain_target_height(err);
1051  if (!err.empty()) {
1052  LOG_ERROR(__FUNCTION__ << ": " << err);
1053  result = 0;
1054  setStatusError(err);
1055  } else {
1056  clearStatus();
1057  }
1058  // Target height can be 0 when daemon is synced. Use blockchain height instead.
1059  if(result == 0)
1060  result = daemonBlockChainHeight();
1061  return result;
1062 }
1063 
1064 bool WalletImpl::daemonSynced() const
1065 {
1067  return false;
1070 }
1071 
1073 {
1074  return m_synchronized;
1075 }
1076 
1078 {
1079  clearStatus();
1080  //TODO: make doRefresh return bool to know whether the error occured during refresh or not
1081  //otherwise one may try, say, to send transaction, transfer fails and this method returns false
1082  doRefresh();
1083  return status() == Status_Ok;
1084 }
1085 
1087 {
1088  LOG_PRINT_L3(__FUNCTION__ << ": Refreshing asynchronously..");
1089  clearStatus();
1090  m_refreshCV.notify_one();
1091 }
1092 
1094 {
1095  clearStatus();
1096  m_refreshShouldRescan = true;
1097  doRefresh();
1098  return status() == Status_Ok;
1099 }
1100 
1102 {
1103  m_refreshShouldRescan = true;
1104  refreshAsync();
1105 }
1106 
1108 {
1109  if (millis > MAX_REFRESH_INTERVAL_MILLIS) {
1110  LOG_ERROR(__FUNCTION__<< ": invalid refresh interval " << millis
1111  << " ms, maximum allowed is " << MAX_REFRESH_INTERVAL_MILLIS << " ms");
1112  m_refreshIntervalMillis = MAX_REFRESH_INTERVAL_MILLIS;
1113  } else {
1114  m_refreshIntervalMillis = millis;
1115  }
1116 }
1117 
1119 {
1120  return m_refreshIntervalMillis;
1121 }
1122 
1124  clearStatus();
1126  if (!m_wallet->load_unsigned_tx(unsigned_filename, transaction->m_unsigned_tx_set)){
1127  setStatusError(tr("Failed to load unsigned transactions"));
1128  }
1129 
1130  // Check tx data and construct confirmation message
1131  std::string extra_message;
1132  if (!transaction->m_unsigned_tx_set.transfers.second.empty())
1133  extra_message = (boost::format("%u outputs to import. ") % (unsigned)transaction->m_unsigned_tx_set.transfers.second.size()).str();
1134  transaction->checkLoadedTx([&transaction](){return transaction->m_unsigned_tx_set.txes.size();}, [&transaction](size_t n)->const tools::wallet2::tx_construction_data&{return transaction->m_unsigned_tx_set.txes[n];}, extra_message);
1135  setStatus(transaction->status(), transaction->errorString());
1136 
1137  return transaction;
1138 }
1139 
1140 bool WalletImpl::submitTransaction(const string &fileName) {
1141  clearStatus();
1142  std::unique_ptr<PendingTransactionImpl> transaction(new PendingTransactionImpl(*this));
1143 
1144  bool r = m_wallet->load_tx(fileName, transaction->m_pending_tx);
1145  if (!r) {
1146  setStatus(Status_Ok, tr("Failed to load transaction from file"));
1147  return false;
1148  }
1149 
1150  if(!transaction->commit()) {
1151  setStatusError(transaction->m_errorString);
1152  return false;
1153  }
1154 
1155  return true;
1156 }
1157 
1158 bool WalletImpl::exportKeyImages(const string &filename)
1159 {
1160  if (m_wallet->watch_only())
1161  {
1162  setStatusError(tr("Wallet is view only"));
1163  return false;
1164  }
1165 
1166  try
1167  {
1168  if (!m_wallet->export_key_images(filename))
1169  {
1170  setStatusError(tr("failed to save file ") + filename);
1171  return false;
1172  }
1173  }
1174  catch (const std::exception &e)
1175  {
1176  LOG_ERROR("Error exporting key images: " << e.what());
1177  setStatusError(e.what());
1178  return false;
1179  }
1180  return true;
1181 }
1182 
1183 bool WalletImpl::importKeyImages(const string &filename)
1184 {
1185  if (!trustedDaemon()) {
1186  setStatusError(tr("Key images can only be imported with a trusted daemon"));
1187  return false;
1188  }
1189  try
1190  {
1191  uint64_t spent = 0, unspent = 0;
1192  uint64_t height = m_wallet->import_key_images(filename, spent, unspent);
1193  LOG_PRINT_L2("Signed key images imported to height " << height << ", "
1194  << print_etn(spent) << " spent, " << print_etn(unspent) << " unspent");
1195  }
1196  catch (const std::exception &e)
1197  {
1198  LOG_ERROR("Error exporting key images: " << e.what());
1199  setStatusError(string(tr("Failed to import key images: ")) + e.what());
1200  return false;
1201  }
1202 
1203  return true;
1204 }
1205 
1207 {
1208  m_wallet->add_subaddress_account(label);
1209 }
1211 {
1212  return m_wallet->get_num_subaddress_accounts();
1213 }
1214 size_t WalletImpl::numSubaddresses(uint32_t accountIndex) const
1215 {
1216  return m_wallet->get_num_subaddresses(accountIndex);
1217 }
1218 void WalletImpl::addSubaddress(uint32_t accountIndex, const std::string& label)
1219 {
1220  m_wallet->add_subaddress(accountIndex, label);
1221 }
1223 {
1224  try
1225  {
1226  return m_wallet->get_subaddress_label({accountIndex, addressIndex});
1227  }
1228  catch (const std::exception &e)
1229  {
1230  LOG_ERROR("Error getting subaddress label: " << e.what());
1231  setStatusError(string(tr("Failed to get subaddress label: ")) + e.what());
1232  return "";
1233  }
1234 }
1235 void WalletImpl::setSubaddressLabel(uint32_t accountIndex, uint32_t addressIndex, const std::string &label)
1236 {
1237  try
1238  {
1239  return m_wallet->set_subaddress_label({accountIndex, addressIndex}, label);
1240  }
1241  catch (const std::exception &e)
1242  {
1243  LOG_ERROR("Error setting subaddress label: " << e.what());
1244  setStatusError(string(tr("Failed to set subaddress label: ")) + e.what());
1245  }
1246 }
1247 
1250  state.isMultisig = m_wallet->multisig(&state.isReady, &state.threshold, &state.total);
1251 
1252  return state;
1253 }
1254 
1256  try {
1257  clearStatus();
1258  return m_wallet->get_multisig_info();
1259  } catch (const exception& e) {
1260  LOG_ERROR("Error on generating multisig info: " << e.what());
1261  setStatusError(string(tr("Failed to get multisig info: ")) + e.what());
1262  }
1263 
1264  return string();
1265 }
1266 
1267 string WalletImpl::makeMultisig(const vector<string>& info, uint32_t threshold) {
1268  try {
1269  clearStatus();
1270 
1271  if (m_wallet->multisig()) {
1272  throw runtime_error("Wallet is already multisig");
1273  }
1274 
1275  return m_wallet->make_multisig(epee::wipeable_string(m_password), info, threshold);
1276  } catch (const exception& e) {
1277  LOG_ERROR("Error on making multisig wallet: " << e.what());
1278  setStatusError(string(tr("Failed to make multisig: ")) + e.what());
1279  }
1280 
1281  return string();
1282 }
1283 
1284 std::string WalletImpl::exchangeMultisigKeys(const std::vector<std::string> &info) {
1285  try {
1286  clearStatus();
1287  checkMultisigWalletNotReady(m_wallet);
1288 
1289  return m_wallet->exchange_multisig_keys(epee::wipeable_string(m_password), info);
1290  } catch (const exception& e) {
1291  LOG_ERROR("Error on exchanging multisig keys: " << e.what());
1292  setStatusError(string(tr("Failed to make multisig: ")) + e.what());
1293  }
1294 
1295  return string();
1296 }
1297 
1298 bool WalletImpl::finalizeMultisig(const vector<string>& extraMultisigInfo) {
1299  try {
1300  clearStatus();
1301  checkMultisigWalletNotReady(m_wallet);
1302 
1303  if (m_wallet->finalize_multisig(epee::wipeable_string(m_password), extraMultisigInfo)) {
1304  return true;
1305  }
1306 
1307  setStatusError(tr("Failed to finalize multisig wallet creation"));
1308  } catch (const exception& e) {
1309  LOG_ERROR("Error on finalizing multisig wallet creation: " << e.what());
1310  setStatusError(string(tr("Failed to finalize multisig wallet creation: ")) + e.what());
1311  }
1312 
1313  return false;
1314 }
1315 
1316 bool WalletImpl::exportMultisigImages(string& images) {
1317  try {
1318  clearStatus();
1319  checkMultisigWalletReady(m_wallet);
1320 
1321  auto blob = m_wallet->export_multisig();
1323  return true;
1324  } catch (const exception& e) {
1325  LOG_ERROR("Error on exporting multisig images: " << e.what());
1326  setStatusError(string(tr("Failed to export multisig images: ")) + e.what());
1327  }
1328 
1329  return false;
1330 }
1331 
1332 size_t WalletImpl::importMultisigImages(const vector<string>& images) {
1333  try {
1334  clearStatus();
1335  checkMultisigWalletReady(m_wallet);
1336 
1337  std::vector<std::string> blobs;
1338  blobs.reserve(images.size());
1339 
1340  for (const auto& image: images) {
1341  std::string blob;
1342  if (!epee::string_tools::parse_hexstr_to_binbuff(image, blob)) {
1343  LOG_ERROR("Failed to parse imported multisig images");
1344  setStatusError(tr("Failed to parse imported multisig images"));
1345  return 0;
1346  }
1347 
1348  blobs.emplace_back(std::move(blob));
1349  }
1350 
1351  return m_wallet->import_multisig(blobs);
1352  } catch (const exception& e) {
1353  LOG_ERROR("Error on importing multisig images: " << e.what());
1354  setStatusError(string(tr("Failed to import multisig images: ")) + e.what());
1355  }
1356 
1357  return 0;
1358 }
1359 
1361  try {
1362  clearStatus();
1363  checkMultisigWalletReady(m_wallet);
1364 
1365  return m_wallet->has_multisig_partial_key_images();
1366  } catch (const exception& e) {
1367  LOG_ERROR("Error on checking for partial multisig key images: " << e.what());
1368  setStatusError(string(tr("Failed to check for partial multisig key images: ")) + e.what());
1369  }
1370 
1371  return false;
1372 }
1373 
1375  try {
1376  clearStatus();
1377  checkMultisigWalletReady(m_wallet);
1378 
1379  string binary;
1380  if (!epee::string_tools::parse_hexstr_to_binbuff(signData, binary)) {
1381  throw runtime_error("Failed to deserialize multisig transaction");
1382  }
1383 
1385  if (!m_wallet->load_multisig_tx(binary, txSet, {})) {
1386  throw runtime_error("couldn't parse multisig transaction data");
1387  }
1388 
1389  auto ptx = new PendingTransactionImpl(*this);
1390  ptx->m_pending_tx = txSet.m_ptx;
1391  ptx->m_signers = txSet.m_signers;
1392 
1393  return ptx;
1394  } catch (exception& e) {
1395  LOG_ERROR("Error on restoring multisig transaction: " << e.what());
1396  setStatusError(string(tr("Failed to restore multisig transaction: ")) + e.what());
1397  }
1398 
1399  return nullptr;
1400 }
1401 
1402 // TODO:
1403 // 1 - properly handle payment id (add another menthod with explicit 'payment_id' param)
1404 // 2 - check / design how "Transaction" can be single interface
1405 // (instead of few different data structures within wallet2 implementation:
1406 // - pending_tx;
1407 // - transfer_details;
1408 // - payment_details;
1409 // - unconfirmed_transfer_details;
1410 // - confirmed_transfer_details)
1411 
1412 PendingTransaction *WalletImpl::createTransaction(const string &dst_addr, const string &payment_id, optional<uint64_t> amount, uint32_t mixin_count,
1413  PendingTransaction::Priority priority, uint32_t subaddr_account, std::set<uint32_t> subaddr_indices)
1414 
1415 {
1416  clearStatus();
1417  // Pause refresh thread while creating transaction
1418  pauseRefresh();
1419 
1421 
1422  // indicates if dst_addr is integrated address (address + payment_id)
1423  // TODO: (https://bitcointalk.org/index.php?topic=753252.msg9985441#msg9985441)
1424  size_t fake_outs_count = mixin_count > 0 ? mixin_count : m_wallet->default_mixin();
1425  if (fake_outs_count == 0)
1426  fake_outs_count = DEFAULT_MIXIN;
1427  fake_outs_count = m_wallet->adjust_mixin(fake_outs_count);
1428 
1429  uint32_t adjusted_priority = m_wallet->adjust_priority(static_cast<uint32_t>(priority));
1430 
1432 
1433  do {
1434  if(!cryptonote::get_account_address_from_str(info, m_wallet->nettype(), dst_addr)) {
1435  // TODO: copy-paste 'if treating as an address fails, try as url' from simplewallet.cpp:1982
1436  setStatusError(tr("Invalid destination address"));
1437  break;
1438  }
1439 
1440 
1441  std::vector<uint8_t> extra;
1442  // if dst_addr is not an integrated address, parse payment_id
1443  if (!info.has_payment_id && !payment_id.empty()) {
1444  // copy-pasted from simplewallet.cpp:2212
1445  crypto::hash payment_id_long;
1446  bool r = tools::wallet2::parse_long_payment_id(payment_id, payment_id_long);
1447  if (r) {
1448  std::string extra_nonce;
1449  cryptonote::set_payment_id_to_tx_extra_nonce(extra_nonce, payment_id_long);
1450  r = add_extra_nonce_to_tx_extra(extra, extra_nonce);
1451  } else {
1452  r = tools::wallet2::parse_short_payment_id(payment_id, info.payment_id);
1453  if (r) {
1454  std::string extra_nonce;
1455  crypto::hash payment_id = crypto::null_hash;
1456  memcpy(payment_id.data, info.payment_id.data, 8); // convert short pid to regular
1457  memset(payment_id.data + 8, 0, 24); // merely a sanity check
1458 
1459  set_payment_id_to_tx_extra_nonce(extra_nonce, payment_id);
1460  r = add_extra_nonce_to_tx_extra(extra, extra_nonce);
1461  }
1462  }
1463 
1464  if (!r) {
1465  setStatusError(tr("payment id has invalid format, expected 16 or 64 character hex string: ") + payment_id);
1466  break;
1467  }
1468  }
1469  else if (info.has_payment_id) {
1470  std::string extra_nonce;
1471  crypto::hash payment_id = crypto::null_hash;
1472  memcpy(payment_id.data, info.payment_id.data, 8); // convert short pid to regular
1473  memset(payment_id.data + 8, 0, 24); // merely a sanity check
1474 
1475  set_payment_id_to_tx_extra_nonce(extra_nonce, payment_id);
1476  bool r = add_extra_nonce_to_tx_extra(extra, extra_nonce);
1477  if (!r) {
1478  setStatusError(tr("Failed to add short payment id: ") + epee::string_tools::pod_to_hex(info.payment_id));
1479  break;
1480  }
1481  }
1482 
1483 
1484  //std::vector<tools::wallet2::pending_tx> ptx_vector;
1485 
1486  try {
1487  if (amount) {
1488  vector<cryptonote::tx_destination_entry> dsts;
1490  de.original = dst_addr;
1491  de.addr = info.address;
1492  de.amount = *amount;
1493  de.is_subaddress = info.is_subaddress;
1494  de.is_integrated = info.has_payment_id;
1495  dsts.push_back(de);
1496  transaction->m_pending_tx = m_wallet->create_transactions_2(dsts, fake_outs_count, 0 /* unlock_time */,
1497  adjusted_priority,
1498  extra, subaddr_account, subaddr_indices);
1499  } else {
1500  // for the GUI, sweep_all (i.e. amount set as "(all)") will always sweep all the funds in all the addresses
1501  if (subaddr_indices.empty())
1502  {
1503  for (uint32_t index = 0; index < m_wallet->get_num_subaddresses(subaddr_account); ++index)
1504  subaddr_indices.insert(index);
1505  }
1506  transaction->m_pending_tx = m_wallet->create_transactions_all(0, info.address, info.is_subaddress, 1, fake_outs_count, 0 /* unlock_time */,
1507  adjusted_priority,
1508  extra, subaddr_account, subaddr_indices);
1509  }
1510 
1511  pendingTxPostProcess(transaction);
1512 
1513  if (multisig().isMultisig) {
1514  auto tx_set = m_wallet->make_multisig_tx_set(transaction->m_pending_tx);
1515  transaction->m_pending_tx = tx_set.m_ptx;
1516  transaction->m_signers = tx_set.m_signers;
1517  }
1518  } catch (const tools::error::daemon_busy&) {
1519  // TODO: make it translatable with "tr"?
1520  setStatusError(tr("daemon is busy. Please try again later."));
1521  } catch (const tools::error::no_connection_to_daemon&) {
1522  setStatusError(tr("no connection to daemon. Please make sure daemon is running."));
1523  } catch (const tools::error::wallet_rpc_error& e) {
1524  setStatusError(tr("RPC error: ") + e.to_string());
1525  } catch (const tools::error::get_outs_error &e) {
1526  setStatusError((boost::format(tr("failed to get outputs to mix: %s")) % e.what()).str());
1527  } catch (const tools::error::not_enough_unlocked_etn& e) {
1528  std::ostringstream writer;
1529 
1530  writer << boost::format(tr("not enough ETN to transfer, available only %s, sent amount %s")) %
1531  print_etn(e.available()) %
1532  print_etn(e.tx_amount());
1533  setStatusError(writer.str());
1534  } catch (const tools::error::not_enough_etn& e) {
1535  std::ostringstream writer;
1536 
1537  writer << boost::format(tr("not enough ETN to transfer, overall balance only %s, sent amount %s")) %
1538  print_etn(e.available()) %
1539  print_etn(e.tx_amount());
1540  setStatusError(writer.str());
1541  } catch (const tools::error::tx_not_possible& e) {
1542  std::ostringstream writer;
1543 
1544  writer << boost::format(tr("not enough ETN to transfer, available only %s, transaction amount %s = %s + %s (fee)")) %
1545  print_etn(e.available()) %
1546  print_etn(e.tx_amount() + e.fee()) %
1547  print_etn(e.tx_amount()) %
1548  print_etn(e.fee());
1549  setStatusError(writer.str());
1550  } catch (const tools::error::not_enough_outs_to_mix& e) {
1551  std::ostringstream writer;
1552  writer << tr("not enough outputs.");
1553  for (const std::pair<uint64_t, uint64_t> outs_for_amount : e.scanty_outs()) {
1554  writer << "\n" << tr("output amount") << " = " << print_etn(outs_for_amount.first) << ", " << tr("found outputs to use") << " = " << outs_for_amount.second;
1555  }
1556  writer << "\n" << tr("Please sweep unmixable outputs.");
1557  setStatusError(writer.str());
1558  } catch (const tools::error::tx_not_constructed&) {
1559  setStatusError(tr("transaction was not constructed"));
1560  } catch (const tools::error::tx_rejected& e) {
1561  std::ostringstream writer;
1562  writer << (boost::format(tr("transaction %s was rejected by daemon with status: ")) % get_transaction_hash(e.tx())) << e.status();
1563  setStatusError(writer.str());
1564  } catch (const tools::error::tx_sum_overflow& e) {
1565  setStatusError(e.what());
1566  } catch (const tools::error::zero_destination&) {
1567  setStatusError(tr("one of destinations is zero"));
1568  } catch (const tools::error::tx_too_big& e) {
1569  setStatusError(tr("failed to find a suitable way to split transactions"));
1570  } catch (const tools::error::transfer_error& e) {
1571  setStatusError(string(tr("unknown transfer error: ")) + e.what());
1572  } catch (const tools::error::wallet_internal_error& e) {
1573  setStatusError(string(tr("internal error: ")) + e.what());
1574  } catch (const std::exception& e) {
1575  setStatusError(string(tr("unexpected error: ")) + e.what());
1576  } catch (...) {
1577  setStatusError(tr("unknown error"));
1578  }
1579  } while (false);
1580 
1581  statusWithErrorString(transaction->m_status, transaction->m_errorString);
1582  // Resume refresh thread
1583  startRefresh();
1584  return transaction;
1585 }
1586 
1588 
1589 {
1590  clearStatus();
1592 
1594 
1595  do {
1596  try {
1597  transaction->m_pending_tx = m_wallet->create_unmixable_sweep_transactions();
1598  pendingTxPostProcess(transaction);
1599 
1600  } catch (const tools::error::daemon_busy&) {
1601  // TODO: make it translatable with "tr"?
1602  setStatusError(tr("daemon is busy. Please try again later."));
1603  } catch (const tools::error::no_connection_to_daemon&) {
1604  setStatusError(tr("no connection to daemon. Please make sure daemon is running."));
1605  } catch (const tools::error::wallet_rpc_error& e) {
1606  setStatusError(tr("RPC error: ") + e.to_string());
1607  } catch (const tools::error::get_outs_error&) {
1608  setStatusError(tr("failed to get outputs to mix"));
1609  } catch (const tools::error::not_enough_unlocked_etn& e) {
1610  setStatusError("");
1611  std::ostringstream writer;
1612 
1613  writer << boost::format(tr("not enough ETN to transfer, available only %s, sent amount %s")) %
1614  print_etn(e.available()) %
1615  print_etn(e.tx_amount());
1616  setStatusError(writer.str());
1617  } catch (const tools::error::not_enough_etn& e) {
1618  setStatusError("");
1619  std::ostringstream writer;
1620 
1621  writer << boost::format(tr("not enough ETN to transfer, overall balance only %s, sent amount %s")) %
1622  print_etn(e.available()) %
1623  print_etn(e.tx_amount());
1624  setStatusError(writer.str());
1625  } catch (const tools::error::tx_not_possible& e) {
1626  setStatusError("");
1627  std::ostringstream writer;
1628 
1629  writer << boost::format(tr("not enough ETN to transfer, available only %s, transaction amount %s = %s + %s (fee)")) %
1630  print_etn(e.available()) %
1631  print_etn(e.tx_amount() + e.fee()) %
1632  print_etn(e.tx_amount()) %
1633  print_etn(e.fee());
1634  setStatusError(writer.str());
1635  } catch (const tools::error::not_enough_outs_to_mix& e) {
1636  std::ostringstream writer;
1637  writer << tr("not enough outputs.");
1638  for (const std::pair<uint64_t, uint64_t> outs_for_amount : e.scanty_outs()) {
1639  writer << "\n" << tr("output amount") << " = " << print_etn(outs_for_amount.first) << ", " << tr("found outputs to use") << " = " << outs_for_amount.second;
1640  }
1641  setStatusError(writer.str());
1642  } catch (const tools::error::tx_not_constructed&) {
1643  setStatusError(tr("transaction was not constructed"));
1644  } catch (const tools::error::tx_rejected& e) {
1645  std::ostringstream writer;
1646  writer << (boost::format(tr("transaction %s was rejected by daemon with status: ")) % get_transaction_hash(e.tx())) << e.status();
1647  setStatusError(writer.str());
1648  } catch (const tools::error::tx_sum_overflow& e) {
1649  setStatusError(e.what());
1650  } catch (const tools::error::zero_destination&) {
1651  setStatusError(tr("one of destinations is zero"));
1652  } catch (const tools::error::tx_too_big& e) {
1653  setStatusError(tr("failed to find a suitable way to split transactions"));
1654  } catch (const tools::error::transfer_error& e) {
1655  setStatusError(string(tr("unknown transfer error: ")) + e.what());
1656  } catch (const tools::error::wallet_internal_error& e) {
1657  setStatusError(string(tr("internal error: ")) + e.what());
1658  } catch (const std::exception& e) {
1659  setStatusError(string(tr("unexpected error: ")) + e.what());
1660  } catch (...) {
1661  setStatusError(tr("unknown error"));
1662  }
1663  } while (false);
1664 
1665  statusWithErrorString(transaction->m_status, transaction->m_errorString);
1666  return transaction;
1667 }
1668 
1670 {
1671  delete t;
1672 }
1673 
1675 {
1676  return m_history.get();
1677 }
1678 
1680 {
1681  return m_addressBook.get();
1682 }
1683 
1685 {
1686  return m_subaddress.get();
1687 }
1688 
1690 {
1691  return m_subaddressAccount.get();
1692 }
1693 
1695 {
1696  // TODO thread synchronization;
1697  m_wallet2Callback->setListener(l);
1698 }
1699 
1701 {
1702  return m_wallet->default_mixin();
1703 }
1704 
1706 {
1707  m_wallet->default_mixin(arg);
1708 }
1709 
1710 bool WalletImpl::setUserNote(const std::string &txid, const std::string &note)
1711 {
1712  cryptonote::blobdata txid_data;
1713  if(!epee::string_tools::parse_hexstr_to_binbuff(txid, txid_data) || txid_data.size() != sizeof(crypto::hash))
1714  return false;
1715  const crypto::hash htxid = *reinterpret_cast<const crypto::hash*>(txid_data.data());
1716 
1717  m_wallet->set_tx_note(htxid, note);
1718  return true;
1719 }
1720 
1722 {
1723  cryptonote::blobdata txid_data;
1724  if(!epee::string_tools::parse_hexstr_to_binbuff(txid, txid_data) || txid_data.size() != sizeof(crypto::hash))
1725  return "";
1726  const crypto::hash htxid = *reinterpret_cast<const crypto::hash*>(txid_data.data());
1727 
1728  return m_wallet->get_tx_note(htxid);
1729 }
1730 
1732 {
1733  crypto::hash txid;
1734  if(!epee::string_tools::hex_to_pod(txid_str, txid))
1735  {
1736  setStatusError(tr("Failed to parse txid"));
1737  return "";
1738  }
1739 
1740  crypto::secret_key tx_key;
1741  std::vector<crypto::secret_key> additional_tx_keys;
1742  if (m_wallet->get_tx_key(txid, tx_key, additional_tx_keys))
1743  {
1744  clearStatus();
1745  std::ostringstream oss;
1746  oss << epee::string_tools::pod_to_hex(tx_key);
1747  for (size_t i = 0; i < additional_tx_keys.size(); ++i)
1748  oss << epee::string_tools::pod_to_hex(additional_tx_keys[i]);
1749  return oss.str();
1750  }
1751  else
1752  {
1753  setStatusError(tr("no tx keys found for this txid"));
1754  return "";
1755  }
1756 }
1757 
1758 bool WalletImpl::checkTxKey(const std::string &txid_str, std::string tx_key_str, const std::string &address_str, uint64_t &received, bool &in_pool, uint64_t &confirmations)
1759 {
1760  crypto::hash txid;
1761  if (!epee::string_tools::hex_to_pod(txid_str, txid))
1762  {
1763  setStatusError(tr("Failed to parse txid"));
1764  return false;
1765  }
1766 
1767  crypto::secret_key tx_key;
1768  std::vector<crypto::secret_key> additional_tx_keys;
1769  if (!epee::string_tools::hex_to_pod(tx_key_str.substr(0, 64), tx_key))
1770  {
1771  setStatusError(tr("Failed to parse tx key"));
1772  return false;
1773  }
1774  tx_key_str = tx_key_str.substr(64);
1775  while (!tx_key_str.empty())
1776  {
1777  additional_tx_keys.resize(additional_tx_keys.size() + 1);
1778  if (!epee::string_tools::hex_to_pod(tx_key_str.substr(0, 64), additional_tx_keys.back()))
1779  {
1780  setStatusError(tr("Failed to parse tx key"));
1781  return false;
1782  }
1783  tx_key_str = tx_key_str.substr(64);
1784  }
1785 
1787  if (!cryptonote::get_account_address_from_str(info, m_wallet->nettype(), address_str))
1788  {
1789  setStatusError(tr("Failed to parse address"));
1790  return false;
1791  }
1792 
1793  try
1794  {
1795  m_wallet->check_tx_key(txid, tx_key, additional_tx_keys, info.address, received, in_pool, confirmations);
1796  clearStatus();
1797  return true;
1798  }
1799  catch (const std::exception &e)
1800  {
1801  setStatusError(e.what());
1802  return false;
1803  }
1804 }
1805 
1806 std::string WalletImpl::getTxProof(const std::string &txid_str, const std::string &address_str, const std::string &message) const
1807 {
1808  crypto::hash txid;
1809  if (!epee::string_tools::hex_to_pod(txid_str, txid))
1810  {
1811  setStatusError(tr("Failed to parse txid"));
1812  return "";
1813  }
1814 
1816  if (!cryptonote::get_account_address_from_str(info, m_wallet->nettype(), address_str))
1817  {
1818  setStatusError(tr("Failed to parse address"));
1819  return "";
1820  }
1821 
1822  try
1823  {
1824  clearStatus();
1825  return m_wallet->get_tx_proof(txid, info.address, info.is_subaddress, message);
1826  }
1827  catch (const std::exception &e)
1828  {
1829  setStatusError(e.what());
1830  return "";
1831  }
1832 }
1833 
1834 bool WalletImpl::checkTxProof(const std::string &txid_str, const std::string &address_str, const std::string &message, const std::string &signature, bool &good, uint64_t &received, bool &in_pool, uint64_t &confirmations)
1835 {
1836  crypto::hash txid;
1837  if (!epee::string_tools::hex_to_pod(txid_str, txid))
1838  {
1839  setStatusError(tr("Failed to parse txid"));
1840  return false;
1841  }
1842 
1844  if (!cryptonote::get_account_address_from_str(info, m_wallet->nettype(), address_str))
1845  {
1846  setStatusError(tr("Failed to parse address"));
1847  return false;
1848  }
1849 
1850  try
1851  {
1852  good = m_wallet->check_tx_proof(txid, info.address, info.is_subaddress, message, signature, received, in_pool, confirmations);
1853  clearStatus();
1854  return true;
1855  }
1856  catch (const std::exception &e)
1857  {
1858  setStatusError(e.what());
1859  return false;
1860  }
1861 }
1862 
1864  crypto::hash txid;
1865  if(!epee::string_tools::hex_to_pod(txid_str, txid))
1866  {
1867  setStatusError(tr("Failed to parse txid"));
1868  return "";
1869  }
1870 
1871  try
1872  {
1873  clearStatus();
1874  return m_wallet->get_spend_proof(txid, message);
1875  }
1876  catch (const std::exception &e)
1877  {
1878  setStatusError(e.what());
1879  return "";
1880  }
1881 }
1882 
1883 bool WalletImpl::checkSpendProof(const std::string &txid_str, const std::string &message, const std::string &signature, bool &good) const {
1884  good = false;
1885  crypto::hash txid;
1886  if(!epee::string_tools::hex_to_pod(txid_str, txid))
1887  {
1888  setStatusError(tr("Failed to parse txid"));
1889  return false;
1890  }
1891 
1892  try
1893  {
1894  clearStatus();
1895  good = m_wallet->check_spend_proof(txid, message, signature);
1896  return true;
1897  }
1898  catch (const std::exception &e)
1899  {
1900  setStatusError(e.what());
1901  return false;
1902  }
1903 }
1904 
1905 std::string WalletImpl::getReserveProof(bool all, uint32_t account_index, uint64_t amount, const std::string &message) const {
1906  try
1907  {
1908  clearStatus();
1909  boost::optional<std::pair<uint32_t, uint64_t>> account_minreserve;
1910  if (!all)
1911  {
1912  account_minreserve = std::make_pair(account_index, amount);
1913  }
1914  return m_wallet->get_reserve_proof(account_minreserve, message);
1915  }
1916  catch (const std::exception &e)
1917  {
1918  setStatusError(e.what());
1919  return "";
1920  }
1921 }
1922 
1923 bool WalletImpl::checkReserveProof(const std::string &address, const std::string &message, const std::string &signature, bool &good, uint64_t &total, uint64_t &spent) const {
1925  if (!cryptonote::get_account_address_from_str(info, m_wallet->nettype(), address))
1926  {
1927  setStatusError(tr("Failed to parse address"));
1928  return false;
1929  }
1930  if (info.is_subaddress)
1931  {
1932  setStatusError(tr("Address must not be a subaddress"));
1933  return false;
1934  }
1935 
1936  good = false;
1937  try
1938  {
1939  clearStatus();
1940  good = m_wallet->check_reserve_proof(info.address, message, signature, total, spent);
1941  return true;
1942  }
1943  catch (const std::exception &e)
1944  {
1945  setStatusError(e.what());
1946  return false;
1947  }
1948 }
1949 
1951 {
1952  return m_wallet->sign(message);
1953 }
1954 
1956 {
1958 
1959  if (!cryptonote::get_account_address_from_str(info, m_wallet->nettype(), address))
1960  return false;
1961 
1962  return m_wallet->verify(message, info.address, signature);
1963 }
1964 
1966 {
1967  clearStatus();
1968 
1969  bool ready = false;
1970  if (!m_wallet->multisig(&ready) || !ready) {
1971  m_status = Status_Error;
1972  m_errorString = tr("The wallet must be in multisig ready state");
1973  return {};
1974  }
1975 
1976  try {
1977  return m_wallet->sign_multisig_participant(message);
1978  } catch (const std::exception& e) {
1979  m_status = Status_Error;
1980  m_errorString = e.what();
1981  }
1982 
1983  return {};
1984 }
1985 
1987 {
1988  clearStatus();
1989 
1990  cryptonote::blobdata pkeyData;
1991  if(!epee::string_tools::parse_hexstr_to_binbuff(publicKey, pkeyData) || pkeyData.size() != sizeof(crypto::public_key))
1992  {
1993  m_status = Status_Error;
1994  m_errorString = tr("Given string is not a key");
1995  return false;
1996  }
1997 
1998  try {
1999  crypto::public_key pkey = *reinterpret_cast<const crypto::public_key*>(pkeyData.data());
2000  return m_wallet->verify_with_public_key(message, pkey, signature);
2001  } catch (const std::exception& e) {
2002  m_status = Status_Error;
2003  m_errorString = e.what();
2004  }
2005 
2006  return false;
2007 }
2008 
2010 {
2011  bool result = m_wallet->check_connection(NULL, NULL, DEFAULT_CONNECTION_TIMEOUT_MILLIS);
2012  if (!result) {
2013  setStatusError("Error connecting to daemon at " + m_wallet->get_daemon_address());
2014  } else {
2015  clearStatus();
2016  // start refreshing here
2017  }
2018  return result;
2019 }
2020 
2022 {
2023  uint32_t version = 0;
2024  m_is_connected = m_wallet->check_connection(&version, NULL, DEFAULT_CONNECTION_TIMEOUT_MILLIS);
2025  if (!m_is_connected)
2027  // Version check is not implemented in light wallets nodes/wallets
2028  if (!m_wallet->light_wallet() && (version >> 16) != CORE_RPC_VERSION_MAJOR)
2031 }
2032 
2034 {
2035  m_wallet->set_trusted_daemon(arg);
2036 }
2037 
2039 {
2040  return m_wallet->is_trusted_daemon();
2041 }
2042 
2044 {
2045  return m_wallet->watch_only();
2046 }
2047 
2048 void WalletImpl::clearStatus() const
2049 {
2050  boost::lock_guard<boost::mutex> l(m_statusMutex);
2051  m_status = Status_Ok;
2052  m_errorString.clear();
2053 }
2054 
2055 void WalletImpl::setStatusError(const std::string& message) const
2056 {
2057  setStatus(Status_Error, message);
2058 }
2059 
2060 void WalletImpl::setStatusCritical(const std::string& message) const
2061 {
2062  setStatus(Status_Critical, message);
2063 }
2064 
2065 void WalletImpl::setStatus(int status, const std::string& message) const
2066 {
2067  boost::lock_guard<boost::mutex> l(m_statusMutex);
2068  m_status = status;
2069  m_errorString = message;
2070 }
2071 
2072 void WalletImpl::refreshThreadFunc()
2073 {
2074  LOG_PRINT_L3(__FUNCTION__ << ": starting refresh thread");
2075 
2076  while (true) {
2077  boost::mutex::scoped_lock lock(m_refreshMutex);
2078  if (m_refreshThreadDone) {
2079  break;
2080  }
2081  LOG_PRINT_L3(__FUNCTION__ << ": waiting for refresh...");
2082  // if auto refresh enabled, we wait for the "m_refreshIntervalSeconds" interval.
2083  // if not - we wait forever
2084  if (m_refreshIntervalMillis > 0) {
2085  boost::posix_time::milliseconds wait_for_ms(m_refreshIntervalMillis.load());
2086  m_refreshCV.timed_wait(lock, wait_for_ms);
2087  } else {
2088  m_refreshCV.wait(lock);
2089  }
2090 
2091  LOG_PRINT_L3(__FUNCTION__ << ": refresh lock acquired...");
2092  LOG_PRINT_L3(__FUNCTION__ << ": m_refreshEnabled: " << m_refreshEnabled);
2093  LOG_PRINT_L3(__FUNCTION__ << ": m_status: " << status());
2094  LOG_PRINT_L3(__FUNCTION__ << ": m_refreshShouldRescan: " << m_refreshShouldRescan);
2095  if (m_refreshEnabled) {
2096  LOG_PRINT_L3(__FUNCTION__ << ": refreshing...");
2097  doRefresh();
2098  }
2099  }
2100  LOG_PRINT_L3(__FUNCTION__ << ": refresh thread stopped");
2101 }
2102 
2103 void WalletImpl::doRefresh()
2104 {
2105  bool rescan = m_refreshShouldRescan.exchange(false);
2106  // synchronizing async and sync refresh calls
2107  boost::lock_guard<boost::mutex> guarg(m_refreshMutex2);
2108  do try {
2109  LOG_PRINT_L3(__FUNCTION__ << ": doRefresh, rescan = "<<rescan);
2110  // Syncing daemon and refreshing wallet simultaneously is very resource intensive.
2111  // Disable refresh if wallet is disconnected or daemon isn't synced.
2112  if (m_wallet->light_wallet() || daemonSynced()) {
2113  if(rescan)
2114  m_wallet->rescan_blockchain(false);
2115  m_wallet->refresh(trustedDaemon());
2116  if (!m_synchronized) {
2117  m_synchronized = true;
2118  }
2119  // assuming if we have empty history, it wasn't initialized yet
2120  // for further history changes client need to update history in
2121  // "on_etn_received" and "on_etn_sent" callbacks
2122  if (m_history->count() == 0) {
2123  m_history->refresh();
2124  }
2125  m_wallet->find_and_save_rings(false);
2126  } else {
2127  LOG_PRINT_L3(__FUNCTION__ << ": skipping refresh - daemon is not synced");
2128  }
2129  } catch (const std::exception &e) {
2130  setStatusError(e.what());
2131  break;
2132  }while(!rescan && (rescan=m_refreshShouldRescan.exchange(false))); // repeat if not rescanned and rescan was requested
2133 
2134  if (m_wallet2Callback->getListener()) {
2135  m_wallet2Callback->getListener()->refreshed();
2136  }
2137 }
2138 
2139 
2141 {
2142  if (!m_refreshEnabled) {
2143  LOG_PRINT_L2(__FUNCTION__ << ": refresh started/resumed...");
2144  m_refreshEnabled = true;
2145  m_refreshCV.notify_one();
2146  }
2147 }
2148 
2149 
2150 
2151 void WalletImpl::stopRefresh()
2152 {
2153  if (!m_refreshThreadDone) {
2154  m_refreshEnabled = false;
2155  m_refreshThreadDone = true;
2156  m_refreshCV.notify_one();
2157  m_refreshThread.join();
2158  }
2159 }
2160 
2162 {
2163  LOG_PRINT_L2(__FUNCTION__ << ": refresh paused...");
2164  // TODO synchronize access
2165  if (!m_refreshThreadDone) {
2166  m_refreshEnabled = false;
2167  }
2168 }
2169 
2170 
2171 bool WalletImpl::isNewWallet() const
2172 {
2173  // in case wallet created without daemon connection, closed and opened again,
2174  // it's the same case as if it created from scratch, i.e. we need "fast sync"
2175  // with the daemon (pull hashes instead of pull blocks).
2176  // If wallet cache is rebuilt, creation height stored in .keys is used.
2177  // Watch only wallet is a copy of an existing wallet.
2178  return !(blockChainHeight() > 1 || m_recoveringFromSeed || m_recoveringFromDevice || m_rebuildWalletCache) && !watchOnly();
2179 }
2180 
2181 void WalletImpl::pendingTxPostProcess(PendingTransactionImpl * pending)
2182 {
2183  // If the device being used is HW device with cold signing protocol, cold sign then.
2184  if (!m_wallet->get_account().get_device().has_tx_cold_sign()){
2185  return;
2186  }
2187 
2188  tools::wallet2::signed_tx_set exported_txs;
2189  std::vector<cryptonote::address_parse_info> dsts_info;
2190 
2191  m_wallet->cold_sign_tx(pending->m_pending_tx, exported_txs, dsts_info, pending->m_tx_device_aux);
2192  pending->m_key_images = exported_txs.key_images;
2193  pending->m_pending_tx = exported_txs.ptx;
2194 }
2195 
2196 bool WalletImpl::doInit(const string &daemon_address, uint64_t upper_transaction_size_limit, bool ssl)
2197 {
2198  if (!m_wallet->init(daemon_address, m_daemon_login, boost::asio::ip::tcp::endpoint{}, upper_transaction_size_limit))
2199  return false;
2200 
2201  // in case new wallet, this will force fast-refresh (pulling hashes instead of blocks)
2202  // If daemon isn't synced a calculated block height will be used instead
2203  //TODO: Handle light wallet scenario where block height = 0.
2204  if (isNewWallet() && daemonSynced()) {
2205  LOG_PRINT_L2(__FUNCTION__ << ":New Wallet - fast refresh until " << daemonBlockChainHeight());
2206  m_wallet->set_refresh_from_block_height(daemonBlockChainHeight());
2207  }
2208 
2209  if (m_rebuildWalletCache)
2210  LOG_PRINT_L2(__FUNCTION__ << ": Rebuilding wallet cache, fast refresh until block " << m_wallet->get_refresh_from_block_height());
2211 
2213  this->setTrustedDaemon(true);
2214  m_refreshIntervalMillis = DEFAULT_REFRESH_INTERVAL_MILLIS;
2215  } else {
2216  this->setTrustedDaemon(false);
2217  m_refreshIntervalMillis = DEFAULT_REMOTE_NODE_REFRESH_INTERVAL_MILLIS;
2218  }
2219  return true;
2220 }
2221 
2222 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)
2223 {
2224  return m_wallet->parse_uri(uri, address, payment_id, amount, tx_description, recipient_name, unknown_parameters, error);
2225 }
2226 
2228 {
2229  return tools::get_default_data_dir();
2230 }
2231 
2233 {
2234  clearStatus();
2235  if (!trustedDaemon()) {
2236  setStatusError(tr("Rescan spent can only be used with a trusted daemon"));
2237  return false;
2238  }
2239  try {
2240  m_wallet->rescan_spent();
2241  } catch (const std::exception &e) {
2242  LOG_ERROR(__FUNCTION__ << " error: " << e.what());
2243  setStatusError(e.what());
2244  return false;
2245  }
2246  return true;
2247 }
2248 
2249 
2250 void WalletImpl::hardForkInfo(uint8_t &version, uint64_t &earliest_height) const
2251 {
2252  m_wallet->get_hard_fork_info(version, earliest_height);
2253 }
2254 
2256 {
2257  return m_wallet->use_fork_rules(version,early_blocks);
2258 }
2259 
2260 bool WalletImpl::blackballOutputs(const std::vector<std::string> &outputs, bool add)
2261 {
2262  std::vector<std::pair<uint64_t, uint64_t>> raw_outputs;
2263  raw_outputs.reserve(outputs.size());
2264  uint64_t amount = std::numeric_limits<uint64_t>::max(), offset, num_offsets;
2265  for (const std::string &str: outputs)
2266  {
2267  if (sscanf(str.c_str(), "@%" PRIu64, &amount) == 1)
2268  continue;
2269  if (amount == std::numeric_limits<uint64_t>::max())
2270  {
2271  setStatusError("First line is not an amount");
2272  return true;
2273  }
2274  if (sscanf(str.c_str(), "%" PRIu64 "*%" PRIu64, &offset, &num_offsets) == 2 && num_offsets <= std::numeric_limits<uint64_t>::max() - offset)
2275  {
2276  while (num_offsets--)
2277  raw_outputs.push_back(std::make_pair(amount, offset++));
2278  }
2279  else if (sscanf(str.c_str(), "%" PRIu64, &offset) == 1)
2280  {
2281  raw_outputs.push_back(std::make_pair(amount, offset));
2282  }
2283  else
2284  {
2285  setStatusError(tr("Invalid output: ") + str);
2286  return false;
2287  }
2288  }
2289  bool ret = m_wallet->set_blackballed_outputs(raw_outputs, add);
2290  if (!ret)
2291  {
2292  setStatusError(tr("Failed to mark outputs as spent"));
2293  return false;
2294  }
2295  return true;
2296 }
2297 
2298 bool WalletImpl::blackballOutput(const std::string &amount, const std::string &offset)
2299 {
2300  uint64_t raw_amount, raw_offset;
2301  if (!epee::string_tools::get_xtype_from_string(raw_amount, amount))
2302  {
2303  setStatusError(tr("Failed to parse output amount"));
2304  return false;
2305  }
2306  if (!epee::string_tools::get_xtype_from_string(raw_offset, offset))
2307  {
2308  setStatusError(tr("Failed to parse output offset"));
2309  return false;
2310  }
2311  bool ret = m_wallet->blackball_output(std::make_pair(raw_amount, raw_offset));
2312  if (!ret)
2313  {
2314  setStatusError(tr("Failed to mark output as spent"));
2315  return false;
2316  }
2317  return true;
2318 }
2319 
2320 bool WalletImpl::unblackballOutput(const std::string &amount, const std::string &offset)
2321 {
2322  uint64_t raw_amount, raw_offset;
2323  if (!epee::string_tools::get_xtype_from_string(raw_amount, amount))
2324  {
2325  setStatusError(tr("Failed to parse output amount"));
2326  return false;
2327  }
2328  if (!epee::string_tools::get_xtype_from_string(raw_offset, offset))
2329  {
2330  setStatusError(tr("Failed to parse output offset"));
2331  return false;
2332  }
2333  bool ret = m_wallet->unblackball_output(std::make_pair(raw_amount, raw_offset));
2334  if (!ret)
2335  {
2336  setStatusError(tr("Failed to mark output as unspent"));
2337  return false;
2338  }
2339  return true;
2340 }
2341 
2342 bool WalletImpl::getRing(const std::string &key_image, std::vector<uint64_t> &ring) const
2343 {
2344  crypto::key_image raw_key_image;
2345  if (!epee::string_tools::hex_to_pod(key_image, raw_key_image))
2346  {
2347  setStatusError(tr("Failed to parse key image"));
2348  return false;
2349  }
2350  bool ret = m_wallet->get_ring(raw_key_image, ring);
2351  if (!ret)
2352  {
2353  setStatusError(tr("Failed to get ring"));
2354  return false;
2355  }
2356  return true;
2357 }
2358 
2359 bool WalletImpl::getRings(const std::string &txid, std::vector<std::pair<std::string, std::vector<uint64_t>>> &rings) const
2360 {
2361  crypto::hash raw_txid;
2362  if (!epee::string_tools::hex_to_pod(txid, raw_txid))
2363  {
2364  setStatusError(tr("Failed to parse txid"));
2365  return false;
2366  }
2367  std::vector<std::pair<crypto::key_image, std::vector<uint64_t>>> raw_rings;
2368  bool ret = m_wallet->get_rings(raw_txid, raw_rings);
2369  if (!ret)
2370  {
2371  setStatusError(tr("Failed to get rings"));
2372  return false;
2373  }
2374  for (const auto &r: raw_rings)
2375  {
2376  rings.push_back(std::make_pair(epee::string_tools::pod_to_hex(r.first), r.second));
2377  }
2378  return true;
2379 }
2380 
2381 bool WalletImpl::setRing(const std::string &key_image, const std::vector<uint64_t> &ring, bool relative)
2382 {
2383  crypto::key_image raw_key_image;
2384  if (!epee::string_tools::hex_to_pod(key_image, raw_key_image))
2385  {
2386  setStatusError(tr("Failed to parse key image"));
2387  return false;
2388  }
2389  bool ret = m_wallet->set_ring(raw_key_image, ring, relative);
2390  if (!ret)
2391  {
2392  setStatusError(tr("Failed to set ring"));
2393  return false;
2394  }
2395  return true;
2396 }
2397 
2399 {
2400  m_wallet->segregate_pre_fork_outputs(segregate);
2401 }
2402 
2404 {
2405  m_wallet->segregation_height(height);
2406 }
2407 
2408 void WalletImpl::keyReuseMitigation2(bool mitigation)
2409 {
2410  m_wallet->key_reuse_mitigation2(mitigation);
2411 }
2412 
2414 {
2415  return m_wallet->lock_keys_file();
2416 }
2417 
2419 {
2420  return m_wallet->unlock_keys_file();
2421 }
2422 
2424 {
2425  return m_wallet->is_keys_file_locked();
2426 }
2427 
2429 {
2430  return m_wallet->cold_key_image_sync(spent, unspent);
2431 }
2432 } // namespace
2433 
2434 namespace Bitelectroneum = Electroneum;
void setListener(WalletListener *listener)
Definition: wallet.cpp:139
bool recoverFromDevice(const std::string &path, const std::string &password, const std::string &device_name)
Definition: wallet.cpp:677
virtual std::string getUserNote(const std::string &txid) const override
getUserNote - return an arbitrary string note attached to a txid
Definition: wallet.cpp:1721
virtual bool checkTxProof(const std::string &txid, const std::string &address, const std::string &message, const std::string &signature, bool &good, uint64_t &received, bool &in_pool, uint64_t &confirmations) override
Definition: wallet.cpp:1834
static bool parse_long_payment_id(const std::string &payment_id_str, crypto::hash &payment_id)
Definition: wallet2.cpp:5712
#define tr(x)
Definition: common_defines.h:4
size_t importMultisigImages(const std::vector< std::string > &images) override
importMultisigImages - imports other participants&#39; multisig images
Definition: wallet.cpp:1332
std::vector< crypto::key_image > key_images
Definition: wallet2.h:506
void setSubaddressLabel(uint32_t accountIndex, uint32_t addressIndex, const std::string &label) override
setSubaddressLabel - sets the label of the specified subaddress
Definition: wallet.cpp:1235
virtual std::string signMessage(const std::string &message) override
Definition: wallet.cpp:1950
bool create(const std::string &path, const std::string &password, const std::string &language)
Definition: wallet.cpp:469
#define LOG_PRINT_L2(x)
Definition: misc_log_ex.h:101
void rescanBlockchainAsync() override
rescanBlockchainAsync - rescans wallet asynchronously, starting from genesys
Definition: wallet.cpp:1101
virtual void on_skip_transaction(uint64_t height, const crypto::hash &txid, const cryptonote::transaction &tx)
Definition: wallet.cpp:210
void setRecoveringFromDevice(bool recoveringFromDevice) override
setRecoveringFromDevice - set state to recovering from device
Definition: wallet.cpp:986
virtual bool blackballOutput(const std::string &amount, const std::string &offset) override
blackballs an output
Definition: wallet.cpp:2298
virtual PendingTransaction * createSweepUnmixableTransaction() override
createSweepUnmixableTransaction creates transaction with unmixable outputs.
Definition: wallet.cpp:1587
bool setPassword(const std::string &password) override
Definition: wallet.cpp:826
virtual void segregatePreForkOutputs(bool segregate) override
sets whether pre-fork outs are to be segregated
Definition: wallet.cpp:2398
The TransactionHistory - interface for displaying transaction history.
Definition: wallet2_api.h:203
virtual void setDefaultMixin(uint32_t arg) override
setDefaultMixin - setum number of mixins to be used for new transactions
Definition: wallet.cpp:1705
std::string publicViewKey() const override
publicViewKey - returns public view key
Definition: wallet.cpp:879
const std::string & get_language_name() const
Returns the name of the language.
WalletListener * m_listener
Definition: wallet.cpp:290
Transaction-like interface for sending etn.
Definition: wallet2_api.h:133
virtual boost::optional< epee::wipeable_string > on_device_pin_request()
Definition: wallet.cpp:261
virtual bool checkSpendProof(const std::string &txid, const std::string &message, const std::string &signature, bool &good) const override
Definition: wallet.cpp:1883
uint64_t unlockedBalance(uint32_t accountIndex=0, bool public_blockchain=false) const override
Definition: wallet.cpp:1001
virtual bool 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) override
Definition: wallet.cpp:2222
virtual std::string signMultisigParticipant(const std::string &message) const override
signMultisigParticipant signs given message with the multisig public signer key
Definition: wallet.cpp:1965
std::string publicKey
std::string secretViewKey() const override
secretViewKey - returns secret view key
Definition: wallet.cpp:874
virtual bool unblackballOutput(const std::string &amount, const std::string &offset) override
unblackballs an output
Definition: wallet.cpp:2320
#define LOG_PRINT_L1(x)
Definition: misc_log_ex.h:100
#define MCWARNING(cat, x)
Definition: misc_log_ex.h:52
std::string publicSpendKey() const override
publicSpendKey - returns public spend key
Definition: wallet.cpp:889
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 set_module_name_and_folder(const std::string &path_to_process_)
Definition: string_tools.h:249
friend class AddressBookImpl
Definition: wallet.h:224
PendingTransaction * createTransaction(const std::string &dst_addr, const std::string &payment_id, optional< uint64_t > amount, uint32_t mixin_count, PendingTransaction::Priority priority=PendingTransaction::Priority_Low, uint32_t subaddr_account=0, std::set< uint32_t > subaddr_indices={}) override
createTransaction creates transaction. if dst_addr is an integrated address, payment_id is ignored ...
Definition: wallet.cpp:1412
bool connectToDaemon() override
connectToDaemon - connects to the daemon. TODO: check if it can be removed
Definition: wallet.cpp:2009
#define CRYPTONOTE_DISPLAY_DECIMAL_POINT
::std::string string
Definition: gtest-port.h:1097
virtual bool getRings(const std::string &txid, std::vector< std::pair< std::string, std::vector< uint64_t >>> &rings) const override
gets the rings used for a txid, if any
Definition: wallet.cpp:2359
epee::misc_utils::struct_init< response_t > response
virtual void segregationHeight(uint64_t height) override
sets the height where segregation should occur
Definition: wallet.cpp:2403
bool close(bool store=true)
Definition: wallet.cpp:762
std::string print_etn(uint64_t amount, unsigned int decimal_point)
const std::string old_language_name
bool finalizeMultisig(const std::vector< std::string > &extraMultisigInfo) override
finalizeMultisig - finalizes N - 1 / N multisig wallets creation
Definition: wallet.cpp:1298
friend struct Wallet2CallbackImpl
Definition: wallet.h:223
std::string mlog_get_default_log_path(const char *default_filename)
Definition: mlog.cpp:72
uint64_t height
Definition: blockchain.cpp:91
std::string getSeedLanguage() const override
Definition: wallet.cpp:798
uint64_t daemonBlockChainTargetHeight() const override
daemonBlockChainTargetHeight - returns daemon blockchain target height
Definition: wallet.cpp:1042
virtual void startRefresh() override
StartRefresh - Start/resume refresh thread (refresh every 10 seconds)
Definition: wallet.cpp:2140
void mlog_configure(const std::string &filename_base, bool console, const std::size_t max_log_file_size=MAX_LOG_FILE_SIZE, const std::size_t max_log_files=MAX_LOG_FILES)
Definition: mlog.cpp:148
bool trustedDaemon() const override
Definition: wallet.cpp:2038
virtual std::string getReserveProof(bool all, uint32_t account_index, uint64_t amount, const std::string &message) const override
getReserveProof - Generates a proof that proves the reserve of unspent funds Parameters account_index...
Definition: wallet.cpp:1905
std::vector< pending_tx > ptx
Definition: wallet2.h:505
const char * key
Definition: hmac_keccak.cpp:39
bool useForkRules(uint8_t version, int64_t early_blocks) const override
check if hard fork rules should be used
Definition: wallet.cpp:2255
virtual bool verifyMessageWithPublicKey(const std::string &message, const std::string &publicKey, const std::string &signature) const override
verifyMessageWithPublicKey verifies that message was signed with the given public key ...
Definition: wallet.cpp:1986
bool exportKeyImages(const std::string &filename) override
exportKeyImages - exports key images to file
Definition: wallet.cpp:1158
virtual void on_unconfirmed_etn_received(uint64_t height, const crypto::hash &txid, const cryptonote::transaction &tx, uint64_t amount, const cryptonote::subaddress_index &subaddr_index)
Definition: wallet.cpp:178
virtual bool unlockKeysFile() override
Definition: wallet.cpp:2418
epee::mlocked< tools::scrubbed< ec_scalar > > secret_key
Definition: crypto.h:82
bool hasMultisigPartialKeyImages() const override
hasMultisigPartialKeyImages - checks if wallet needs to import multisig key images from other partici...
Definition: wallet.cpp:1360
STL namespace.
std::string errorString() const override
in case error status, returns error string
Definition: wallet.cpp:814
virtual void on_etn_received(uint64_t height, const crypto::hash &txid, const cryptonote::transaction &tx, uint64_t amount, const cryptonote::subaddress_index &subaddr_index, uint64_t unlock_time)
Definition: wallet.cpp:162
virtual void on_lw_etn_received(uint64_t height, const crypto::hash &txid, uint64_t amount)
Definition: wallet.cpp:223
bool words_to_bytes(const epee::wipeable_string &words, epee::wipeable_string &dst, size_t len, bool duplicate, std::string &language_name)
Converts seed words to bytes (secret key).
virtual bool isKeysFileLocked() override
returns true if the keys file is locked
Definition: wallet.cpp:2423
virtual std::string getTxProof(const std::string &txid, const std::string &address, const std::string &message) const override
Definition: wallet.cpp:1806
unsigned char uint8_t
Definition: stdint.h:124
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="")
Definition: wallet.cpp:572
virtual void on_device_progress(const hw::device_progress &event)
Definition: wallet.cpp:283
std::unordered_set< crypto::public_key > m_signers
Definition: wallet2.h:513
virtual bool blackballOutputs(const std::vector< std::string > &outputs, bool add) override
blackballs a set of outputs
Definition: wallet.cpp:2260
virtual void disposeTransaction(PendingTransaction *t) override
disposeTransaction - destroys transaction object
Definition: wallet.cpp:1669
void set_seed_language(const std::string &language)
Sets the seed language.
Definition: wallet2.cpp:1425
virtual void setListener(WalletListener *l) override
Definition: wallet.cpp:1694
bool open(const std::string &path, const std::string &password)
Definition: wallet.cpp:699
bool init(const std::string &daemon_address, uint64_t upper_transaction_size_limit=0, const std::string &daemon_username="", const std::string &daemon_password="", bool use_ssl=false, bool lightWallet=false) override
init - initializes wallet with daemon connection params. if daemon_address is local address...
Definition: wallet.cpp:937
uint64_t import_key_images(const std::vector< std::pair< crypto::key_image, crypto::signature >> &signed_key_images, size_t offset, uint64_t &spent, uint64_t &unspent, bool check_spent=true)
Definition: wallet2.cpp:12333
void statusWithErrorString(int &status, std::string &errorString) const override
returns both error and error string atomically. suggested to use in instead of status() and errorStri...
Definition: wallet.cpp:820
std::string integratedAddress(const std::string &payment_id) const override
integratedAddress - returns integrated address for current wallet address and given payment_id...
Definition: wallet.cpp:865
uint64_t estimateBlockChainHeight() const override
estimateBlockChainHeight - returns estimate blockchain height. More accurate than approximateBlockCha...
Definition: wallet.cpp:1018
std::string get_default_data_dir()
Returns the default data directory.
Definition: util.cpp:600
void setTrustedDaemon(bool arg) override
Definition: wallet.cpp:2033
Holds cryptonote related classes and helpers.
Definition: ban.cpp:40
virtual void pauseRefresh() override
pauseRefresh - pause refresh thread
Definition: wallet.cpp:2161
virtual void on_new_block(uint64_t height, const cryptonote::block &block)
Definition: wallet.cpp:149
friend class SubaddressAccountImpl
Definition: wallet.h:226
std::string address(uint32_t accountIndex=0, uint32_t addressIndex=0) const override
Definition: wallet.cpp:860
bool parse_amount(uint64_t &amount, const std::string &str_amount_)
virtual bool lockKeysFile() override
locks/unlocks the keys file; returns true on success
Definition: wallet.cpp:2413
bool rescanBlockchain() override
rescanBlockchain - rescans the wallet, updating transactions from daemon
Definition: wallet.cpp:1093
virtual void on_lw_etn_spent(uint64_t height, const crypto::hash &txid, uint64_t amount)
Definition: wallet.cpp:239
bool isAddressLocal(const std::string &address)
Definition: utils.cpp:42
std::string pod_to_hex(const t_pod_type &s)
Definition: string_tools.h:317
virtual bool verifySignedMessage(const std::string &message, const std::string &address, const std::string &signature) const override
verifySignedMessage - verify a signature matches a given message
Definition: wallet.cpp:1955
friend class TransactionHistoryImpl
Definition: wallet.h:222
unsigned int uint32_t
Definition: stdint.h:126
PendingTransaction * restoreMultisigTransaction(const std::string &signData) override
restoreMultisigTransaction creates PendingTransaction from signData
Definition: wallet.cpp:1374
#define MCERROR(cat, x)
Definition: misc_log_ex.h:51
virtual SubaddressAccount * subaddressAccount() override
Definition: wallet.cpp:1689
bool rescanSpent() override
Definition: wallet.cpp:2232
static void error(const std::string &category, const std::string &str)
Definition: wallet.cpp:415
virtual AddressBook * addressBook() override
Definition: wallet.cpp:1679
void setSeedLanguage(const std::string &arg) override
Definition: wallet.cpp:803
void hardForkInfo(uint8_t &version, uint64_t &earliest_height) const override
returns current hard fork info
Definition: wallet.cpp:2250
bool setDevicePin(const std::string &password) override
Definition: wallet.cpp:838
bool exportMultisigImages(std::string &images) override
exportMultisigImages - exports transfers&#39; key images
Definition: wallet.cpp:1316
The AddressBook - interface for Book.
Definition: wallet2_api.h:241
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
MultisigState multisig() const override
multisig - returns current state of multisig wallet creation process
Definition: wallet.cpp:1248
virtual bool checkTxKey(const std::string &txid, std::string tx_key, const std::string &address, uint64_t &received, bool &in_pool, uint64_t &confirmations) override
Definition: wallet.cpp:1758
uint64_t amount
bool hex_to_pod(const std::string &hex_str, t_pod_type &s)
Definition: string_tools.h:324
const scanty_outs_t & scanty_outs() const
std::string getMultisigInfo() const override
getMultisigInfo
Definition: wallet.cpp:1255
virtual TransactionHistory * history() override
Definition: wallet.cpp:1674
#define false
Definition: stdbool.h:38
virtual bool setUserNote(const std::string &txid, const std::string &note) override
setUserNote - attach an arbitrary string note to a txid
Definition: wallet.cpp:1710
void refreshAsync() override
refreshAsync - refreshes wallet asynchronously.
Definition: wallet.cpp:1086
bool is_subaddress
Transaction-like interface for sending etn.
Definition: wallet2_api.h:72
virtual void on_device_button_request(uint64_t code)
Definition: wallet.cpp:247
bool is_integrated
#define LOG_PRINT_L3(x)
Definition: misc_log_ex.h:102
POD_CLASS public_key
Definition: crypto.h:76
bool refresh() override
refresh - refreshes the wallet, updating transactions from daemon
Definition: wallet.cpp:1077
version
Supported socks variants.
Definition: socks.h:57
virtual std::string getSpendProof(const std::string &txid, const std::string &message) const override
Definition: wallet.cpp:1863
virtual bool lightWalletLogin(bool &isNewWallet) const override
Light wallet authenticate and login.
Definition: wallet.cpp:946
Device getDeviceType() const override
Queries backing device for wallet keys.
Definition: wallet.cpp:694
std::string message("Message requiring signing")
virtual void keyReuseMitigation2(bool mitigation) override
secondary key reuse mitigation
Definition: wallet.cpp:2408
static bool parse_short_payment_id(const std::string &payment_id_str, crypto::hash8 &payment_id)
Definition: wallet2.cpp:5725
WalletListener * getListener() const
Definition: wallet.cpp:144
void set_refresh_from_block_height(uint64_t height)
Definition: wallet2.h:742
void addSubaddress(uint32_t accountIndex, const std::string &label) override
addSubaddress - appends a new subaddress at the end of the last minor index of the specified subaddre...
Definition: wallet.cpp:1218
bool importKeyImages(const std::string &filename) override
importKeyImages - imports key images from file
Definition: wallet.cpp:1183
void setRecoveringFromSeed(bool recoveringFromSeed) override
setRecoveringFromSeed - set state recover form seed
Definition: wallet.cpp:981
account_public_address addr
std::string blobdata
Definition: blobdatatype.h:39
uint64_t blockChainHeight() const override
blockChainHeight - returns current blockchain height
Definition: wallet.cpp:1006
bool createWatchOnly(const std::string &path, const std::string &password, const std::string &language) const override
createWatchOnly - Creates a watch only wallet
Definition: wallet.cpp:506
CXA_THROW_INFO_T * info
Definition: stack_trace.cpp:91
virtual double progress() const
Definition: device.hpp:73
friend class UnsignedTransactionImpl
Definition: wallet.h:221
void setRefreshFromBlockHeight(uint64_t refresh_from_block_height) override
setRefreshFromBlockHeight - start refresh from block height on recover
Definition: wallet.cpp:976
bool setDevicePassphrase(const std::string &password) override
Definition: wallet.cpp:849
POD_CLASS signature
Definition: crypto.h:108
virtual bool setRing(const std::string &key_image, const std::vector< uint64_t > &ring, bool relative) override
sets the ring used for a key image
Definition: wallet.cpp:2381
POD_CLASS hash8
Definition: hash.h:53
virtual uint32_t defaultMixin() const override
defaultMixin - returns number of mixins used in transactions
Definition: wallet.cpp:1700
virtual bool checkReserveProof(const std::string &address, const std::string &message, const std::string &signature, bool &good, uint64_t &total, uint64_t &spent) const override
Definition: wallet.cpp:1923
std::string seed() const override
Definition: wallet.cpp:790
const T & move(const T &t)
Definition: gtest-port.h:1317
int autoRefreshInterval() const override
autoRefreshInterval - returns automatic refresh interval in millis
Definition: wallet.cpp:1118
string daemon_address
Definition: transfers.cpp:42
std::string original
#define LOG_ERROR(x)
Definition: misc_log_ex.h:98
#define DEFAULT_MIX
#define PRIu64
Definition: inttypes.h:142
Definition: blake256.h:37
const std::string & status() const
std::string buff_to_hex_nodelimer(const std::string &src)
Definition: string_tools.h:87
POD_CLASS key_image
Definition: crypto.h:102
void import_blockchain(const std::tuple< size_t, crypto::hash, std::vector< crypto::hash >> &bc)
Definition: wallet2.cpp:12703
bool watchOnly() const override
watchOnly - checks if wallet is watch only
Definition: wallet.cpp:2043
void * memcpy(void *a, const void *b, size_t c)
std::string makeMultisig(const std::vector< std::string > &info, uint32_t threshold) override
makeMultisig - switches wallet in multisig state. The one and only creation phase for N / N wallets ...
Definition: wallet.cpp:1267
size_t numSubaddressAccounts() const override
numSubaddressAccounts - returns the number of existing subaddress accounts
Definition: wallet.cpp:1210
New English word list and map.
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
crypto::hash get_transaction_hash(const transaction &t)
friend class PendingTransactionImpl
Definition: wallet.h:220
bool add_extra_nonce_to_tx_extra(std::vector< uint8_t > &tx_extra, const blobdata &extra_nonce)
signed __int64 int64_t
Definition: stdint.h:135
size_t numSubaddresses(uint32_t accountIndex) const override
numSubaddresses - returns the number of existing subaddresses associated with the specified subaddres...
Definition: wallet.cpp:1214
bool get_account_address_from_str(address_parse_info &info, network_type nettype, std::string const &str)
NetworkType nettype() const override
Definition: wallet.h:132
bool synchronized() const override
synchronized - checks if wallet was ever synchronized
Definition: wallet.cpp:1072
std::string secretSpendKey() const override
secretSpendKey - returns secret spend key
Definition: wallet.cpp:884
Mnemonic seed generation and wallet restoration from them.
uint64_t balance(uint32_t accountIndex=0, bool public_blockchain=false) const override
Definition: wallet.cpp:996
bool submitTransaction(const std::string &fileName) override
submitTransaction - submits transaction in signed tx file
Definition: wallet.cpp:1140
virtual boost::optional< epee::wipeable_string > on_device_passphrase_request(bool on_device)
Definition: wallet.cpp:272
std::string publicMultisigSignerKey() const override
publicMultisigSignerKey - returns public signer key
Definition: wallet.cpp:894
int status() const override
returns wallet status (Status_Ok | Status_Error)
Definition: wallet.cpp:808
std::string to_string() const
uint64_t daemonBlockChainHeight() const override
daemonBlockChainHeight - returns daemon blockchain height
Definition: wallet.cpp:1023
virtual bool lightWalletImportWalletRequest(std::string &payment_id, uint64_t &fee, bool &new_request, bool &request_fulfilled, std::string &payment_address, std::string &status) override
Initiates a light wallet import wallet request.
Definition: wallet.cpp:951
const cryptonote::transaction & tx() const
size_t import_outputs(const std::pair< size_t, std::vector< tools::wallet2::transfer_details >> &outputs)
Definition: wallet2.cpp:12763
bool store(const std::string &path) override
store - stores wallet to file.
Definition: wallet.cpp:909
static void info(const std::string &category, const std::string &str)
Definition: wallet.cpp:407
virtual std::string getTxKey(const std::string &txid) const override
Definition: wallet.cpp:1731
POD_CLASS hash
Definition: hash.h:50
Wallet2CallbackImpl(WalletImpl *wallet)
Definition: wallet.cpp:127
#define MCDEBUG(cat, x)
Definition: misc_log_ex.h:54
std::string getSubaddressLabel(uint32_t accountIndex, uint32_t addressIndex) const override
getSubaddressLabel - gets the label of the specified subaddress
Definition: wallet.cpp:1222
std::string exchangeMultisigKeys(const std::vector< std::string > &info) override
exchange_multisig_keys - provides additional key exchange round for arbitrary multisig schemes (like ...
Definition: wallet.cpp:1284
virtual void on_lw_new_block(uint64_t height)
Definition: wallet.cpp:216
const char * address
Definition: multisig.cpp:37
virtual std::string getDefaultDataDir() const override
Definition: wallet.cpp:2227
bool secret_key_to_public_key(const secret_key &sec, public_key &pub)
Definition: crypto.h:262
const char * spendkey
Definition: multisig.cpp:38
void set_payment_id_to_tx_extra_nonce(blobdata &extra_nonce, const crypto::hash &payment_id)
#define MCINFO(cat, x)
Definition: misc_log_ex.h:53
uint64_t approximateBlockChainHeight() const override
approximateBlockChainHeight - returns approximate blockchain height calculated from date/time ...
Definition: wallet.cpp:1013
void setAutoRefreshInterval(int millis) override
setAutoRefreshInterval - setup interval for automatic refresh.
Definition: wallet.cpp:1107
virtual void on_etn_spent(uint64_t height, const crypto::hash &txid, const cryptonote::transaction &in_tx, uint64_t amount, const cryptonote::transaction &spend_tx, const cryptonote::subaddress_index &subaddr_index)
Definition: wallet.cpp:194
ConnectionStatus connected() const override
connected - checks if the wallet connected to the daemon
Definition: wallet.cpp:2021
std::vector< pending_tx > m_ptx
Definition: wallet2.h:512
virtual void on_lw_unconfirmed_etn_received(uint64_t height, const crypto::hash &txid, uint64_t amount)
Definition: wallet.cpp:231
void import_payments_out(const std::list< std::pair< crypto::hash, wallet2::confirmed_transfer_details >> &confirmed_payments)
Definition: wallet2.cpp:12682
void setSubaddressLookahead(uint32_t major, uint32_t minor) override
setSubaddressLookahead - set size of subaddress lookahead
Definition: wallet.cpp:991
PUSH_WARNINGS bool get_xtype_from_string(OUT XType &val, const std::string &str_id)
Definition: string_tools.h:125
virtual bool getRing(const std::string &key_image, std::vector< uint64_t > &ring) const override
gets the ring used for a key image, if any
Definition: wallet.cpp:2342
virtual UnsignedTransaction * loadUnsignedTx(const std::string &unsigned_filename) override
loadUnsignedTx - creates transaction from unsigned tx file
Definition: wallet.cpp:1123
virtual void on_device_button_pressed()
Definition: wallet.cpp:254
std::string filename() const override
filename - returns wallet filename
Definition: wallet.cpp:927
error
Tracks LMDB error codes.
Definition: error.h:44
std::string keysFilename() const override
keysFilename - returns keys filename. usually this formed as "wallet_filename".keys ...
Definition: wallet.cpp:932
#define ELECTRONEUM_DEFAULT_LOG_CATEGORY
Definition: wallet.cpp:59
virtual Subaddress * subaddress() override
Definition: wallet.cpp:1684
#define CORE_RPC_VERSION_MAJOR
bool parse_hexstr_to_binbuff(const epee::span< const char > s, epee::span< char > &res)
Definition: string_tools.h:92
void generate(const std::string &wallet_, const epee::wipeable_string &password, const epee::wipeable_string &multisig_data, bool create_address_file=false)
Generates a wallet or restores one.
Definition: wallet2.cpp:4869
void addSubaddressAccount(const std::string &label) override
addSubaddressAccount - appends a new subaddress account at the end of the last major index of existin...
Definition: wallet.cpp:1206
virtual uint64_t coldKeyImageSync(uint64_t &spent, uint64_t &unspent) override
cold-device protocol key image sync
Definition: wallet.cpp:2428
std::string path() const override
Definition: wallet.cpp:904
void import_payments(const payment_container &payments)
Definition: wallet2.cpp:12674
bool multisig(bool *ready=NULL, uint32_t *threshold=NULL, uint32_t *total=NULL) const
Definition: wallet2.cpp:5634
friend class SubaddressImpl
Definition: wallet.h:225
Interface for wallet operations. TODO: check if /include/IWallet.h is still actual.
Definition: wallet2_api.h:430
uint8_t threshold
Definition: blockchain.cpp:92