From 2fde1cf4b8b014581ddf6eab639f2fafdc1d9e21 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Thu, 16 Feb 2017 14:22:18 +0100 Subject: [PATCH 1/6] Add facility to store wallet flags (64 bits) --- src/wallet/wallet.cpp | 19 +++++++++++++++++++ src/wallet/wallet.h | 12 ++++++++++++ src/wallet/walletdb.cpp | 12 ++++++++++++ src/wallet/walletdb.h | 1 + 4 files changed, 44 insertions(+) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index fa82c9c9df7..9819c5b1eac 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1350,6 +1350,25 @@ bool CWallet::IsHDEnabled() const return !hdChain.masterKeyID.IsNull(); } +void CWallet::AddWalletFlag(uint64_t flags) +{ + walletFlags |= flags; + if (!CWalletDB(*dbw).WriteWalletFlags(walletFlags)) + throw std::runtime_error(std::string(__func__) + ": writing wallet flags failed"); +} + +bool CWallet::IsWalletFlagSet(uint64_t flag) +{ + return (walletFlags & flag); +} + +void CWallet::SetWalletFlags(uint64_t overwriteFlags, bool memonly) +{ + walletFlags = overwriteFlags; + if (!memonly && !CWalletDB(*dbw).WriteWalletFlags(walletFlags)) + throw std::runtime_error(std::string(__func__) + ": writing wallet flags failed"); +} + int64_t CWalletTx::GetTxTime() const { int64_t n = nTimeSmart; diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 81f7ec59f5d..ef02e4aaaed 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -696,6 +696,8 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface /* HD derive new child key (on internal or external chain) */ void DeriveNewChildKey(CKeyMetadata& metadata, CKey& secret, bool internal = false); + std::atomic walletFlags; + std::set setKeyPool; int64_t nTimeFirstKey; @@ -791,6 +793,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface nRelockTime = 0; fAbortRescan = false; fScanningWallet = false; + walletFlags = 0; } std::map mapWallet; @@ -1104,6 +1107,15 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface caller must ensure the current wallet version is correct before calling this function). */ bool SetHDMasterKey(const CPubKey& key); + + /* set a single wallet flag */ + void AddWalletFlag(uint64_t flags); + + /* check if a certain wallet flag is set */ + bool IsWalletFlagSet(uint64_t flag); + + /* overwrite all flags by the given unit64_t */ + void SetWalletFlags(uint64_t overwriteFlags, bool memOnly); }; /** A key allocated from the key pool. */ diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index a90fa6dbbda..3e07d07c1bb 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -537,6 +537,12 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, return false; } } + else if (strType == "flags") + { + uint64_t flags; + ssValue >> flags; + pwallet->SetWalletFlags(flags, true); + } } catch (...) { return false; @@ -871,6 +877,12 @@ bool CWalletDB::WriteHDChain(const CHDChain& chain) return batch.Write(std::string("hdchain"), chain); } +bool CWalletDB::WriteWalletFlags(const uint64_t flags) +{ + nWalletDBUpdateCounter++; + return batch.Write(std::string("flags"), flags); +} + void CWalletDB::IncrementUpdateCounter() { nWalletDBUpdateCounter++; diff --git a/src/wallet/walletdb.h b/src/wallet/walletdb.h index cd9fe279c53..9058b8e9f19 100644 --- a/src/wallet/walletdb.h +++ b/src/wallet/walletdb.h @@ -212,6 +212,7 @@ class CWalletDB //! write the hdchain model (external chain child index counter) bool WriteHDChain(const CHDChain& chain); + bool WriteWalletFlags(const uint64_t flags); static void IncrementUpdateCounter(); static unsigned int GetUpdateCounter(); From 9935fbd829d4e1c3f9f054c49179e0751de45aee Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Fri, 5 May 2017 08:53:39 +0200 Subject: [PATCH 2/6] Add per wallet -disablehot option to ensure pure watchonly-wallets --- src/wallet/rpcwallet.cpp | 12 ++++++++++++ src/wallet/wallet.cpp | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ src/wallet/wallet.h | 5 +++++ 3 files changed, 65 insertions(+) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index d1e7485d042..88897707b14 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -129,6 +129,10 @@ UniValue getnewaddress(const JSONRPCRequest& request) + HelpExampleRpc("getnewaddress", "") ); + if (pwalletMain->IsWalletFlagSet(WALLET_FLAG_DISABLE_HOT_KEYS)) { + throw JSONRPCError(RPC_WALLET_ERROR, "Error: Hot keys are disabled (-disablehot)"); + } + LOCK2(cs_main, pwallet->cs_wallet); // Parse the account first so we don't generate a key if there's an error @@ -216,6 +220,10 @@ UniValue getrawchangeaddress(const JSONRPCRequest& request) + HelpExampleRpc("getrawchangeaddress", "") ); + if (pwalletMain->IsWalletFlagSet(WALLET_FLAG_DISABLE_HOT_KEYS)) { + throw JSONRPCError(RPC_WALLET_ERROR, "Error: Hot keys are disabled (-disablehot)"); + } + LOCK2(cs_main, pwallet->cs_wallet); if (!pwallet->IsLocked()) { @@ -1960,6 +1968,10 @@ UniValue keypoolrefill(const JSONRPCRequest& request) + HelpExampleRpc("keypoolrefill", "") ); + if (pwalletMain->IsWalletFlagSet(WALLET_FLAG_DISABLE_HOT_KEYS)) { + throw JSONRPCError(RPC_WALLET_ERROR, "Error: Hot keys are disabled (-disablehot)"); + } + LOCK2(cs_main, pwallet->cs_wallet); // 0 is interpreted by TopUpKeyPool() as the default keypool size given by -keypool diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 9819c5b1eac..5404d74fcf6 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -89,6 +89,7 @@ const CWalletTx* CWallet::GetWalletTx(const uint256& hash) const CPubKey CWallet::GenerateNewKey(bool internal) { + assert(!IsWalletFlagSet(WALLET_FLAG_DISABLE_HOT_KEYS)); AssertLockHeld(cs_wallet); // mapKeyMetadata bool fCompressed = CanSupportFeature(FEATURE_COMPRPUBKEY); // default to compressed public keys if we want 0.6.0 wallets @@ -1293,6 +1294,7 @@ CAmount CWallet::GetChange(const CTransaction& tx) const CPubKey CWallet::GenerateNewHDMasterKey() { + assert(!IsWalletFlagSet(WALLET_FLAG_DISABLE_HOT_KEYS)); CKey key; key.MakeNewKey(true); @@ -2516,6 +2518,10 @@ bool CWallet::CreateTransaction(const std::vector& vecSend, CWalletT // post-backup change. // Reserve a new key pair from key pool + if (IsWalletFlagSet(WALLET_FLAG_DISABLE_HOT_KEYS)) { + strFailReason = _("Can't generate a change-address key. Hot keys are disabled for this wallet (-disablehot)."); + return false; + } CPubKey vchPubKey; bool ret; ret = reservekey.GetReservedKey(vchPubKey, true); @@ -2833,6 +2839,9 @@ DBErrors CWallet::LoadWallet(bool& fFirstRunRet) if (nLoadWalletRet != DB_LOAD_OK) return nLoadWalletRet; fFirstRunRet = !vchDefaultKey.IsValid(); + if (IsWalletFlagSet(WALLET_FLAG_DISABLE_HOT_KEYS)) { + fFirstRunRet = false; + } uiInterface.LoadWallet(this); @@ -2957,6 +2966,9 @@ bool CWallet::SetDefaultKey(const CPubKey &vchPubKey) */ bool CWallet::NewKeyPool() { + if (IsWalletFlagSet(WALLET_FLAG_DISABLE_HOT_KEYS)) { + return false; + } { LOCK(cs_wallet); CWalletDB walletdb(*dbw); @@ -2997,6 +3009,9 @@ size_t CWallet::KeypoolCountExternalKeys() bool CWallet::TopUpKeyPool(unsigned int kpSize) { + if (IsWalletFlagSet(WALLET_FLAG_DISABLE_HOT_KEYS)) { + return false; + } { LOCK(cs_wallet); @@ -3097,6 +3112,10 @@ void CWallet::ReturnKey(int64_t nIndex) bool CWallet::GetKeyFromPool(CPubKey& result, bool internal) { + if (IsWalletFlagSet(WALLET_FLAG_DISABLE_HOT_KEYS)) { + return false; + } + int64_t nIndex = 0; CKeyPool keypool; { @@ -3598,6 +3617,7 @@ std::string CWallet::GetWalletHelpString(bool showDebug) { std::string strUsage = HelpMessageGroup(_("Wallet options:")); strUsage += HelpMessageOpt("-disablewallet", _("Do not load the wallet and disable wallet RPC calls")); + strUsage += HelpMessageOpt("-disablehot", _("Disable the possibility of hot keys (only watchonlys are possible in this mode") + " " + strprintf(_("(default: %u)"), DEFAULT_DISABLE_HOT_WALLET)); strUsage += HelpMessageOpt("-keypool=", strprintf(_("Set key pool size to (default: %u)"), DEFAULT_KEYPOOL_SIZE)); strUsage += HelpMessageOpt("-fallbackfee=", strprintf(_("A fee rate (in %s/kB) that will be used when fee estimation has insufficient data (default: %s)"), CURRENCY_UNIT, FormatMoney(DEFAULT_FALLBACK_FEE))); @@ -3717,6 +3737,9 @@ CWallet* CWallet::CreateWalletFromFile(const std::string walletFile) if (!walletInstance->SetHDMasterKey(masterPubKey)) throw std::runtime_error(std::string(__func__) + ": Storing master key failed"); } + if (GetBoolArg("-disablehot", DEFAULT_DISABLE_HOT_WALLET)) { + walletInstance->AddWalletFlag(WALLET_FLAG_DISABLE_HOT_KEYS); + } CPubKey newDefaultKey; if (walletInstance->GetKeyFromPool(newDefaultKey, false)) { walletInstance->SetDefaultKey(newDefaultKey); @@ -3728,6 +3751,27 @@ CWallet* CWallet::CreateWalletFromFile(const std::string walletFile) walletInstance->SetBestChain(chainActive.GetLocator()); } + else if (IsArgSet("-disablehot")) { + bool disableHot = GetBoolArg("-disablehot", DEFAULT_DISABLE_HOT_WALLET); + LOCK(walletInstance->cs_wallet); + if (walletInstance->vchDefaultKey.IsValid() && disableHot) { + InitError(strprintf(_("Error loading %s: You can't disable hot keys if your wallet already contains hot keys"), walletFile)); + return NULL; + } + bool hotKeys = walletInstance->IsWalletFlagSet(WALLET_FLAG_DISABLE_HOT_KEYS); + if (hotKeys && !disableHot) { + InitError(strprintf(_("Error loading %s: You can't enable hot keys once you have initialized a wallet with disabled hot keys (use -disablehot instead)"), walletFile)); + return NULL; + } + } + else if (walletInstance->IsWalletFlagSet(WALLET_FLAG_DISABLE_HOT_KEYS)) { + LOCK(walletInstance->cs_wallet); + /* make sure we don't have hot keys */ + if (walletInstance->GetKeyPoolSize()) { + InitError(strprintf(_("Error loading %s: You can't disable hot keys if your wallet already contains hot keys"), walletFile)); + return NULL; + } + } else if (IsArgSet("-usehd")) { bool useHD = GetBoolArg("-usehd", DEFAULT_USE_HD_WALLET); if (walletInstance->IsHDEnabled() && !useHD) { @@ -3858,6 +3902,10 @@ bool CWallet::ParameterInteraction() if (GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)) return true; + if (GetBoolArg("-disablehot", DEFAULT_DISABLE_HOT_WALLET) && SoftSetBoolArg("-usehd", false)) { + LogPrintf("%s: parameter interaction: -disablehot=1 -> setting -usehd=0\n", __func__); + } + if (GetBoolArg("-blocksonly", DEFAULT_BLOCKSONLY) && SoftSetBoolArg("-walletbroadcast", false)) { LogPrintf("%s: parameter interaction: -blocksonly=1 -> setting -walletbroadcast=0\n", __func__); } diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index ef02e4aaaed..fd9946f2957 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -61,6 +61,7 @@ static const unsigned int DEFAULT_TX_CONFIRM_TARGET = 6; static const bool DEFAULT_WALLET_RBF = false; static const bool DEFAULT_WALLETBROADCAST = true; static const bool DEFAULT_DISABLE_WALLET = false; +static const bool DEFAULT_DISABLE_HOT_WALLET = false; //! if set, all keys will be derived by using BIP32 static const bool DEFAULT_USE_HD_WALLET = true; @@ -91,6 +92,10 @@ enum WalletFeature FEATURE_LATEST = FEATURE_COMPRPUBKEY // HD is optional, use FEATURE_COMPRPUBKEY as latest version }; +enum WalletFlags : uint64_t { + // will enforce the rule that the wallet can't contain any private keys (only watch-only/pubkeys) + WALLET_FLAG_DISABLE_HOT_KEYS = (1 << 0), +}; /** A key pool entry */ class CKeyPool From 885e9916fd4cf758f1500fba978259993285b838 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Wed, 1 Feb 2017 13:54:28 +0100 Subject: [PATCH 3/6] [Qt] Disable creating receive addresses when -disablehot is set --- src/qt/receivecoinsdialog.cpp | 4 ++++ src/qt/walletmodel.cpp | 5 +++++ src/qt/walletmodel.h | 1 + 3 files changed, 10 insertions(+) diff --git a/src/qt/receivecoinsdialog.cpp b/src/qt/receivecoinsdialog.cpp index e98f4d33474..4d4595c80fe 100644 --- a/src/qt/receivecoinsdialog.cpp +++ b/src/qt/receivecoinsdialog.cpp @@ -93,6 +93,10 @@ void ReceiveCoinsDialog::setModel(WalletModel *_model) SLOT(recentRequestsView_selectionChanged(QItemSelection, QItemSelection))); // Last 2 columns are set by the columnResizingFixer, when the table geometry is ready. columnResizingFixer = new GUIUtil::TableViewLastColumnResizingFixer(tableView, AMOUNT_MINIMUM_COLUMN_WIDTH, DATE_COLUMN_WIDTH, this); + + if (_model->hotKeysDisabled()) { + ui->receiveButton->setEnabled(false); + } } } diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index a2a92719048..49310351139 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -703,6 +703,11 @@ bool WalletModel::hdEnabled() const return wallet->IsHDEnabled(); } +bool WalletModel::hotKeysDisabled() const +{ + return (wallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_HOT_KEYS)); +} + int WalletModel::getDefaultConfirmTarget() const { return nTxConfirmTarget; diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h index 78e45dc3693..c1506cb8492 100644 --- a/src/qt/walletmodel.h +++ b/src/qt/walletmodel.h @@ -210,6 +210,7 @@ class WalletModel : public QObject static bool isWalletEnabled(); bool hdEnabled() const; + bool hotKeysDisabled() const; int getDefaultConfirmTarget() const; From fcea55a6ec6be57ee96458bde6fb24656269d3ee Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Fri, 5 May 2017 09:17:56 +0200 Subject: [PATCH 4/6] [QA] Add disablehot.py functional test --- test/functional/disablehot.py | 65 ++++++++++++++++++++++++++++++++++++++++++ test/functional/test_runner.py | 1 + 2 files changed, 66 insertions(+) create mode 100755 test/functional/disablehot.py diff --git a/test/functional/disablehot.py b/test/functional/disablehot.py new file mode 100755 index 00000000000..ab68cdbc454 --- /dev/null +++ b/test/functional/disablehot.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python3 +# Copyright (c) 2017 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import * + +class DisableHotKeysTest(BitcoinTestFramework): + + def __init__(self): + super().__init__() + self.setup_clean_chain = True + self.num_nodes = 2 + + def setup_network(self, split=False): + self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, [[], ['-disablehot']]) + + connect_nodes_bi(self.nodes,0,1) + + self.is_network_split=False + self.sync_all() + + def run_test(self): + assert_equal(self.nodes[1].getwalletinfo()['keypoolsize'], 0) + + print("Mining blocks...") + self.sync_all() + self.nodes[0].generate(101) + self.sync_all() + + n0addrR = self.nodes[0].getnewaddress() + n0pubkR = self.nodes[0].validateaddress(n0addrR)['pubkey'] + n0addrC = self.nodes[0].getnewaddress() + n0pubkC = self.nodes[0].validateaddress(n0addrC)['pubkey'] + n0addr = self.nodes[0].getnewaddress() + self.nodes[0].sendtoaddress(n0addrR, 10); + self.nodes[0].generate(6) + self.sync_all() + + assert_raises_jsonrpc(-4,"Error: Hot keys are disabled (-disablehot)", self.nodes[1].getnewaddress) + assert_raises_jsonrpc(-4,"Error: Hot keys are disabled (-disablehot)", self.nodes[1].getrawchangeaddress) + + self.nodes[1].importpubkey(n0pubkR) #TODO switch to importmulti + self.nodes[1].importpubkey(n0pubkC) + assert_equal(self.nodes[1].getbalance("*", 1, True), 10) + rawtx = self.nodes[1].createrawtransaction([], {n0addr: 1.0}) + frawtx= self.nodes[1].fundrawtransaction(rawtx, {"changeAddress": n0addrC, "includeWatching": True}) + + # check if we can re-enable private keys + assert_equal(self.nodes[1].signrawtransaction(frawtx['hex'])['complete'], False) + print("restarting node with disablehot=0 (try to re-enable private keys which must not be possible)") + stop_nodes(self.nodes) + assert_start_raises_init_error(1, self.options.tmpdir, ['-disablehot=0'], 'can\'t enable hot keys') + + #remove wallet + os.remove(self.options.tmpdir + "/node1/regtest/wallet.dat") + print("start node, create normal private key wallet") + self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, [[], ['-disablehot=0']]) + stop_nodes(self.nodes) + assert_start_raises_init_error(1, self.options.tmpdir, ['-disablehot=1'], 'You can\'t disable hot keys') + self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, [[], ['-disablehot=0']]) + +if __name__ == '__main__': + DisableHotKeysTest().main() diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py index c87010b0f45..38752151506 100755 --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -110,6 +110,7 @@ 'rpcnamedargs.py', 'listsinceblock.py', 'p2p-leaktests.py', + 'disablehot.py', ] EXTENDED_SCRIPTS = [ From 770db3a530ee4aa86c76a2d93d3f4098c91c953c Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Wed, 24 May 2017 11:12:08 +0200 Subject: [PATCH 5/6] Disable importprivkey and importwallet during -disablehot mode --- src/wallet/rpcdump.cpp | 8 ++++++++ test/functional/disablehot.py | 2 ++ 2 files changed, 10 insertions(+) diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index 82708dab26e..073bd03c7a7 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -102,6 +102,10 @@ UniValue importprivkey(const JSONRPCRequest& request) ); + if (pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_HOT_KEYS)) { + throw JSONRPCError(RPC_WALLET_ERROR, "Error: Hot keys are disabled (-disablehot)"); + } + LOCK2(cs_main, pwallet->cs_wallet); EnsureWalletIsUnlocked(pwallet); @@ -470,6 +474,10 @@ UniValue importwallet(const JSONRPCRequest& request) if (fPruneMode) throw JSONRPCError(RPC_WALLET_ERROR, "Importing wallets is disabled in pruned mode"); + if (pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_HOT_KEYS)) { + throw JSONRPCError(RPC_WALLET_ERROR, "Error: Hot keys are disabled (-disablehot)"); + } + LOCK2(cs_main, pwallet->cs_wallet); EnsureWalletIsUnlocked(pwallet); diff --git a/test/functional/disablehot.py b/test/functional/disablehot.py index ab68cdbc454..ec4eff2a586 100755 --- a/test/functional/disablehot.py +++ b/test/functional/disablehot.py @@ -40,6 +40,8 @@ def run_test(self): assert_raises_jsonrpc(-4,"Error: Hot keys are disabled (-disablehot)", self.nodes[1].getnewaddress) assert_raises_jsonrpc(-4,"Error: Hot keys are disabled (-disablehot)", self.nodes[1].getrawchangeaddress) + assert_raises_jsonrpc(-4,"Error: Hot keys are disabled (-disablehot)", self.nodes[1].importprivkey, "92e6XLo5jVAVwrQKPNTs93oQco8f8sDNBcpv73Dsrs397fQtFQn") + assert_raises_jsonrpc(-4,"Error: Hot keys are disabled (-disablehot)", self.nodes[1].importwallet, "dummy") self.nodes[1].importpubkey(n0pubkR) #TODO switch to importmulti self.nodes[1].importpubkey(n0pubkC) From 9e94cc41b3180949011d2299da14c13471b6aa2b Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Wed, 24 May 2017 11:13:03 +0200 Subject: [PATCH 6/6] Use pwallet instead of pwalletMain for IsWalletFlagSet tests --- src/wallet/rpcwallet.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 88897707b14..5d221d43780 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -129,7 +129,7 @@ UniValue getnewaddress(const JSONRPCRequest& request) + HelpExampleRpc("getnewaddress", "") ); - if (pwalletMain->IsWalletFlagSet(WALLET_FLAG_DISABLE_HOT_KEYS)) { + if (pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_HOT_KEYS)) { throw JSONRPCError(RPC_WALLET_ERROR, "Error: Hot keys are disabled (-disablehot)"); } @@ -220,7 +220,7 @@ UniValue getrawchangeaddress(const JSONRPCRequest& request) + HelpExampleRpc("getrawchangeaddress", "") ); - if (pwalletMain->IsWalletFlagSet(WALLET_FLAG_DISABLE_HOT_KEYS)) { + if (pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_HOT_KEYS)) { throw JSONRPCError(RPC_WALLET_ERROR, "Error: Hot keys are disabled (-disablehot)"); } @@ -1968,7 +1968,7 @@ UniValue keypoolrefill(const JSONRPCRequest& request) + HelpExampleRpc("keypoolrefill", "") ); - if (pwalletMain->IsWalletFlagSet(WALLET_FLAG_DISABLE_HOT_KEYS)) { + if (pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_HOT_KEYS)) { throw JSONRPCError(RPC_WALLET_ERROR, "Error: Hot keys are disabled (-disablehot)"); }