mirror of
https://github.com/monero-project/monero.git
synced 2024-12-25 21:19:27 +00:00
Wallet API: Create wallet from keys
This commit is contained in:
parent
4629ead8c5
commit
774a21394a
5 changed files with 178 additions and 0 deletions
|
@ -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);
|
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)
|
std::string Wallet::paymentIdFromAddress(const std::string &str, bool testnet)
|
||||||
{
|
{
|
||||||
bool has_payment_id;
|
bool has_payment_id;
|
||||||
|
@ -337,6 +375,98 @@ bool WalletImpl::createWatchOnly(const std::string &path, const std::string &pas
|
||||||
return true;
|
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)
|
bool WalletImpl::open(const std::string &path, const std::string &password)
|
||||||
{
|
{
|
||||||
clearStatus();
|
clearStatus();
|
||||||
|
|
|
@ -58,6 +58,11 @@ public:
|
||||||
const std::string &language) const;
|
const std::string &language) const;
|
||||||
bool open(const std::string &path, const std::string &password);
|
bool open(const std::string &path, const std::string &password);
|
||||||
bool recover(const std::string &path, const std::string &seed);
|
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();
|
bool close();
|
||||||
std::string seed() const;
|
std::string seed() const;
|
||||||
std::string getSeedLanguage() const;
|
std::string getSeedLanguage() const;
|
||||||
|
|
|
@ -72,6 +72,22 @@ Wallet *WalletManagerImpl::recoveryWallet(const std::string &path, const std::st
|
||||||
return wallet;
|
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)
|
bool WalletManagerImpl::closeWallet(Wallet *wallet)
|
||||||
{
|
{
|
||||||
WalletImpl * wallet_ = dynamic_cast<WalletImpl*>(wallet);
|
WalletImpl * wallet_ = dynamic_cast<WalletImpl*>(wallet);
|
||||||
|
|
|
@ -41,6 +41,13 @@ public:
|
||||||
const std::string &language, bool testnet);
|
const std::string &language, bool testnet);
|
||||||
Wallet * openWallet(const std::string &path, const std::string &password, 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 * 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);
|
virtual bool closeWallet(Wallet *wallet);
|
||||||
bool walletExists(const std::string &path);
|
bool walletExists(const std::string &path);
|
||||||
std::vector<std::string> findWallets(const std::string &path);
|
std::vector<std::string> findWallets(const std::string &path);
|
||||||
|
|
|
@ -435,6 +435,7 @@ struct Wallet
|
||||||
static std::string genPaymentId();
|
static std::string genPaymentId();
|
||||||
static bool paymentIdValid(const std::string &paiment_id);
|
static bool paymentIdValid(const std::string &paiment_id);
|
||||||
static bool addressValid(const std::string &str, bool testnet);
|
static bool addressValid(const std::string &str, bool testnet);
|
||||||
|
static bool keyValid(const std::string &secret_key_string, const std::string &address_string, bool isViewKey, bool testnet, std::string &error);
|
||||||
static std::string paymentIdFromAddress(const std::string &str, bool testnet);
|
static std::string paymentIdFromAddress(const std::string &str, bool testnet);
|
||||||
static uint64_t maximumAllowedAmount();
|
static uint64_t maximumAllowedAmount();
|
||||||
|
|
||||||
|
@ -614,6 +615,25 @@ struct WalletManager
|
||||||
*/
|
*/
|
||||||
virtual Wallet * recoveryWallet(const std::string &path, const std::string &memo, bool testnet = false, uint64_t restoreHeight = 0) = 0;
|
virtual Wallet * recoveryWallet(const std::string &path, const std::string &memo, bool testnet = false, uint64_t restoreHeight = 0) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief recovers existing wallet using keys. Creates a view only wallet if spend key is omitted
|
||||||
|
* \param path Name of wallet file to be created
|
||||||
|
* \param language language
|
||||||
|
* \param testnet testnet
|
||||||
|
* \param restoreHeight restore from start height
|
||||||
|
* \param addressString public address
|
||||||
|
* \param viewKeyString view key
|
||||||
|
* \param spendKeyString spend key (optional)
|
||||||
|
* \return Wallet instance (Wallet::status() needs to be called to check if recovered successfully)
|
||||||
|
*/
|
||||||
|
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 = "") = 0;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Closes wallet. In case operation succeded, wallet object deleted. in case operation failed, wallet object not deleted
|
* \brief Closes wallet. In case operation succeded, 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
|
||||||
|
|
Loading…
Reference in a new issue