Electroneum
Loading...
Searching...
No Matches
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"
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
55using namespace std;
56using namespace cryptonote;
57
58#undef ELECTRONEUM_DEFAULT_LOG_CATEGORY
59#define ELECTRONEUM_DEFAULT_LOG_CATEGORY "WalletAPI"
60
61namespace Electroneum {
62
63namespace {
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
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
165 std::string tx_hash = epee::string_tools::pod_to_hex(txid);
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
181 std::string tx_hash = epee::string_tools::pod_to_hex(txid);
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;
198 std::string tx_hash = epee::string_tools::pod_to_hex(txid);
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) {
226 std::string tx_hash = epee::string_tools::pod_to_hex(txid);
227 m_listener->etnReceived(tx_hash, amount);
228 }
229 }
230
232 {
233 if (m_listener) {
234 std::string tx_hash = epee::string_tools::pod_to_hex(txid);
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) {
242 std::string tx_hash = epee::string_tools::pod_to_hex(txid);
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
295
297
298
300{
301 return cryptonote::print_etn(amount);
302}
303
305{
306 uint64_t result = 0;
307 cryptonote::parse_amount(result, amount);
308 return result;
309}
310
312{
313 std::stringstream ss;
314 ss << std::fixed << std::setprecision(CRYPTONOTE_DISPLAY_DECIMAL_POINT) << amount;
315 return amountFromString(ss.str());
316}
317
319{
321 return epee::string_tools::pod_to_hex(payment_id);
322
323}
324
325bool 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
341
342bool 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
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
378std::string Wallet::paymentIdFromAddress(const std::string &str, NetworkType nettype)
379{
382 return "";
383 if (!info.has_payment_id)
384 return "";
385 return epee::string_tools::pod_to_hex(info.payment_id);
386}
387
389{
390 return std::numeric_limits<uint64_t>::max();
391}
392
393void 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
403void Wallet::debug(const std::string &category, const std::string &str) {
404 MCDEBUG(category.empty() ? ELECTRONEUM_DEFAULT_LOG_CATEGORY : category.c_str(), str);
405}
406
407void Wallet::info(const std::string &category, const std::string &str) {
408 MCINFO(category.empty() ? ELECTRONEUM_DEFAULT_LOG_CATEGORY : category.c_str(), str);
409}
410
411void Wallet::warning(const std::string &category, const std::string &str) {
412 MCWARNING(category.empty() ? ELECTRONEUM_DEFAULT_LOG_CATEGORY : category.c_str(), str);
413}
414
415void Wallet::error(const std::string &category, const std::string &str) {
416 MCERROR(category.empty() ? ELECTRONEUM_DEFAULT_LOG_CATEGORY : category.c_str(), str);
417}
418
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
469bool 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.";
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
506bool 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.";
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
572bool WalletImpl::recoverFromKeys(const std::string &path,
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
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
677bool 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
699bool 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
725bool WalletImpl::recover(const std::string &path, const std::string &seed)
726{
727 return recover(path, "", seed);
728}
729
730bool 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
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
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
790std::string WalletImpl::seed() const
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
803void WalletImpl::setSeedLanguage(const std::string &arg)
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
814std::string WalletImpl::errorString() const
815{
816 boost::lock_guard<boost::mutex> l(m_statusMutex);
817 return m_errorString;
818}
819
821 boost::lock_guard<boost::mutex> l(m_statusMutex);
822 status = m_status;
823 errorString = m_errorString;
824}
825
826bool WalletImpl::setPassword(const std::string &password)
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
838bool WalletImpl::setDevicePin(const std::string &pin)
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
849bool WalletImpl::setDevicePassphrase(const std::string &passphrase)
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
860std::string WalletImpl::address(uint32_t accountIndex, uint32_t addressIndex) const
861{
862 return m_wallet->get_subaddress_as_str({accountIndex, addressIndex});
863}
864
865std::string WalletImpl::integratedAddress(const std::string &payment_id) const
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
874std::string WalletImpl::secretViewKey() const
875{
876 return epee::string_tools::pod_to_hex(m_wallet->get_account().get_keys().m_view_secret_key);
877}
878
879std::string WalletImpl::publicViewKey() const
880{
881 return epee::string_tools::pod_to_hex(m_wallet->get_account().get_keys().m_account_address.m_view_public_key);
882}
883
884std::string WalletImpl::secretSpendKey() const
885{
886 return epee::string_tools::pod_to_hex(m_wallet->get_account().get_keys().m_spend_secret_key);
887}
888
889std::string WalletImpl::publicSpendKey() const
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
904std::string WalletImpl::path() const
905{
906 return m_wallet->path();
907}
908
909bool WalletImpl::store(const std::string &path)
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
928{
929 return m_wallet->get_wallet_file();
930}
931
933{
934 return m_wallet->get_keys_file();
935}
936
937bool 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
946bool WalletImpl::lightWalletLogin(bool &isNewWallet) const
947{
948 return m_wallet->light_wallet_login(isNewWallet);
949}
950
951bool 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
976void WalletImpl::setRefreshFromBlockHeight(uint64_t refresh_from_block_height)
977{
978 m_wallet->set_refresh_from_block_height(refresh_from_block_height);
979}
980
981void WalletImpl::setRecoveringFromSeed(bool recoveringFromSeed)
982{
983 m_recoveringFromSeed = recoveringFromSeed;
984}
985
986void WalletImpl::setRecoveringFromDevice(bool recoveringFromDevice)
987{
988 m_recoveringFromDevice = recoveringFromDevice;
989}
990
992{
993 m_wallet->set_subaddress_lookahead(major, minor);
994}
995
996uint64_t WalletImpl::balance(uint32_t accountIndex, bool public_blockchain) const
997{
998 return m_wallet->balance(accountIndex, public_blockchain);
999}
1000
1001uint64_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
1064bool 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
1123UnsignedTransaction *WalletImpl::loadUnsignedTx(const std::string &unsigned_filename) {
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
1140bool 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
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
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
1206void WalletImpl::addSubaddressAccount(const std::string& label)
1207{
1208 m_wallet->add_subaddress_account(label);
1209}
1211{
1212 return m_wallet->get_num_subaddress_accounts();
1213}
1214size_t WalletImpl::numSubaddresses(uint32_t accountIndex) const
1215{
1216 return m_wallet->get_num_subaddresses(accountIndex);
1217}
1218void WalletImpl::addSubaddress(uint32_t accountIndex, const std::string& label)
1219{
1220 m_wallet->add_subaddress(accountIndex, label);
1221}
1222std::string WalletImpl::getSubaddressLabel(uint32_t accountIndex, uint32_t addressIndex) const
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}
1235void 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
1267string 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
1284std::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
1298bool 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
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
1332size_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;
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
1412PendingTransaction *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
1710bool 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
1721std::string WalletImpl::getUserNote(const std::string &txid) const
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
1731std::string WalletImpl::getTxKey(const std::string &txid_str) const
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
1758bool 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
1806std::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
1834bool 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
1863std::string WalletImpl::getSpendProof(const std::string &txid_str, const std::string &message) const {
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
1883bool 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
1905std::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
1923bool 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
1950std::string WalletImpl::signMessage(const std::string &message)
1951{
1952 return m_wallet->sign(message);
1953}
1954
1955bool WalletImpl::verifySignedMessage(const std::string &message, const std::string &address, const std::string &signature) const
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
1965std::string WalletImpl::signMultisigParticipant(const std::string &message) const
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
1986bool WalletImpl::verifyMessageWithPublicKey(const std::string &message, const std::string &publicKey, const std::string &signature) const
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
2048void WalletImpl::clearStatus() const
2049{
2050 boost::lock_guard<boost::mutex> l(m_statusMutex);
2051 m_status = Status_Ok;
2052 m_errorString.clear();
2053}
2054
2055void WalletImpl::setStatusError(const std::string& message) const
2056{
2057 setStatus(Status_Error, message);
2058}
2059
2060void WalletImpl::setStatusCritical(const std::string& message) const
2061{
2062 setStatus(Status_Critical, message);
2063}
2064
2065void 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
2072void 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
2103void 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
2151void 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
2171bool 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
2181void 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
2196bool 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
2222bool 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{
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
2250void 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
2260bool 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
2298bool 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
2320bool 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
2342bool 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
2359bool 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
2381bool 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
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
2434namespace Bitelectroneum = Electroneum;
uint64_t height
uint8_t version
uint8_t threshold
virtual std::string signMultisigParticipant(const std::string &message) const override
signMultisigParticipant signs given message with the multisig public signer key
Definition wallet.cpp:1965
friend class SubaddressAccountImpl
Definition wallet.h:226
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 AddressBook * addressBook() override
Definition wallet.cpp:1679
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 SubaddressAccount * subaddressAccount() override
Definition wallet.cpp:1689
int status() const override
returns wallet status (Status_Ok | Status_Error)
Definition wallet.cpp:808
virtual UnsignedTransaction * loadUnsignedTx(const std::string &unsigned_filename) override
loadUnsignedTx - creates transaction from unsigned tx file
Definition wallet.cpp:1123
std::string path() const override
Definition wallet.cpp:904
void hardForkInfo(uint8_t &version, uint64_t &earliest_height) const override
returns current hard fork info
Definition wallet.cpp:2250
size_t numSubaddressAccounts() const override
numSubaddressAccounts - returns the number of existing subaddress accounts
Definition wallet.cpp:1210
void rescanBlockchainAsync() override
rescanBlockchainAsync - rescans wallet asynchronously, starting from genesys
Definition wallet.cpp:1101
friend class SubaddressImpl
Definition wallet.h:225
virtual uint64_t coldKeyImageSync(uint64_t &spent, uint64_t &unspent) override
cold-device protocol key image sync
Definition wallet.cpp:2428
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
bool synchronized() const override
synchronized - checks if wallet was ever synchronized
Definition wallet.cpp:1072
virtual std::string getTxKey(const std::string &txid) const override
Definition wallet.cpp:1731
uint64_t daemonBlockChainTargetHeight() const override
daemonBlockChainTargetHeight - returns daemon blockchain target height
Definition wallet.cpp:1042
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
bool open(const std::string &path, const std::string &password)
Definition wallet.cpp:699
bool trustedDaemon() const override
Definition wallet.cpp:2038
virtual void segregatePreForkOutputs(bool segregate) override
sets whether pre-fork outs are to be segregated
Definition wallet.cpp:2398
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 startRefresh() override
StartRefresh - Start/resume refresh thread (refresh every 10 seconds).
Definition wallet.cpp:2140
bool setPassword(const std::string &password) override
Definition wallet.cpp:826
bool recover(const std::string &path, const std::string &password, const std::string &seed)
Definition wallet.cpp:730
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
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
bool setDevicePassphrase(const std::string &password) override
Definition wallet.cpp:849
virtual uint32_t defaultMixin() const override
defaultMixin - returns number of mixins used in transactions
Definition wallet.cpp:1700
std::string publicMultisigSignerKey() const override
publicMultisigSignerKey - returns public signer key
Definition wallet.cpp:894
bool store(const std::string &path) override
store - stores wallet to file.
Definition wallet.cpp:909
bool importKeyImages(const std::string &filename) override
importKeyImages - imports key images from file
Definition wallet.cpp:1183
virtual void segregationHeight(uint64_t height) override
sets the height where segregation should occur
Definition wallet.cpp:2403
std::string secretViewKey() const override
secretViewKey - returns secret view key
Definition wallet.cpp:874
uint64_t approximateBlockChainHeight() const override
approximateBlockChainHeight - returns approximate blockchain height calculated from date/time
Definition wallet.cpp:1013
virtual void disposeTransaction(PendingTransaction *t) override
disposeTransaction - destroys transaction object
Definition wallet.cpp:1669
virtual Subaddress * subaddress() override
Definition wallet.cpp:1684
uint64_t unlockedBalance(uint32_t accountIndex=0, bool public_blockchain=false) const override
Definition wallet.cpp:1001
bool rescanBlockchain() override
rescanBlockchain - rescans the wallet, updating transactions from daemon
Definition wallet.cpp:1093
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
bool setDevicePin(const std::string &password) override
Definition wallet.cpp:838
PendingTransaction * restoreMultisigTransaction(const std::string &signData) override
restoreMultisigTransaction creates PendingTransaction from signData
Definition wallet.cpp:1374
std::string keysFilename() const override
keysFilename - returns keys filename. usually this formed as "wallet_filename".keys
Definition wallet.cpp:932
void setSubaddressLookahead(uint32_t major, uint32_t minor) override
setSubaddressLookahead - set size of subaddress lookahead
Definition wallet.cpp:991
virtual bool checkSpendProof(const std::string &txid, const std::string &message, const std::string &signature, bool &good) const override
Definition wallet.cpp:1883
virtual std::string getTxProof(const std::string &txid, const std::string &address, const std::string &message) const override
Definition wallet.cpp:1806
NetworkType nettype() const override
Definition wallet.h:132
virtual bool lockKeysFile() override
locks/unlocks the keys file; returns true on success
Definition wallet.cpp:2413
int autoRefreshInterval() const override
autoRefreshInterval - returns automatic refresh interval in millis
Definition wallet.cpp:1118
WalletImpl(NetworkType nettype=MAINNET, uint64_t kdf_rounds=1)
Definition wallet.cpp:420
virtual std::string getSpendProof(const std::string &txid, const std::string &message) const override
Definition wallet.cpp:1863
friend class PendingTransactionImpl
Definition wallet.h:220
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
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
bool hasMultisigPartialKeyImages() const override
hasMultisigPartialKeyImages - checks if wallet needs to import multisig key images from other partici...
Definition wallet.cpp:1360
friend struct Wallet2CallbackImpl
Definition wallet.h:223
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
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
virtual bool unblackballOutput(const std::string &amount, const std::string &offset) override
unblackballs an output
Definition wallet.cpp:2320
void setRefreshFromBlockHeight(uint64_t refresh_from_block_height) override
setRefreshFromBlockHeight - start refresh from block height on recover
Definition wallet.cpp:976
Device getDeviceType() const override
Queries backing device for wallet keys.
Definition wallet.cpp:694
virtual bool blackballOutput(const std::string &amount, const std::string &offset) override
blackballs an output
Definition wallet.cpp:2298
virtual std::string getUserNote(const std::string &txid) const override
getUserNote - return an arbitrary string note attached to a txid
Definition wallet.cpp:1721
bool watchOnly() const override
watchOnly - checks if wallet is watch only
Definition wallet.cpp:2043
virtual void keyReuseMitigation2(bool mitigation) override
secondary key reuse mitigation
Definition wallet.cpp:2408
virtual bool blackballOutputs(const std::vector< std::string > &outputs, bool add) override
blackballs a set of outputs
Definition wallet.cpp:2260
std::string publicViewKey() const override
publicViewKey - returns public view key
Definition wallet.cpp:879
void setRecoveringFromSeed(bool recoveringFromSeed) override
setRecoveringFromSeed - set state recover form seed
Definition wallet.cpp:981
uint64_t balance(uint32_t accountIndex=0, bool public_blockchain=false) const override
Definition wallet.cpp:996
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
std::string getSeedLanguage() const override
Definition wallet.cpp:798
std::string errorString() const override
in case error status, returns error string
Definition wallet.cpp:814
bool refresh() override
refresh - refreshes the wallet, updating transactions from daemon
Definition wallet.cpp:1077
std::string getSubaddressLabel(uint32_t accountIndex, uint32_t addressIndex) const override
getSubaddressLabel - gets the label of the specified subaddress
Definition wallet.cpp:1222
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::string getMultisigInfo() const override
getMultisigInfo
Definition wallet.cpp:1255
uint64_t estimateBlockChainHeight() const override
estimateBlockChainHeight - returns estimate blockchain height. More accurate than approximateBlockCha...
Definition wallet.cpp:1018
void setSeedLanguage(const std::string &arg) override
Definition wallet.cpp:803
virtual void setListener(WalletListener *l) override
Definition wallet.cpp:1694
bool useForkRules(uint8_t version, int64_t early_blocks) const override
check if hard fork rules should be used
Definition wallet.cpp:2255
bool recoverFromDevice(const std::string &path, const std::string &password, const std::string &device_name)
Definition wallet.cpp:677
uint64_t daemonBlockChainHeight() const override
daemonBlockChainHeight - returns daemon blockchain height
Definition wallet.cpp:1023
virtual bool unlockKeysFile() override
Definition wallet.cpp:2418
std::string secretSpendKey() const override
secretSpendKey - returns secret spend key
Definition wallet.cpp:884
bool close(bool store=true)
Definition wallet.cpp:762
std::string address(uint32_t accountIndex=0, uint32_t addressIndex=0) const override
Definition wallet.cpp:860
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
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
friend class UnsignedTransactionImpl
Definition wallet.h:221
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
void setTrustedDaemon(bool arg) override
Definition wallet.cpp:2033
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
void refreshAsync() override
refreshAsync - refreshes wallet asynchronously.
Definition wallet.cpp:1086
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
friend class TransactionHistoryImpl
Definition wallet.h:222
virtual bool lightWalletLogin(bool &isNewWallet) const override
Light wallet authenticate and login.
Definition wallet.cpp:946
bool rescanSpent() override
Definition wallet.cpp:2232
bool create(const std::string &path, const std::string &password, const std::string &language)
Definition wallet.cpp:469
virtual PendingTransaction * createSweepUnmixableTransaction() override
createSweepUnmixableTransaction creates transaction with unmixable outputs.
Definition wallet.cpp:1587
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
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
ConnectionStatus connected() const override
connected - checks if the wallet connected to the daemon
Definition wallet.cpp:2021
friend class AddressBookImpl
Definition wallet.h:224
void setRecoveringFromDevice(bool recoveringFromDevice) override
setRecoveringFromDevice - set state to recovering from device
Definition wallet.cpp:986
virtual void pauseRefresh() override
pauseRefresh - pause refresh thread
Definition wallet.cpp:2161
virtual std::string signMessage(const std::string &message) override
Definition wallet.cpp:1950
uint64_t blockChainHeight() const override
blockChainHeight - returns current blockchain height
Definition wallet.cpp:1006
bool submitTransaction(const std::string &fileName) override
submitTransaction - submits transaction in signed tx file
Definition wallet.cpp:1140
bool exportMultisigImages(std::string &images) override
exportMultisigImages - exports transfers' key images
Definition wallet.cpp:1316
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
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
MultisigState multisig() const override
multisig - returns current state of multisig wallet creation process
Definition wallet.cpp:1248
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
virtual void setDefaultMixin(uint32_t arg) override
setDefaultMixin - setum number of mixins to be used for new transactions
Definition wallet.cpp:1705
bool finalizeMultisig(const std::vector< std::string > &extraMultisigInfo) override
finalizeMultisig - finalizes N - 1 / N multisig wallets creation
Definition wallet.cpp:1298
std::string filename() const override
filename - returns wallet filename
Definition wallet.cpp:927
virtual TransactionHistory * history() override
Definition wallet.cpp:1674
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 connectToDaemon() override
connectToDaemon - connects to the daemon. TODO: check if it can be removed
Definition wallet.cpp:2009
std::string seed() const override
Definition wallet.cpp:790
bool exportKeyImages(const std::string &filename) override
exportKeyImages - exports key images to file
Definition wallet.cpp:1158
virtual bool isKeysFileLocked() override
returns true if the keys file is locked
Definition wallet.cpp:2423
void setAutoRefreshInterval(int millis) override
setAutoRefreshInterval - setup interval for automatic refresh.
Definition wallet.cpp:1107
virtual std::string getDefaultDataDir() const override
Definition wallet.cpp:2227
std::string publicSpendKey() const override
publicSpendKey - returns public spend key
Definition wallet.cpp:889
size_t importMultisigImages(const std::vector< std::string > &images) override
importMultisigImages - imports other participants' multisig images
Definition wallet.cpp:1332
const std::string & get_language_name() const
Returns the name of the language.
hw::device & get_device() const
Definition account.h:91
virtual bool indeterminate() const
Definition device.hpp:74
virtual double progress() const
Definition device.hpp:73
virtual bool has_tx_cold_sign(void) const
Definition device.hpp:244
cryptonote::account_base & get_account()
Definition wallet2.h:734
static bool parse_long_payment_id(const std::string &payment_id_str, crypto::hash &payment_id)
Definition wallet2.cpp:5712
bool multisig(bool *ready=NULL, uint32_t *threshold=NULL, uint32_t *total=NULL) const
Definition wallet2.cpp:5634
static bool parse_short_payment_id(const std::string &payment_id_str, crypto::hash8 &payment_id)
Definition wallet2.cpp:5725
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
#define tr(x)
#define CORE_RPC_VERSION_MAJOR
#define CRYPTONOTE_DISPLAY_DECIMAL_POINT
#define DEFAULT_MIX
std::string publicKey
std::string message("Message requiring signing")
Mnemonic seed generation and wallet restoration from them.
New English word list and map.
void * memcpy(void *a, const void *b, size_t c)
const char * key
#define PRIu64
Definition inttypes.h:142
#define MCERROR(cat, x)
Definition misc_log_ex.h:51
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
#define LOG_PRINT_L3(x)
#define ELECTRONEUM_DEFAULT_LOG_CATEGORY
Definition misc_log_ex.h:36
std::string mlog_get_default_log_path(const char *default_filename)
Definition mlog.cpp:72
#define MCINFO(cat, x)
Definition misc_log_ex.h:53
#define MCWARNING(cat, x)
Definition misc_log_ex.h:52
#define LOG_PRINT_L1(x)
#define LOG_ERROR(x)
Definition misc_log_ex.h:98
#define LOG_PRINT_L2(x)
#define MCDEBUG(cat, x)
Definition misc_log_ex.h:54
bool isAddressLocal(const std::string &address)
Definition utils.cpp:42
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).
const std::string old_language_name
std::enable_if< std::is_pod< T >::value, T >::type rand()
Definition crypto.h:216
epee::mlocked< tools::scrubbed< ec_scalar > > secret_key
Definition crypto.h:82
POD_CLASS hash8
Definition hash.h:53
POD_CLASS public_key
Definition crypto.h:79
POD_CLASS key_image
Definition crypto.h:105
bool secret_key_to_public_key(const secret_key &sec, public_key &pub)
Definition crypto.h:262
POD_CLASS hash
Definition hash.h:50
Holds cryptonote related classes and helpers.
Definition ban.cpp:40
void set_payment_id_to_tx_extra_nonce(blobdata &extra_nonce, const crypto::hash &payment_id)
bool get_account_address_from_str(address_parse_info &info, network_type nettype, std::string const &str)
crypto::hash get_transaction_hash(const transaction &t)
std::string blobdata
bool parse_amount(uint64_t &amount, const std::string &str_amount_)
std::string print_etn(uint64_t amount, unsigned int decimal_point)
bool add_extra_nonce_to_tx_extra(std::vector< uint8_t > &tx_extra, const blobdata &extra_nonce)
bool set_module_name_and_folder(const std::string &path_to_process_)
bool parse_hexstr_to_binbuff(const epee::span< const char > s, epee::span< char > &res)
std::string pod_to_hex(const t_pod_type &s)
bool hex_to_pod(const std::string &hex_str, t_pod_type &s)
PUSH_WARNINGS bool get_xtype_from_string(OUT XType &val, const std::string &str_id)
std::string buff_to_hex_nodelimer(const std::string &src)
STL namespace.
failed_rpc_request< transfer_error, get_outs_error_message_index > get_outs_error
std::string get_default_data_dir()
Returns the default data directory.
Definition util.cpp:600
#define false
signed __int64 int64_t
Definition stdint.h:135
unsigned int uint32_t
Definition stdint.h:126
unsigned char uint8_t
Definition stdint.h:124
unsigned __int64 uint64_t
Definition stdint.h:136
The AddressBook - interface for Book.
Transaction-like interface for sending etn.
Definition wallet2_api.h:73
The TransactionHistory - interface for displaying transaction history.
Transaction-like interface for sending etn.
void setListener(WalletListener *listener)
Definition wallet.cpp:139
virtual void on_lw_etn_spent(uint64_t height, const crypto::hash &txid, uint64_t amount)
Definition wallet.cpp:239
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 void on_device_button_pressed()
Definition wallet.cpp:254
virtual boost::optional< epee::wipeable_string > on_device_passphrase_request(bool on_device)
Definition wallet.cpp:272
Wallet2CallbackImpl(WalletImpl *wallet)
Definition wallet.cpp:127
virtual void on_device_progress(const hw::device_progress &event)
Definition wallet.cpp:283
virtual void on_lw_etn_received(uint64_t height, const crypto::hash &txid, uint64_t amount)
Definition wallet.cpp:223
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
virtual void on_lw_unconfirmed_etn_received(uint64_t height, const crypto::hash &txid, uint64_t amount)
Definition wallet.cpp:231
virtual boost::optional< epee::wipeable_string > on_device_pin_request()
Definition wallet.cpp:261
virtual void on_skip_transaction(uint64_t height, const crypto::hash &txid, const cryptonote::transaction &tx)
Definition wallet.cpp:210
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_new_block(uint64_t height, const cryptonote::block &block)
Definition wallet.cpp:149
virtual void on_device_button_request(uint64_t code)
Definition wallet.cpp:247
virtual void on_lw_new_block(uint64_t height)
Definition wallet.cpp:216
WalletListener * getListener() const
Definition wallet.cpp:144
Interface for wallet operations. TODO: check if /include/IWallet.h is still actual.
static void debug(const std::string &category, const std::string &str)
Definition wallet.cpp:403
static uint64_t amountFromDouble(double amount)
Definition wallet.cpp:311
static void error(const std::string &category, const std::string &str)
Definition wallet.cpp:415
static void info(const std::string &category, const std::string &str)
Definition wallet.cpp:407
static std::string displayAmount(uint64_t amount)
Definition wallet.cpp:299
virtual 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)=0
init - initializes wallet with daemon connection params. if daemon_address is local address,...
static bool keyValid(const std::string &secret_key_string, const std::string &address_string, bool isViewKey, NetworkType nettype, std::string &error)
Definition wallet.cpp:342
static uint64_t maximumAllowedAmount()
Definition wallet.cpp:388
static uint64_t amountFromString(const std::string &amount)
Definition wallet.cpp:304
static void warning(const std::string &category, const std::string &str)
Definition wallet.cpp:411
static std::string genPaymentId()
Definition wallet.cpp:318
virtual ~Wallet()=0
Definition wallet.cpp:294
static bool paymentIdValid(const std::string &paiment_id)
Definition wallet.cpp:325
static std::string paymentIdFromAddress(const std::string &str, NetworkType nettype)
Definition wallet.cpp:378
static bool addressValid(const std::string &str, NetworkType nettype)
Definition wallet.cpp:336
virtual NetworkType nettype() const =0
bool is_subaddress
bool is_integrated
std::string original
uint64_t amount
account_public_address addr
epee::misc_utils::struct_init< response_t > response
std::string to_string() const
std::unordered_set< crypto::public_key > m_signers
Definition wallet2.h:513
std::vector< pending_tx > m_ptx
Definition wallet2.h:512
std::vector< crypto::key_image > key_images
Definition wallet2.h:506
std::vector< pending_tx > ptx
Definition wallet2.h:505
const char * spendkey
Definition multisig.cpp:38
string daemon_address
Definition transfers.cpp:42