mirror of
https://github.com/dashpay/dash.git
synced 2024-12-25 03:52:49 +01:00
fix(rpc): Improve upgradetohd
(#5455)
## Issue being fixed or feature implemented Allow `upgradetohd` in IBD, better errors, no GUI lock-up ## What was done? Pls see individual commits. Most of it is changes in whitespaces, might want to use ?w=1 to review i.e. https://github.com/dashpay/dash/pull/5455/files?w=1 ## How Has This Been Tested? run tests, try `upgradetohd` on testnet ## Breaking Changes n/a ## Checklist: - [x] I have performed a self-review of my own code - [ ] I have commented my code, particularly in hard-to-understand areas - [ ] I have added or updated relevant unit/integration/functional/e2e tests - [ ] I have made corresponding changes to the documentation - [x] I have assigned this pull request to a milestone _(for repository code-owners and collaborators only)_
This commit is contained in:
parent
bfb3f4b0e0
commit
5e99e3f516
@ -201,7 +201,6 @@ static const CRPCConvertParam vRPCConvertParams[] =
|
||||
{ "createwallet", 1, "disable_private_keys"},
|
||||
{ "createwallet", 2, "blank"},
|
||||
{ "createwallet", 4, "avoid_reuse"},
|
||||
{ "upgradetohd", 3, "rescan"},
|
||||
{ "createwallet", 5, "load_on_startup"},
|
||||
{ "loadwallet", 1, "load_on_startup"},
|
||||
{ "unloadwallet", 1, "load_on_startup"},
|
||||
|
@ -2665,67 +2665,66 @@ static UniValue upgradetohd(const JSONRPCRequest& request)
|
||||
throw JSONRPCError(RPC_WALLET_ERROR, "This type of wallet does not support this command");
|
||||
}
|
||||
|
||||
LOCK(pwallet->cs_wallet);
|
||||
|
||||
// Do not do anything to HD wallets
|
||||
if (pwallet->IsHDEnabled()) {
|
||||
throw JSONRPCError(RPC_WALLET_ERROR, "Cannot upgrade a wallet to HD if it is already upgraded to HD.");
|
||||
}
|
||||
|
||||
if (!pwallet->SetMaxVersion(FEATURE_HD)) {
|
||||
throw JSONRPCError(RPC_WALLET_ERROR, "Cannot downgrade wallet");
|
||||
}
|
||||
|
||||
if (pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
|
||||
throw JSONRPCError(RPC_WALLET_ERROR, "Error: Private keys are disabled for this wallet");
|
||||
}
|
||||
|
||||
bool prev_encrypted = pwallet->IsCrypted();
|
||||
|
||||
SecureString secureWalletPassphrase;
|
||||
secureWalletPassphrase.reserve(100);
|
||||
// TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
|
||||
// Alternately, find a way to make request.params[0] mlock()'d to begin with.
|
||||
if (request.params[2].isNull()) {
|
||||
if (prev_encrypted) {
|
||||
throw JSONRPCError(RPC_WALLET_PASSPHRASE_INCORRECT, "Cannot upgrade encrypted wallet to HD without the wallet passphrase");
|
||||
}
|
||||
} else {
|
||||
secureWalletPassphrase = request.params[2].get_str().c_str();
|
||||
if (!pwallet->Unlock(secureWalletPassphrase)) {
|
||||
throw JSONRPCError(RPC_WALLET_PASSPHRASE_INCORRECT, "The wallet passphrase entered was incorrect");
|
||||
}
|
||||
}
|
||||
|
||||
bool generate_mnemonic = request.params[0].isNull() || request.params[0].get_str().empty();
|
||||
|
||||
SecureString secureMnemonic;
|
||||
secureMnemonic.reserve(256);
|
||||
if (!generate_mnemonic) {
|
||||
if (pwallet->chain().isInitialBlockDownload()) {
|
||||
throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Cannot set mnemonic while still in Initial Block Download");
|
||||
{
|
||||
LOCK(pwallet->cs_wallet);
|
||||
|
||||
// Do not do anything to HD wallets
|
||||
if (pwallet->IsHDEnabled()) {
|
||||
throw JSONRPCError(RPC_WALLET_ERROR, "Cannot upgrade a wallet to HD if it is already upgraded to HD.");
|
||||
}
|
||||
secureMnemonic = request.params[0].get_str().c_str();
|
||||
}
|
||||
|
||||
SecureString secureMnemonicPassphrase;
|
||||
secureMnemonicPassphrase.reserve(256);
|
||||
if (!request.params[1].isNull()) {
|
||||
secureMnemonicPassphrase = request.params[1].get_str().c_str();
|
||||
}
|
||||
|
||||
pwallet->WalletLogPrintf("Upgrading wallet to HD\n");
|
||||
pwallet->SetMinVersion(FEATURE_HD);
|
||||
|
||||
if (prev_encrypted) {
|
||||
if (!pwallet->GenerateNewHDChainEncrypted(secureMnemonic, secureMnemonicPassphrase, secureWalletPassphrase)) {
|
||||
throw JSONRPCError(RPC_WALLET_ERROR, "Failed to generate encrypted HD wallet");
|
||||
if (!pwallet->SetMaxVersion(FEATURE_HD)) {
|
||||
throw JSONRPCError(RPC_WALLET_ERROR, "Cannot downgrade wallet");
|
||||
}
|
||||
} else {
|
||||
spk_man->GenerateNewHDChain(secureMnemonic, secureMnemonicPassphrase);
|
||||
if (!secureWalletPassphrase.empty()) {
|
||||
if (!pwallet->EncryptWallet(secureWalletPassphrase)) {
|
||||
throw JSONRPCError(RPC_WALLET_ENCRYPTION_FAILED, "Failed to encrypt HD wallet");
|
||||
|
||||
if (pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
|
||||
throw JSONRPCError(RPC_WALLET_ERROR, "Error: Private keys are disabled for this wallet");
|
||||
}
|
||||
|
||||
bool prev_encrypted = pwallet->IsCrypted();
|
||||
|
||||
SecureString secureWalletPassphrase;
|
||||
secureWalletPassphrase.reserve(100);
|
||||
// TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
|
||||
// Alternately, find a way to make request.params[0] mlock()'d to begin with.
|
||||
if (request.params[2].isNull()) {
|
||||
if (prev_encrypted) {
|
||||
throw JSONRPCError(RPC_WALLET_PASSPHRASE_INCORRECT, "Cannot upgrade encrypted wallet to HD without the wallet passphrase");
|
||||
}
|
||||
} else {
|
||||
secureWalletPassphrase = request.params[2].get_str().c_str();
|
||||
if (!pwallet->Unlock(secureWalletPassphrase)) {
|
||||
throw JSONRPCError(RPC_WALLET_PASSPHRASE_INCORRECT, "The wallet passphrase entered was incorrect");
|
||||
}
|
||||
}
|
||||
|
||||
SecureString secureMnemonic;
|
||||
secureMnemonic.reserve(256);
|
||||
if (!generate_mnemonic) {
|
||||
secureMnemonic = request.params[0].get_str().c_str();
|
||||
}
|
||||
|
||||
SecureString secureMnemonicPassphrase;
|
||||
secureMnemonicPassphrase.reserve(256);
|
||||
if (!request.params[1].isNull()) {
|
||||
secureMnemonicPassphrase = request.params[1].get_str().c_str();
|
||||
}
|
||||
|
||||
pwallet->WalletLogPrintf("Upgrading wallet to HD\n");
|
||||
pwallet->SetMinVersion(FEATURE_HD);
|
||||
|
||||
if (prev_encrypted) {
|
||||
if (!pwallet->GenerateNewHDChainEncrypted(secureMnemonic, secureMnemonicPassphrase, secureWalletPassphrase)) {
|
||||
throw JSONRPCError(RPC_WALLET_ERROR, "Failed to generate encrypted HD wallet");
|
||||
}
|
||||
} else {
|
||||
spk_man->GenerateNewHDChain(secureMnemonic, secureMnemonicPassphrase);
|
||||
if (!secureWalletPassphrase.empty()) {
|
||||
if (!pwallet->EncryptWallet(secureWalletPassphrase)) {
|
||||
throw JSONRPCError(RPC_WALLET_ENCRYPTION_FAILED, "Failed to encrypt HD wallet");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2737,7 +2736,16 @@ static UniValue upgradetohd(const JSONRPCRequest& request)
|
||||
if (!reserver.reserve()) {
|
||||
throw JSONRPCError(RPC_WALLET_ERROR, "Wallet is currently rescanning. Abort existing rescan or wait.");
|
||||
}
|
||||
pwallet->ScanForWalletTransactions(pwallet->chain().getBlockHash(0), 0, {}, reserver, true);
|
||||
CWallet::ScanResult result = pwallet->ScanForWalletTransactions(pwallet->chain().getBlockHash(0), 0, {}, reserver, true);
|
||||
switch (result.status) {
|
||||
case CWallet::ScanResult::SUCCESS:
|
||||
break;
|
||||
case CWallet::ScanResult::FAILURE:
|
||||
throw JSONRPCError(RPC_MISC_ERROR, "Rescan failed. Potentially corrupted data files.");
|
||||
case CWallet::ScanResult::USER_ABORT:
|
||||
throw JSONRPCError(RPC_MISC_ERROR, "Rescan aborted.");
|
||||
// no default case, so the compiler can warn about missing cases
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
Loading…
Reference in New Issue
Block a user