From 8fb50b738f09e8c883294f367cbfec0bcbf7264f Mon Sep 17 00:00:00 2001 From: stoffu Date: Mon, 4 Jun 2018 16:58:13 +0900 Subject: [PATCH] Wallet API: add support for wallet creation from hardware device --- src/wallet/api/wallet.cpp | 32 ++++++++++++++++++++++++++++++- src/wallet/api/wallet.h | 6 ++++++ src/wallet/api/wallet2_api.h | 32 +++++++++++++++++++++++++++++++ src/wallet/api/wallet_manager.cpp | 20 +++++++++++++++++++ src/wallet/api/wallet_manager.h | 6 ++++++ 5 files changed, 95 insertions(+), 1 deletion(-) diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp index 367011eaa..c0a5e4780 100644 --- a/src/wallet/api/wallet.cpp +++ b/src/wallet/api/wallet.cpp @@ -338,6 +338,7 @@ WalletImpl::WalletImpl(NetworkType nettype) , m_trustedDaemon(false) , m_wallet2Callback(nullptr) , m_recoveringFromSeed(false) + , m_recoveringFromDevice(false) , m_synchronized(false) , m_rebuildWalletCache(false) , m_is_connected(false) @@ -385,6 +386,7 @@ bool WalletImpl::create(const std::string &path, const std::string &password, co clearStatus(); m_recoveringFromSeed = false; + m_recoveringFromDevice = false; bool keys_file_exists; bool wallet_file_exists; tools::wallet2::wallet_exists(path, keys_file_exists, wallet_file_exists); @@ -584,11 +586,28 @@ bool WalletImpl::recoverFromKeysWithPassword(const std::string &path, return true; } +bool WalletImpl::recoverFromDevice(const std::string &path, const std::string &password, const std::string &device_name) +{ + clearStatus(); + m_recoveringFromSeed = false; + m_recoveringFromDevice = true; + try + { + m_wallet->restore(path, password, device_name); + LOG_PRINT_L1("Generated new wallet from device: " + device_name); + } + catch (const std::exception& e) { + setStatusError(string(tr("failed to generate new wallet: ")) + e.what()); + return false; + } + return true; +} bool WalletImpl::open(const std::string &path, const std::string &password) { clearStatus(); m_recoveringFromSeed = false; + m_recoveringFromDevice = false; try { // TODO: handle "deprecated" // Check if wallet cache exists @@ -628,6 +647,7 @@ bool WalletImpl::recover(const std::string &path, const std::string &password, c } m_recoveringFromSeed = true; + m_recoveringFromDevice = false; crypto::secret_key recovery_key; std::string old_language; if (!crypto::ElectrumWords::words_to_bytes(seed, recovery_key, old_language)) { @@ -837,6 +857,16 @@ void WalletImpl::setRecoveringFromSeed(bool recoveringFromSeed) m_recoveringFromSeed = recoveringFromSeed; } +void WalletImpl::setRecoveringFromDevice(bool recoveringFromDevice) +{ + m_recoveringFromDevice = recoveringFromDevice; +} + +void WalletImpl::setSubaddressLookahead(uint32_t major, uint32_t minor) +{ + m_wallet->set_subaddress_lookahead(major, minor); +} + uint64_t WalletImpl::balance(uint32_t accountIndex) const { return m_wallet->balance(accountIndex); @@ -1839,7 +1869,7 @@ bool WalletImpl::isNewWallet() const // with the daemon (pull hashes instead of pull blocks). // If wallet cache is rebuilt, creation height stored in .keys is used. // Watch only wallet is a copy of an existing wallet. - return !(blockChainHeight() > 1 || m_recoveringFromSeed || m_rebuildWalletCache) && !watchOnly(); + return !(blockChainHeight() > 1 || m_recoveringFromSeed || m_recoveringFromDevice || m_rebuildWalletCache) && !watchOnly(); } bool WalletImpl::doInit(const string &daemon_address, uint64_t upper_transaction_size_limit, bool ssl) diff --git a/src/wallet/api/wallet.h b/src/wallet/api/wallet.h index 4929c9673..6ad372357 100644 --- a/src/wallet/api/wallet.h +++ b/src/wallet/api/wallet.h @@ -76,6 +76,9 @@ public: const std::string &address_string, const std::string &viewkey_string, const std::string &spendkey_string = ""); + bool recoverFromDevice(const std::string &path, + const std::string &password, + const std::string &device_name); bool close(bool store = true); std::string seed() const; std::string getSeedLanguage() const; @@ -113,6 +116,8 @@ public: void setRefreshFromBlockHeight(uint64_t refresh_from_block_height); uint64_t getRefreshFromBlockHeight() const { return m_wallet->get_refresh_from_block_height(); }; void setRecoveringFromSeed(bool recoveringFromSeed); + void setRecoveringFromDevice(bool recoveringFromDevice) override; + void setSubaddressLookahead(uint32_t major, uint32_t minor) override; bool watchOnly() const; bool rescanSpent(); NetworkType nettype() const {return static_cast(m_wallet->nettype());} @@ -216,6 +221,7 @@ private: // so it shouldn't be considered as new and pull blocks (slow-refresh) // instead of pulling hashes (fast-refresh) std::atomic m_recoveringFromSeed; + std::atomic m_recoveringFromDevice; std::atomic m_synchronized; std::atomic m_rebuildWalletCache; // cache connection status to avoid unnecessary RPC calls diff --git a/src/wallet/api/wallet2_api.h b/src/wallet/api/wallet2_api.h index 4fbc7298a..546ce16ae 100644 --- a/src/wallet/api/wallet2_api.h +++ b/src/wallet/api/wallet2_api.h @@ -468,6 +468,21 @@ struct Wallet */ virtual void setRecoveringFromSeed(bool recoveringFromSeed) = 0; + /*! + * \brief setRecoveringFromDevice - set state to recovering from device + * + * \param recoveringFromDevice - true/false + */ + virtual void setRecoveringFromDevice(bool recoveringFromDevice) = 0; + + /*! + * \brief setSubaddressLookahead - set size of subaddress lookahead + * + * \param major - size fot the major index + * \param minor - size fot the minor index + */ + virtual void setSubaddressLookahead(uint32_t major, uint32_t minor) = 0; + /** * @brief connectToDaemon - connects to the daemon. TODO: check if it can be removed * @return @@ -916,6 +931,23 @@ struct WalletManager return createWalletFromKeys(path, language, testnet ? TESTNET : MAINNET, restoreHeight, addressString, viewKeyString, spendKeyString); } + /*! + * \brief creates wallet using hardware device. + * \param path Name of wallet file to be created + * \param password Password of wallet file + * \param nettype Network type + * \param deviceName Device name + * \param restoreHeight restore from start height (0 sets to current height) + * \param subaddressLookahead Size of subaddress lookahead (empty sets to some default low value) + * \return Wallet instance (Wallet::status() needs to be called to check if recovered successfully) + */ + virtual Wallet * createWalletFromDevice(const std::string &path, + const std::string &password, + NetworkType nettype, + const std::string &deviceName, + uint64_t restoreHeight = 0, + const std::string &subaddressLookahead = "") = 0; + /*! * \brief Closes wallet. In case operation succeeded, wallet object deleted. in case operation failed, wallet object not deleted * \param wallet previously opened / created wallet instance diff --git a/src/wallet/api/wallet_manager.cpp b/src/wallet/api/wallet_manager.cpp index a63716576..99eadc82f 100644 --- a/src/wallet/api/wallet_manager.cpp +++ b/src/wallet/api/wallet_manager.cpp @@ -114,6 +114,26 @@ Wallet *WalletManagerImpl::createWalletFromKeys(const std::string &path, return wallet; } +Wallet *WalletManagerImpl::createWalletFromDevice(const std::string &path, + const std::string &password, + NetworkType nettype, + const std::string &deviceName, + uint64_t restoreHeight, + const std::string &subaddressLookahead) +{ + WalletImpl * wallet = new WalletImpl(nettype); + if(restoreHeight > 0){ + wallet->setRefreshFromBlockHeight(restoreHeight); + } + auto lookahead = tools::parse_subaddress_lookahead(subaddressLookahead); + if (lookahead) + { + wallet->setSubaddressLookahead(lookahead->first, lookahead->second); + } + wallet->recoverFromDevice(path, password, deviceName); + return wallet; +} + bool WalletManagerImpl::closeWallet(Wallet *wallet, bool store) { WalletImpl * wallet_ = dynamic_cast(wallet); diff --git a/src/wallet/api/wallet_manager.h b/src/wallet/api/wallet_manager.h index 26238b658..19aad9ee3 100644 --- a/src/wallet/api/wallet_manager.h +++ b/src/wallet/api/wallet_manager.h @@ -64,6 +64,12 @@ public: const std::string &addressString, const std::string &viewKeyString, const std::string &spendKeyString = ""); + virtual Wallet * createWalletFromDevice(const std::string &path, + const std::string &password, + NetworkType nettype, + const std::string &deviceName, + uint64_t restoreHeight = 0, + const std::string &subaddressLookahead = "") override; virtual bool closeWallet(Wallet *wallet, bool store = true); bool walletExists(const std::string &path); bool verifyWalletPassword(const std::string &keys_file_name, const std::string &password, bool no_spend_key) const;