Wallet API: add support for wallet creation from hardware device

This commit is contained in:
stoffu 2018-06-04 16:58:13 +09:00
parent 248310de06
commit 46e90b7780
No known key found for this signature in database
GPG key ID: 41DAB8343A9EC012
5 changed files with 95 additions and 1 deletions

View file

@ -372,6 +372,7 @@ WalletImpl::WalletImpl(NetworkType nettype)
, m_trustedDaemon(false) , m_trustedDaemon(false)
, m_wallet2Callback(nullptr) , m_wallet2Callback(nullptr)
, m_recoveringFromSeed(false) , m_recoveringFromSeed(false)
, m_recoveringFromDevice(false)
, m_synchronized(false) , m_synchronized(false)
, m_rebuildWalletCache(false) , m_rebuildWalletCache(false)
, m_is_connected(false) , m_is_connected(false)
@ -419,6 +420,7 @@ bool WalletImpl::create(const std::string &path, const std::string &password, co
clearStatus(); clearStatus();
m_recoveringFromSeed = false; m_recoveringFromSeed = false;
m_recoveringFromDevice = false;
bool keys_file_exists; bool keys_file_exists;
bool wallet_file_exists; bool wallet_file_exists;
tools::wallet2::wallet_exists(path, keys_file_exists, wallet_file_exists); tools::wallet2::wallet_exists(path, keys_file_exists, wallet_file_exists);
@ -621,11 +623,28 @@ bool WalletImpl::recoverFromKeysWithPassword(const std::string &path,
return true; 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) bool WalletImpl::open(const std::string &path, const std::string &password)
{ {
clearStatus(); clearStatus();
m_recoveringFromSeed = false; m_recoveringFromSeed = false;
m_recoveringFromDevice = false;
try { try {
// TODO: handle "deprecated" // TODO: handle "deprecated"
// Check if wallet cache exists // Check if wallet cache exists
@ -663,6 +682,7 @@ bool WalletImpl::recover(const std::string &path, const std::string &password, c
} }
m_recoveringFromSeed = true; m_recoveringFromSeed = true;
m_recoveringFromDevice = false;
crypto::secret_key recovery_key; crypto::secret_key recovery_key;
std::string old_language; std::string old_language;
if (!crypto::ElectrumWords::words_to_bytes(seed, recovery_key, old_language)) { if (!crypto::ElectrumWords::words_to_bytes(seed, recovery_key, old_language)) {
@ -884,6 +904,16 @@ void WalletImpl::setRecoveringFromSeed(bool recoveringFromSeed)
m_recoveringFromSeed = 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 uint64_t WalletImpl::balance(uint32_t accountIndex) const
{ {
return m_wallet->balance(accountIndex); return m_wallet->balance(accountIndex);
@ -1996,7 +2026,7 @@ bool WalletImpl::isNewWallet() const
// with the daemon (pull hashes instead of pull blocks). // with the daemon (pull hashes instead of pull blocks).
// If wallet cache is rebuilt, creation height stored in .keys is used. // If wallet cache is rebuilt, creation height stored in .keys is used.
// Watch only wallet is a copy of an existing wallet. // 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) bool WalletImpl::doInit(const string &daemon_address, uint64_t upper_transaction_size_limit, bool ssl)

View file

@ -76,6 +76,9 @@ public:
const std::string &address_string, const std::string &address_string,
const std::string &viewkey_string, const std::string &viewkey_string,
const std::string &spendkey_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); bool close(bool store = true);
std::string seed() const; std::string seed() const;
std::string getSeedLanguage() const; std::string getSeedLanguage() const;
@ -115,6 +118,8 @@ public:
void setRefreshFromBlockHeight(uint64_t refresh_from_block_height); void setRefreshFromBlockHeight(uint64_t refresh_from_block_height);
uint64_t getRefreshFromBlockHeight() const { return m_wallet->get_refresh_from_block_height(); }; uint64_t getRefreshFromBlockHeight() const { return m_wallet->get_refresh_from_block_height(); };
void setRecoveringFromSeed(bool recoveringFromSeed); void setRecoveringFromSeed(bool recoveringFromSeed);
void setRecoveringFromDevice(bool recoveringFromDevice) override;
void setSubaddressLookahead(uint32_t major, uint32_t minor) override;
bool watchOnly() const; bool watchOnly() const;
bool rescanSpent(); bool rescanSpent();
NetworkType nettype() const {return static_cast<NetworkType>(m_wallet->nettype());} NetworkType nettype() const {return static_cast<NetworkType>(m_wallet->nettype());}
@ -232,6 +237,7 @@ private:
// so it shouldn't be considered as new and pull blocks (slow-refresh) // so it shouldn't be considered as new and pull blocks (slow-refresh)
// instead of pulling hashes (fast-refresh) // instead of pulling hashes (fast-refresh)
std::atomic<bool> m_recoveringFromSeed; std::atomic<bool> m_recoveringFromSeed;
std::atomic<bool> m_recoveringFromDevice;
std::atomic<bool> m_synchronized; std::atomic<bool> m_synchronized;
std::atomic<bool> m_rebuildWalletCache; std::atomic<bool> m_rebuildWalletCache;
// cache connection status to avoid unnecessary RPC calls // cache connection status to avoid unnecessary RPC calls

View file

@ -509,6 +509,21 @@ struct Wallet
*/ */
virtual void setRecoveringFromSeed(bool recoveringFromSeed) = 0; 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 * @brief connectToDaemon - connects to the daemon. TODO: check if it can be removed
* @return * @return
@ -1014,6 +1029,23 @@ struct WalletManager
return createWalletFromKeys(path, language, testnet ? TESTNET : MAINNET, restoreHeight, addressString, viewKeyString, spendKeyString); 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 * \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 * \param wallet previously opened / created wallet instance

View file

@ -114,6 +114,26 @@ Wallet *WalletManagerImpl::createWalletFromKeys(const std::string &path,
return wallet; 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) bool WalletManagerImpl::closeWallet(Wallet *wallet, bool store)
{ {
WalletImpl * wallet_ = dynamic_cast<WalletImpl*>(wallet); WalletImpl * wallet_ = dynamic_cast<WalletImpl*>(wallet);

View file

@ -64,6 +64,12 @@ public:
const std::string &addressString, const std::string &addressString,
const std::string &viewKeyString, const std::string &viewKeyString,
const std::string &spendKeyString = ""); 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); virtual bool closeWallet(Wallet *wallet, bool store = true);
bool walletExists(const std::string &path); bool walletExists(const std::string &path);
bool verifyWalletPassword(const std::string &keys_file_name, const std::string &password, bool no_spend_key) const; bool verifyWalletPassword(const std::string &keys_file_name, const std::string &password, bool no_spend_key) const;