diff options
Diffstat (limited to 'src/wallet/api')
-rw-r--r-- | src/wallet/api/wallet.cpp | 130 | ||||
-rw-r--r-- | src/wallet/api/wallet.h | 6 | ||||
-rw-r--r-- | src/wallet/api/wallet_manager.cpp | 16 | ||||
-rw-r--r-- | src/wallet/api/wallet_manager.h | 7 |
4 files changed, 159 insertions, 0 deletions
diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp index cd4b523c9..9e40d2e02 100644 --- a/src/wallet/api/wallet.cpp +++ b/src/wallet/api/wallet.cpp @@ -197,6 +197,44 @@ bool Wallet::addressValid(const std::string &str, bool testnet) return get_account_integrated_address_from_str(address, has_payment_id, pid, testnet, str); } +bool Wallet::keyValid(const std::string &secret_key_string, const std::string &address_string, bool isViewKey, bool testnet, std::string &error) +{ + bool has_payment_id; + cryptonote::account_public_address address; + crypto::hash8 pid; + if(!get_account_integrated_address_from_str(address, has_payment_id, pid, testnet, address_string)) { + error = tr("Failed to parse address"); + return false; + } + + cryptonote::blobdata key_data; + if(!epee::string_tools::parse_hexstr_to_binbuff(secret_key_string, key_data) || key_data.size() != sizeof(crypto::secret_key)) + { + error = tr("Failed to parse key"); + return false; + } + crypto::secret_key key = *reinterpret_cast<const crypto::secret_key*>(key_data.data()); + + // check the key match the given address + crypto::public_key pkey; + if (!crypto::secret_key_to_public_key(key, pkey)) { + error = tr("failed to verify key"); + return false; + } + bool matchAddress = false; + if(isViewKey) + matchAddress = address.m_view_public_key == pkey; + else + matchAddress = address.m_spend_public_key == pkey; + + if(!matchAddress) { + error = tr("key does not match address"); + return false; + } + + return true; +} + std::string Wallet::paymentIdFromAddress(const std::string &str, bool testnet) { bool has_payment_id; @@ -337,6 +375,98 @@ bool WalletImpl::createWatchOnly(const std::string &path, const std::string &pas return true; } +bool WalletImpl::recoverFromKeys(const std::string &path, + const std::string &language, + const std::string &address_string, + const std::string &viewkey_string, + const std::string &spendkey_string) +{ + cryptonote::account_public_address address; + bool has_payment_id; + crypto::hash8 new_payment_id; + if(!get_account_integrated_address_from_str(address, has_payment_id, new_payment_id, m_wallet->testnet(), address_string)) + { + m_errorString = tr("failed to parse address"); + m_status = Status_Error; + return false; + } + + // parse optional spend key + crypto::secret_key spendkey; + bool has_spendkey = false; + if (!spendkey_string.empty()) { + cryptonote::blobdata spendkey_data; + if(!epee::string_tools::parse_hexstr_to_binbuff(spendkey_string, spendkey_data) || spendkey_data.size() != sizeof(crypto::secret_key)) + { + m_errorString = tr("failed to parse secret spend key"); + m_status = Status_Error; + return false; + } + has_spendkey = true; + spendkey = *reinterpret_cast<const crypto::secret_key*>(spendkey_data.data()); + } + + // parse view secret key + if (viewkey_string.empty()) { + m_errorString = tr("No view key supplied, cancelled"); + m_status = Status_Error; + return false; + } + cryptonote::blobdata viewkey_data; + if(!epee::string_tools::parse_hexstr_to_binbuff(viewkey_string, viewkey_data) || viewkey_data.size() != sizeof(crypto::secret_key)) + { + m_errorString = tr("failed to parse secret view key"); + m_status = Status_Error; + return false; + } + crypto::secret_key viewkey = *reinterpret_cast<const crypto::secret_key*>(viewkey_data.data()); + + // check the spend and view keys match the given address + crypto::public_key pkey; + if(has_spendkey) { + if (!crypto::secret_key_to_public_key(spendkey, pkey)) { + m_errorString = tr("failed to verify secret spend key"); + m_status = Status_Error; + return false; + } + if (address.m_spend_public_key != pkey) { + m_errorString = tr("spend key does not match address"); + m_status = Status_Error; + return false; + } + } + if (!crypto::secret_key_to_public_key(viewkey, pkey)) { + m_errorString = tr("failed to verify secret view key"); + m_status = Status_Error; + return false; + } + if (address.m_view_public_key != pkey) { + m_errorString = tr("view key does not match address"); + m_status = Status_Error; + return false; + } + + try + { + if (has_spendkey) { + m_wallet->generate(path, "", address, spendkey, viewkey); + LOG_PRINT_L1("Generated new wallet from keys"); + } + else { + m_wallet->generate(path, "", address, viewkey); + LOG_PRINT_L1("Generated new view only wallet from keys"); + } + + } + catch (const std::exception& e) { + m_errorString = string(tr("failed to generate new wallet: ")) + e.what(); + m_status = Status_Error; + return false; + } + return true; +} + + bool WalletImpl::open(const std::string &path, const std::string &password) { clearStatus(); diff --git a/src/wallet/api/wallet.h b/src/wallet/api/wallet.h index 844d552c4..7daf63e43 100644 --- a/src/wallet/api/wallet.h +++ b/src/wallet/api/wallet.h @@ -58,6 +58,11 @@ public: const std::string &language) const; bool open(const std::string &path, const std::string &password); bool recover(const std::string &path, const std::string &seed); + 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 = ""); bool close(); std::string seed() const; std::string getSeedLanguage() const; @@ -94,6 +99,7 @@ public: void setRecoveringFromSeed(bool recoveringFromSeed); bool watchOnly() const; bool rescanSpent(); + bool testnet() const {return m_wallet->testnet();} PendingTransaction * createTransaction(const std::string &dst_addr, const std::string &payment_id, diff --git a/src/wallet/api/wallet_manager.cpp b/src/wallet/api/wallet_manager.cpp index 0601c104e..c761cc6d2 100644 --- a/src/wallet/api/wallet_manager.cpp +++ b/src/wallet/api/wallet_manager.cpp @@ -81,6 +81,22 @@ Wallet *WalletManagerImpl::recoveryWallet(const std::string &path, const std::st return wallet; } +Wallet *WalletManagerImpl::createWalletFromKeys(const std::string &path, + const std::string &language, + bool testnet, + uint64_t restoreHeight, + const std::string &addressString, + const std::string &viewKeyString, + const std::string &spendKeyString) +{ + WalletImpl * wallet = new WalletImpl(testnet); + if(restoreHeight > 0){ + wallet->setRefreshFromBlockHeight(restoreHeight); + } + wallet->recoverFromKeys(path, language, addressString, viewKeyString, spendKeyString); + return wallet; +} + bool WalletManagerImpl::closeWallet(Wallet *wallet) { WalletImpl * wallet_ = dynamic_cast<WalletImpl*>(wallet); diff --git a/src/wallet/api/wallet_manager.h b/src/wallet/api/wallet_manager.h index ca9570254..ce9b70e96 100644 --- a/src/wallet/api/wallet_manager.h +++ b/src/wallet/api/wallet_manager.h @@ -41,6 +41,13 @@ public: const std::string &language, bool testnet); Wallet * openWallet(const std::string &path, const std::string &password, bool testnet); virtual Wallet * recoveryWallet(const std::string &path, const std::string &memo, bool testnet, uint64_t restoreHeight); + virtual Wallet * createWalletFromKeys(const std::string &path, + const std::string &language, + bool testnet, + uint64_t restoreHeight, + const std::string &addressString, + const std::string &viewKeyString, + const std::string &spendKeyString = ""); virtual bool closeWallet(Wallet *wallet); bool walletExists(const std::string &path); std::vector<std::string> findWallets(const std::string &path); |