diff --git a/src/device/device.hpp b/src/device/device.hpp index dd9ad4332..3e782d21a 100644 --- a/src/device/device.hpp +++ b/src/device/device.hpp @@ -80,6 +80,14 @@ namespace hw { return false; } + class i_device_callback { + public: + virtual void on_button_request() {} + virtual void on_pin_request(epee::wipeable_string & pin) {} + virtual void on_passphrase_request(bool on_device, epee::wipeable_string & passphrase) {} + virtual ~i_device_callback() = default; + }; + class device { protected: std::string name; @@ -129,6 +137,7 @@ namespace hw { virtual device_type get_type() const = 0; virtual device_protocol_t device_protocol() const { return PROTOCOL_DEFAULT; }; + virtual void set_callback(i_device_callback * callback) {}; /* ======================================================================= */ /* LOCKER */ diff --git a/src/device_trezor/device_trezor_base.cpp b/src/device_trezor/device_trezor_base.cpp index 38c20c30b..dcfc9cb67 100644 --- a/src/device_trezor/device_trezor_base.cpp +++ b/src/device_trezor/device_trezor_base.cpp @@ -39,7 +39,7 @@ namespace trezor { const uint32_t device_trezor_base::DEFAULT_BIP44_PATH[] = {0x8000002c, 0x80000080, 0x80000000}; - device_trezor_base::device_trezor_base() { + device_trezor_base::device_trezor_base(): m_callback(nullptr) { } @@ -332,10 +332,6 @@ namespace trezor { MDEBUG("on_passhprase_state_request"); CHECK_AND_ASSERT_THROW_MES(msg, "Empty message"); - if (m_callback){ - m_callback->on_passphrase_state_request(msg->state()); - } - messages::common::PassphraseStateAck m; resp = call_raw(&m); } diff --git a/src/device_trezor/device_trezor_base.hpp b/src/device_trezor/device_trezor_base.hpp index 88d419494..a4e92bf78 100644 --- a/src/device_trezor/device_trezor_base.hpp +++ b/src/device_trezor/device_trezor_base.hpp @@ -57,17 +57,6 @@ namespace trezor { #ifdef WITH_DEVICE_TREZOR class device_trezor_base; - /** - * Trezor device callbacks - */ - class trezor_callback { - public: - virtual void on_button_request() {}; - virtual void on_pin_request(epee::wipeable_string & pin) {}; - virtual void on_passphrase_request(bool on_device, epee::wipeable_string & passphrase) {}; - virtual void on_passphrase_state_request(const std::string & state) {}; - }; - /** * TREZOR device template with basic functions */ @@ -79,7 +68,7 @@ namespace trezor { mutable boost::mutex command_locker; std::shared_ptr m_transport; - std::shared_ptr m_callback; + i_device_callback * m_callback; std::string full_name; @@ -218,7 +207,11 @@ namespace trezor { return m_transport; } - std::shared_ptr getCallback(){ + void set_callback(i_device_callback * callback) override { + m_callback = callback; + } + + i_device_callback * get_callback(){ return m_callback; } diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index d9fd0c13e..6d19235c5 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -3786,6 +3786,7 @@ boost::optional simple_wallet::new_wallet(const boost::pr { auto rc = tools::wallet2::make_new(vm, false, password_prompter); m_wallet = std::move(rc.first); + m_wallet->callback(this); if (!m_wallet) { return {}; @@ -3893,7 +3894,7 @@ bool simple_wallet::open_wallet(const boost::program_options::variables_map& vm) epee::wipeable_string password; try { - auto rc = tools::wallet2::make_from_file(vm, false, m_wallet_file, password_prompter); + auto rc = tools::wallet2::make_from_file(vm, false, "", password_prompter); m_wallet = std::move(rc.first); password = std::move(std::move(rc.second).password()); if (!m_wallet) @@ -3901,6 +3902,8 @@ bool simple_wallet::open_wallet(const boost::program_options::variables_map& vm) return false; } + m_wallet->callback(this); + m_wallet->load(m_wallet_file, password); std::string prefix; bool ready; uint32_t threshold, total; @@ -4304,6 +4307,38 @@ boost::optional simple_wallet::on_get_password(const char return pwd_container->password(); } //---------------------------------------------------------------------------------------------------- +void simple_wallet::on_button_request() +{ + message_writer(console_color_white, false) << tr("Device requires attention"); +} +//---------------------------------------------------------------------------------------------------- +void simple_wallet::on_pin_request(epee::wipeable_string & pin) +{ +#ifdef HAVE_READLINE + rdln::suspend_readline pause_readline; +#endif + std::string msg = tr("Enter device PIN"); + auto pwd_container = tools::password_container::prompt(false, msg.c_str()); + THROW_WALLET_EXCEPTION_IF(!pwd_container, tools::error::password_entry_failed, tr("Failed to read device PIN")); + pin = pwd_container->password(); +} +//---------------------------------------------------------------------------------------------------- +void simple_wallet::on_passphrase_request(bool on_device, epee::wipeable_string & passphrase) +{ + if (on_device){ + message_writer(console_color_white, true) << tr("Please enter the device passphrase on the device"); + return; + } + +#ifdef HAVE_READLINE + rdln::suspend_readline pause_readline; +#endif + std::string msg = tr("Enter device passphrase"); + auto pwd_container = tools::password_container::prompt(false, msg.c_str()); + THROW_WALLET_EXCEPTION_IF(!pwd_container, tools::error::password_entry_failed, tr("Failed to read device passphrase")); + passphrase = pwd_container->password(); +} +//---------------------------------------------------------------------------------------------------- bool simple_wallet::refresh_main(uint64_t start_height, enum ResetType reset, bool is_init) { if (!try_connect_to_daemon(is_init)) diff --git a/src/simplewallet/simplewallet.h b/src/simplewallet/simplewallet.h index 421afbeda..7e2edba7f 100644 --- a/src/simplewallet/simplewallet.h +++ b/src/simplewallet/simplewallet.h @@ -287,6 +287,9 @@ namespace cryptonote virtual void on_money_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); virtual void on_skip_transaction(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& tx); virtual boost::optional on_get_password(const char *reason); + virtual void on_button_request(); + virtual void on_pin_request(epee::wipeable_string & pin); + virtual void on_passphrase_request(bool on_device, epee::wipeable_string & passphrase); //---------------------------------------------------------- friend class refresh_progress_reporter_t; diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 49aef4350..ae6ed0937 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -818,6 +818,24 @@ wallet_keys_unlocker::~wallet_keys_unlocker() w.encrypt_keys(key); } +void wallet_device_callback::on_button_request() +{ + if (wallet) + wallet->on_button_request(); +} + +void wallet_device_callback::on_pin_request(epee::wipeable_string & pin) +{ + if (wallet) + wallet->on_pin_request(pin); +} + +void wallet_device_callback::on_passphrase_request(bool on_device, epee::wipeable_string & passphrase) +{ + if (wallet) + wallet->on_passphrase_request(on_device, passphrase); +} + wallet2::wallet2(network_type nettype, uint64_t kdf_rounds, bool unattended): m_multisig_rescan_info(NULL), m_multisig_rescan_k(NULL), @@ -929,7 +947,7 @@ std::pair, password_container> wallet2::make_from_file( return {nullptr, password_container{}}; } auto wallet = make_basic(vm, unattended, opts, password_prompter); - if (wallet) + if (wallet && !wallet_file.empty()) { wallet->load(wallet_file, pwd->password()); } @@ -1071,15 +1089,16 @@ bool wallet2::reconnect_device() hw::device &hwdev = lookup_device(m_device_name); hwdev.set_name(m_device_name); hwdev.set_network_type(m_nettype); + hwdev.set_callback(get_device_callback()); r = hwdev.init(); if (!r){ - LOG_PRINT_L2("Could not init device"); + MERROR("Could not init device"); return false; } r = hwdev.connect(); if (!r){ - LOG_PRINT_L2("Could not connect to the device"); + MERROR("Could not connect to the device"); return false; } @@ -3441,6 +3460,7 @@ bool wallet2::load_keys(const std::string& keys_file_name, const epee::wipeable_ hw::device &hwdev = lookup_device(m_device_name); THROW_WALLET_EXCEPTION_IF(!hwdev.set_name(m_device_name), error::wallet_internal_error, "Could not set device name " + m_device_name); hwdev.set_network_type(m_nettype); + hwdev.set_callback(get_device_callback()); THROW_WALLET_EXCEPTION_IF(!hwdev.init(), error::wallet_internal_error, "Could not initialize the device " + m_device_name); THROW_WALLET_EXCEPTION_IF(!hwdev.connect(), error::wallet_internal_error, "Could not connect to the device " + m_device_name); m_account.set_device(hwdev); @@ -3947,6 +3967,7 @@ void wallet2::restore(const std::string& wallet_, const epee::wipeable_string& p auto &hwdev = lookup_device(device_name); hwdev.set_name(device_name); hwdev.set_network_type(m_nettype); + hwdev.set_callback(get_device_callback()); m_account.create_from_device(hwdev); m_key_device_type = m_account.get_device().get_type(); @@ -11940,4 +11961,29 @@ uint64_t wallet2::get_segregation_fork_height() const void wallet2::generate_genesis(cryptonote::block& b) const { cryptonote::generate_genesis_block(b, get_config(m_nettype).GENESIS_TX, get_config(m_nettype).GENESIS_NONCE); } +//---------------------------------------------------------------------------------------------------- +wallet_device_callback * wallet2::get_device_callback() +{ + if (!m_device_callback){ + m_device_callback.reset(new wallet_device_callback(this)); + } + return m_device_callback.get(); +}//---------------------------------------------------------------------------------------------------- +void wallet2::on_button_request() +{ + if (0 != m_callback) + m_callback->on_button_request(); +} +//---------------------------------------------------------------------------------------------------- +void wallet2::on_pin_request(epee::wipeable_string & pin) +{ + if (0 != m_callback) + m_callback->on_pin_request(pin); +} +//---------------------------------------------------------------------------------------------------- +void wallet2::on_passphrase_request(bool on_device, epee::wipeable_string & passphrase) +{ + if (0 != m_callback) + m_callback->on_passphrase_request(on_device, passphrase); +} } diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index eb0763131..c07054177 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -98,11 +98,26 @@ namespace tools virtual void on_lw_money_received(uint64_t height, const crypto::hash &txid, uint64_t amount) {} virtual void on_lw_unconfirmed_money_received(uint64_t height, const crypto::hash &txid, uint64_t amount) {} virtual void on_lw_money_spent(uint64_t height, const crypto::hash &txid, uint64_t amount) {} + // Device callbacks + virtual void on_button_request() {} + virtual void on_pin_request(epee::wipeable_string & pin) {} + virtual void on_passphrase_request(bool on_device, epee::wipeable_string & passphrase) {} // Common callbacks virtual void on_pool_tx_removed(const crypto::hash &txid) {} virtual ~i_wallet2_callback() {} }; + class wallet_device_callback : public hw::i_device_callback + { + public: + wallet_device_callback(wallet2 * wallet): wallet(wallet) {}; + void on_button_request() override; + void on_pin_request(epee::wipeable_string & pin) override; + void on_passphrase_request(bool on_device, epee::wipeable_string & passphrase) override; + private: + wallet2 * wallet; + }; + struct tx_dust_policy { uint64_t dust_threshold; @@ -154,6 +169,7 @@ namespace tools { friend class ::Serialization_portability_wallet_Test; friend class wallet_keys_unlocker; + friend class wallet_device_callback; public: static constexpr const std::chrono::seconds rpc_timeout = std::chrono::minutes(3) + std::chrono::seconds(30); @@ -1285,6 +1301,11 @@ namespace tools void setup_new_blockchain(); void create_keys_file(const std::string &wallet_, bool watch_only, const epee::wipeable_string &password, bool create_address_file); + wallet_device_callback * get_device_callback(); + void on_button_request(); + void on_pin_request(epee::wipeable_string & pin); + void on_passphrase_request(bool on_device, epee::wipeable_string & passphrase); + cryptonote::account_base m_account; boost::optional m_daemon_login; std::string m_daemon_address; @@ -1396,6 +1417,7 @@ namespace tools bool m_devices_registered; std::shared_ptr m_tx_notify; + std::unique_ptr m_device_callback; }; } BOOST_CLASS_VERSION(tools::wallet2, 26) diff --git a/src/wallet/wallet_errors.h b/src/wallet/wallet_errors.h index b3141985d..e2caee5d2 100644 --- a/src/wallet/wallet_errors.h +++ b/src/wallet/wallet_errors.h @@ -219,6 +219,14 @@ namespace tools } }; //---------------------------------------------------------------------------------------------------- + struct password_entry_failed : public wallet_runtime_error + { + explicit password_entry_failed(std::string&& loc, const std::string &msg = "Password entry failed") + : wallet_runtime_error(std::move(loc), msg) + { + } + }; + //---------------------------------------------------------------------------------------------------- const char* const file_error_messages[] = { "file already exists", "file not found",