aboutsummaryrefslogtreecommitdiff
path: root/src/wallet/rpcwallet.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/wallet/rpcwallet.cpp')
-rw-r--r--src/wallet/rpcwallet.cpp71
1 files changed, 71 insertions, 0 deletions
diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp
index 94e61aa20e..a7b2b05d9b 100644
--- a/src/wallet/rpcwallet.cpp
+++ b/src/wallet/rpcwallet.cpp
@@ -4079,6 +4079,76 @@ static UniValue listlabels(const JSONRPCRequest& request)
return ret;
}
+UniValue sethdseed(const JSONRPCRequest& request)
+{
+ CWallet* const pwallet = GetWalletForJSONRPCRequest(request);
+
+ if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
+ return NullUniValue;
+ }
+
+ if (request.fHelp || request.params.size() > 2) {
+ throw std::runtime_error(
+ "sethdseed ( \"newkeypool\" \"seed\" )\n"
+ "\nSet or generate a new HD wallet seed. Non-HD wallets will not be upgraded to being a HD wallet. Wallets that are already\n"
+ "HD will have a new HD seed set so that new keys added to the keypool will be derived from this new seed.\n"
+ "\nNote that you will need to MAKE A NEW BACKUP of your wallet after setting the HD wallet seed.\n"
+ + HelpRequiringPassphrase(pwallet) +
+ "\nArguments:\n"
+ "1. \"newkeypool\" (boolean, optional, default=true) Whether to flush old unused addresses, including change addresses, from the keypool and regenerate it.\n"
+ " If true, the next address from getnewaddress and change address from getrawchangeaddress will be from this new seed.\n"
+ " If false, addresses (including change addresses if the wallet already had HD Chain Split enabled) from the existing\n"
+ " keypool will be used until it has been depleted.\n"
+ "2. \"seed\" (string, optional) The WIF private key to use as the new HD seed; if not provided a random seed will be used.\n"
+ " The seed value can be retrieved using the dumpwallet command. It is the private key marked hdmaster=1\n"
+ "\nExamples:\n"
+ + HelpExampleCli("sethdseed", "")
+ + HelpExampleCli("sethdseed", "false")
+ + HelpExampleCli("sethdseed", "true \"wifkey\"")
+ + HelpExampleRpc("sethdseed", "true, \"wifkey\"")
+ );
+ }
+
+ if (IsInitialBlockDownload()) {
+ throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Cannot set a new HD seed while still in Initial Block Download");
+ }
+
+ LOCK2(cs_main, pwallet->cs_wallet);
+
+ // Do not do anything to non-HD wallets
+ if (!pwallet->IsHDEnabled()) {
+ throw JSONRPCError(RPC_WALLET_ERROR, "Cannot set a HD seed on a non-HD wallet. Start with -upgradewallet in order to upgrade a non-HD wallet to HD");
+ }
+
+ EnsureWalletIsUnlocked(pwallet);
+
+ bool flush_key_pool = true;
+ if (!request.params[0].isNull()) {
+ flush_key_pool = request.params[0].get_bool();
+ }
+
+ CPubKey master_pub_key;
+ if (request.params[1].isNull()) {
+ master_pub_key = pwallet->GenerateNewHDMasterKey();
+ } else {
+ CKey key = DecodeSecret(request.params[1].get_str());
+ if (!key.IsValid()) {
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key");
+ }
+
+ if (HaveKey(*pwallet, key)) {
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Already have this key (either as an HD seed or as a loose private key)");
+ }
+
+ master_pub_key = pwallet->DeriveNewMasterHDKey(key);
+ }
+
+ pwallet->SetHDMasterKey(master_pub_key);
+ if (flush_key_pool) pwallet->NewKeyPool();
+
+ return NullUniValue;
+}
+
extern UniValue abortrescan(const JSONRPCRequest& request); // in rpcdump.cpp
extern UniValue dumpprivkey(const JSONRPCRequest& request); // in rpcdump.cpp
extern UniValue importprivkey(const JSONRPCRequest& request);
@@ -4139,6 +4209,7 @@ static const CRPCCommand commands[] =
{ "wallet", "walletpassphrase", &walletpassphrase, {"passphrase","timeout"} },
{ "wallet", "removeprunedfunds", &removeprunedfunds, {"txid"} },
{ "wallet", "rescanblockchain", &rescanblockchain, {"start_height", "stop_height"} },
+ { "wallet", "sethdseed", &sethdseed, {"newkeypool","seed"} },
/** Account functions (deprecated) */
{ "wallet", "getaccountaddress", &getlabeladdress, {"account"} },