Skip to content

Commit 9b81fd1

Browse files
committed
Fetch keys from keypool when private keys are disabled
When private keys are disabled, still fetch keys from the keypool if the keypool has keys. Those keys come from importing them and adding them to the keypool.
1 parent 99cccb9 commit 9b81fd1

File tree

3 files changed

+16
-25
lines changed

3 files changed

+16
-25
lines changed

src/wallet/rpcwallet.cpp

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -173,18 +173,12 @@ static UniValue getnewaddress(const JSONRPCRequest& request)
173173
},
174174
}.ToString());
175175

176-
// Belt and suspenders check for disabled private keys
177-
if (pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
178-
throw JSONRPCError(RPC_WALLET_ERROR, "Error: Private keys are disabled for this wallet");
179-
}
180-
181176
LOCK(pwallet->cs_wallet);
182177

183178
if (!pwallet->CanGetAddresses()) {
184179
throw JSONRPCError(RPC_WALLET_ERROR, "Error: This wallet has no available keys");
185180
}
186181

187-
188182
// Parse the label first so we don't generate a key if there's an error
189183
std::string label;
190184
if (!request.params[0].isNull())
@@ -240,11 +234,6 @@ static UniValue getrawchangeaddress(const JSONRPCRequest& request)
240234
},
241235
}.ToString());
242236

243-
// Belt and suspenders check for disabled private keys
244-
if (pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
245-
throw JSONRPCError(RPC_WALLET_ERROR, "Error: Private keys are disabled for this wallet");
246-
}
247-
248237
LOCK(pwallet->cs_wallet);
249238

250239
if (!pwallet->CanGetAddresses(true)) {
@@ -2447,7 +2436,7 @@ static UniValue getwalletinfo(const JSONRPCRequest& request)
24472436
obj.pushKV("keypoololdest", pwallet->GetOldestKeyPoolTime());
24482437
obj.pushKV("keypoolsize", (int64_t)kpExternalSize);
24492438
CKeyID seed_id = pwallet->GetHDChain().seed_id;
2450-
if (!seed_id.IsNull() && pwallet->CanSupportFeature(FEATURE_HD_SPLIT)) {
2439+
if (pwallet->CanSupportFeature(FEATURE_HD_SPLIT)) {
24512440
obj.pushKV("keypoolsize_hd_internal", (int64_t)(pwallet->GetKeyPoolSize() - kpExternalSize));
24522441
}
24532442
if (pwallet->IsCrypted()) {

src/wallet/wallet.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2833,8 +2833,8 @@ bool CWallet::CreateTransaction(interfaces::Chain::Lock& locked_chain, const std
28332833
// post-backup change.
28342834

28352835
// Reserve a new key pair from key pool
2836-
if (IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
2837-
strFailReason = _("Can't generate a change-address key. Private keys are disabled for this wallet.");
2836+
if (!CanGetAddresses(true)) {
2837+
strFailReason = _("Can't generate a change-address key. No keys in the internal keypool and can't generate any keys.");
28382838
return false;
28392839
}
28402840
CPubKey vchPubKey;
@@ -3487,7 +3487,8 @@ bool CWallet::ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool, bool fRe
34873487
if (!IsLocked())
34883488
TopUpKeyPool();
34893489

3490-
bool fReturningInternal = IsHDEnabled() && CanSupportFeature(FEATURE_HD_SPLIT) && fRequestedInternal;
3490+
bool fReturningInternal = fRequestedInternal;
3491+
fReturningInternal &= (IsHDEnabled() && CanSupportFeature(FEATURE_HD_SPLIT)) || IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS);
34913492
bool use_split_keypool = set_pre_split_keypool.empty();
34923493
std::set<int64_t>& setKeyPool = use_split_keypool ? (fReturningInternal ? setInternalKeyPool : setExternalKeyPool) : set_pre_split_keypool;
34933494

@@ -3504,7 +3505,8 @@ bool CWallet::ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool, bool fRe
35043505
if (!batch.ReadPool(nIndex, keypool)) {
35053506
throw std::runtime_error(std::string(__func__) + ": read failed");
35063507
}
3507-
if (!HaveKey(keypool.vchPubKey.GetID())) {
3508+
CPubKey pk;
3509+
if (!GetPubKey(keypool.vchPubKey.GetID(), pk)) {
35083510
throw std::runtime_error(std::string(__func__) + ": unknown key in key pool");
35093511
}
35103512
// If the key was pre-split keypool, we don't care about what type it is
@@ -3558,7 +3560,7 @@ bool CWallet::GetKeyFromPool(CPubKey& result, bool internal)
35583560
{
35593561
LOCK(cs_wallet);
35603562
int64_t nIndex;
3561-
if (!ReserveKeyFromKeyPool(nIndex, keypool, internal)) {
3563+
if (!ReserveKeyFromKeyPool(nIndex, keypool, internal) && !IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
35623564
if (IsLocked()) return false;
35633565
WalletBatch batch(*database);
35643566
result = GenerateNewKey(batch, internal);

test/functional/wallet_createwallet.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ def run_test(self):
3131
self.log.info("Test disableprivatekeys creation.")
3232
self.nodes[0].createwallet(wallet_name='w1', disable_private_keys=True)
3333
w1 = node.get_wallet_rpc('w1')
34-
assert_raises_rpc_error(-4, "Error: Private keys are disabled for this wallet", w1.getnewaddress)
35-
assert_raises_rpc_error(-4, "Error: Private keys are disabled for this wallet", w1.getrawchangeaddress)
34+
assert_raises_rpc_error(-4, "Error: This wallet has no available keys", w1.getnewaddress)
35+
assert_raises_rpc_error(-4, "Error: This wallet has no available keys", w1.getrawchangeaddress)
3636
w1.importpubkey(w0.getaddressinfo(address1)['pubkey'])
3737

3838
self.log.info('Test that private keys cannot be imported')
@@ -48,8 +48,8 @@ def run_test(self):
4848
self.log.info("Test blank creation with private keys disabled.")
4949
self.nodes[0].createwallet(wallet_name='w2', disable_private_keys=True, blank=True)
5050
w2 = node.get_wallet_rpc('w2')
51-
assert_raises_rpc_error(-4, "Error: Private keys are disabled for this wallet", w2.getnewaddress)
52-
assert_raises_rpc_error(-4, "Error: Private keys are disabled for this wallet", w2.getrawchangeaddress)
51+
assert_raises_rpc_error(-4, "Error: This wallet has no available keys", w2.getnewaddress)
52+
assert_raises_rpc_error(-4, "Error: This wallet has no available keys", w2.getrawchangeaddress)
5353
w2.importpubkey(w0.getaddressinfo(address1)['pubkey'])
5454

5555
self.log.info("Test blank creation with private keys enabled.")
@@ -89,12 +89,12 @@ def run_test(self):
8989
self.nodes[0].createwallet(wallet_name='w5', disable_private_keys=True, blank=True)
9090
w5 = node.get_wallet_rpc('w5')
9191
assert_equal(w5.getwalletinfo()['keypoolsize'], 0)
92-
assert_raises_rpc_error(-4, "Error: Private keys are disabled for this wallet", w5.getnewaddress)
93-
assert_raises_rpc_error(-4, "Error: Private keys are disabled for this wallet", w5.getrawchangeaddress)
92+
assert_raises_rpc_error(-4, "Error: This wallet has no available keys", w5.getnewaddress)
93+
assert_raises_rpc_error(-4, "Error: This wallet has no available keys", w5.getrawchangeaddress)
9494
# Encrypt the wallet
9595
w5.encryptwallet('pass')
96-
assert_raises_rpc_error(-4, "Error: Private keys are disabled for this wallet", w5.getnewaddress)
97-
assert_raises_rpc_error(-4, "Error: Private keys are disabled for this wallet", w5.getrawchangeaddress)
96+
assert_raises_rpc_error(-4, "Error: This wallet has no available keys", w5.getnewaddress)
97+
assert_raises_rpc_error(-4, "Error: This wallet has no available keys", w5.getrawchangeaddress)
9898

9999
if __name__ == '__main__':
100100
CreateWalletTest().main()

0 commit comments

Comments
 (0)