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.
This commit is contained in:
parent
99cccb900b
commit
9b81fd19ac
3 changed files with 16 additions and 25 deletions
|
@ -173,18 +173,12 @@ static UniValue getnewaddress(const JSONRPCRequest& request)
|
||||||
},
|
},
|
||||||
}.ToString());
|
}.ToString());
|
||||||
|
|
||||||
// Belt and suspenders check for disabled private keys
|
|
||||||
if (pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
|
|
||||||
throw JSONRPCError(RPC_WALLET_ERROR, "Error: Private keys are disabled for this wallet");
|
|
||||||
}
|
|
||||||
|
|
||||||
LOCK(pwallet->cs_wallet);
|
LOCK(pwallet->cs_wallet);
|
||||||
|
|
||||||
if (!pwallet->CanGetAddresses()) {
|
if (!pwallet->CanGetAddresses()) {
|
||||||
throw JSONRPCError(RPC_WALLET_ERROR, "Error: This wallet has no available keys");
|
throw JSONRPCError(RPC_WALLET_ERROR, "Error: This wallet has no available keys");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Parse the label first so we don't generate a key if there's an error
|
// Parse the label first so we don't generate a key if there's an error
|
||||||
std::string label;
|
std::string label;
|
||||||
if (!request.params[0].isNull())
|
if (!request.params[0].isNull())
|
||||||
|
@ -240,11 +234,6 @@ static UniValue getrawchangeaddress(const JSONRPCRequest& request)
|
||||||
},
|
},
|
||||||
}.ToString());
|
}.ToString());
|
||||||
|
|
||||||
// Belt and suspenders check for disabled private keys
|
|
||||||
if (pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
|
|
||||||
throw JSONRPCError(RPC_WALLET_ERROR, "Error: Private keys are disabled for this wallet");
|
|
||||||
}
|
|
||||||
|
|
||||||
LOCK(pwallet->cs_wallet);
|
LOCK(pwallet->cs_wallet);
|
||||||
|
|
||||||
if (!pwallet->CanGetAddresses(true)) {
|
if (!pwallet->CanGetAddresses(true)) {
|
||||||
|
@ -2447,7 +2436,7 @@ static UniValue getwalletinfo(const JSONRPCRequest& request)
|
||||||
obj.pushKV("keypoololdest", pwallet->GetOldestKeyPoolTime());
|
obj.pushKV("keypoololdest", pwallet->GetOldestKeyPoolTime());
|
||||||
obj.pushKV("keypoolsize", (int64_t)kpExternalSize);
|
obj.pushKV("keypoolsize", (int64_t)kpExternalSize);
|
||||||
CKeyID seed_id = pwallet->GetHDChain().seed_id;
|
CKeyID seed_id = pwallet->GetHDChain().seed_id;
|
||||||
if (!seed_id.IsNull() && pwallet->CanSupportFeature(FEATURE_HD_SPLIT)) {
|
if (pwallet->CanSupportFeature(FEATURE_HD_SPLIT)) {
|
||||||
obj.pushKV("keypoolsize_hd_internal", (int64_t)(pwallet->GetKeyPoolSize() - kpExternalSize));
|
obj.pushKV("keypoolsize_hd_internal", (int64_t)(pwallet->GetKeyPoolSize() - kpExternalSize));
|
||||||
}
|
}
|
||||||
if (pwallet->IsCrypted()) {
|
if (pwallet->IsCrypted()) {
|
||||||
|
|
|
@ -2833,8 +2833,8 @@ bool CWallet::CreateTransaction(interfaces::Chain::Lock& locked_chain, const std
|
||||||
// post-backup change.
|
// post-backup change.
|
||||||
|
|
||||||
// Reserve a new key pair from key pool
|
// Reserve a new key pair from key pool
|
||||||
if (IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
|
if (!CanGetAddresses(true)) {
|
||||||
strFailReason = _("Can't generate a change-address key. Private keys are disabled for this wallet.");
|
strFailReason = _("Can't generate a change-address key. No keys in the internal keypool and can't generate any keys.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
CPubKey vchPubKey;
|
CPubKey vchPubKey;
|
||||||
|
@ -3487,7 +3487,8 @@ bool CWallet::ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool, bool fRe
|
||||||
if (!IsLocked())
|
if (!IsLocked())
|
||||||
TopUpKeyPool();
|
TopUpKeyPool();
|
||||||
|
|
||||||
bool fReturningInternal = IsHDEnabled() && CanSupportFeature(FEATURE_HD_SPLIT) && fRequestedInternal;
|
bool fReturningInternal = fRequestedInternal;
|
||||||
|
fReturningInternal &= (IsHDEnabled() && CanSupportFeature(FEATURE_HD_SPLIT)) || IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS);
|
||||||
bool use_split_keypool = set_pre_split_keypool.empty();
|
bool use_split_keypool = set_pre_split_keypool.empty();
|
||||||
std::set<int64_t>& setKeyPool = use_split_keypool ? (fReturningInternal ? setInternalKeyPool : setExternalKeyPool) : set_pre_split_keypool;
|
std::set<int64_t>& setKeyPool = use_split_keypool ? (fReturningInternal ? setInternalKeyPool : setExternalKeyPool) : set_pre_split_keypool;
|
||||||
|
|
||||||
|
@ -3504,7 +3505,8 @@ bool CWallet::ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool, bool fRe
|
||||||
if (!batch.ReadPool(nIndex, keypool)) {
|
if (!batch.ReadPool(nIndex, keypool)) {
|
||||||
throw std::runtime_error(std::string(__func__) + ": read failed");
|
throw std::runtime_error(std::string(__func__) + ": read failed");
|
||||||
}
|
}
|
||||||
if (!HaveKey(keypool.vchPubKey.GetID())) {
|
CPubKey pk;
|
||||||
|
if (!GetPubKey(keypool.vchPubKey.GetID(), pk)) {
|
||||||
throw std::runtime_error(std::string(__func__) + ": unknown key in key pool");
|
throw std::runtime_error(std::string(__func__) + ": unknown key in key pool");
|
||||||
}
|
}
|
||||||
// If the key was pre-split keypool, we don't care about what type it is
|
// 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)
|
||||||
{
|
{
|
||||||
LOCK(cs_wallet);
|
LOCK(cs_wallet);
|
||||||
int64_t nIndex;
|
int64_t nIndex;
|
||||||
if (!ReserveKeyFromKeyPool(nIndex, keypool, internal)) {
|
if (!ReserveKeyFromKeyPool(nIndex, keypool, internal) && !IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
|
||||||
if (IsLocked()) return false;
|
if (IsLocked()) return false;
|
||||||
WalletBatch batch(*database);
|
WalletBatch batch(*database);
|
||||||
result = GenerateNewKey(batch, internal);
|
result = GenerateNewKey(batch, internal);
|
||||||
|
|
|
@ -31,8 +31,8 @@ class CreateWalletTest(BitcoinTestFramework):
|
||||||
self.log.info("Test disableprivatekeys creation.")
|
self.log.info("Test disableprivatekeys creation.")
|
||||||
self.nodes[0].createwallet(wallet_name='w1', disable_private_keys=True)
|
self.nodes[0].createwallet(wallet_name='w1', disable_private_keys=True)
|
||||||
w1 = node.get_wallet_rpc('w1')
|
w1 = node.get_wallet_rpc('w1')
|
||||||
assert_raises_rpc_error(-4, "Error: Private keys are disabled for this wallet", w1.getnewaddress)
|
assert_raises_rpc_error(-4, "Error: This wallet has no available keys", w1.getnewaddress)
|
||||||
assert_raises_rpc_error(-4, "Error: Private keys are disabled for this wallet", w1.getrawchangeaddress)
|
assert_raises_rpc_error(-4, "Error: This wallet has no available keys", w1.getrawchangeaddress)
|
||||||
w1.importpubkey(w0.getaddressinfo(address1)['pubkey'])
|
w1.importpubkey(w0.getaddressinfo(address1)['pubkey'])
|
||||||
|
|
||||||
self.log.info('Test that private keys cannot be imported')
|
self.log.info('Test that private keys cannot be imported')
|
||||||
|
@ -48,8 +48,8 @@ class CreateWalletTest(BitcoinTestFramework):
|
||||||
self.log.info("Test blank creation with private keys disabled.")
|
self.log.info("Test blank creation with private keys disabled.")
|
||||||
self.nodes[0].createwallet(wallet_name='w2', disable_private_keys=True, blank=True)
|
self.nodes[0].createwallet(wallet_name='w2', disable_private_keys=True, blank=True)
|
||||||
w2 = node.get_wallet_rpc('w2')
|
w2 = node.get_wallet_rpc('w2')
|
||||||
assert_raises_rpc_error(-4, "Error: Private keys are disabled for this wallet", w2.getnewaddress)
|
assert_raises_rpc_error(-4, "Error: This wallet has no available keys", w2.getnewaddress)
|
||||||
assert_raises_rpc_error(-4, "Error: Private keys are disabled for this wallet", w2.getrawchangeaddress)
|
assert_raises_rpc_error(-4, "Error: This wallet has no available keys", w2.getrawchangeaddress)
|
||||||
w2.importpubkey(w0.getaddressinfo(address1)['pubkey'])
|
w2.importpubkey(w0.getaddressinfo(address1)['pubkey'])
|
||||||
|
|
||||||
self.log.info("Test blank creation with private keys enabled.")
|
self.log.info("Test blank creation with private keys enabled.")
|
||||||
|
@ -89,12 +89,12 @@ class CreateWalletTest(BitcoinTestFramework):
|
||||||
self.nodes[0].createwallet(wallet_name='w5', disable_private_keys=True, blank=True)
|
self.nodes[0].createwallet(wallet_name='w5', disable_private_keys=True, blank=True)
|
||||||
w5 = node.get_wallet_rpc('w5')
|
w5 = node.get_wallet_rpc('w5')
|
||||||
assert_equal(w5.getwalletinfo()['keypoolsize'], 0)
|
assert_equal(w5.getwalletinfo()['keypoolsize'], 0)
|
||||||
assert_raises_rpc_error(-4, "Error: Private keys are disabled for this wallet", w5.getnewaddress)
|
assert_raises_rpc_error(-4, "Error: This wallet has no available keys", w5.getnewaddress)
|
||||||
assert_raises_rpc_error(-4, "Error: Private keys are disabled for this wallet", w5.getrawchangeaddress)
|
assert_raises_rpc_error(-4, "Error: This wallet has no available keys", w5.getrawchangeaddress)
|
||||||
# Encrypt the wallet
|
# Encrypt the wallet
|
||||||
w5.encryptwallet('pass')
|
w5.encryptwallet('pass')
|
||||||
assert_raises_rpc_error(-4, "Error: Private keys are disabled for this wallet", w5.getnewaddress)
|
assert_raises_rpc_error(-4, "Error: This wallet has no available keys", w5.getnewaddress)
|
||||||
assert_raises_rpc_error(-4, "Error: Private keys are disabled for this wallet", w5.getrawchangeaddress)
|
assert_raises_rpc_error(-4, "Error: This wallet has no available keys", w5.getrawchangeaddress)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
CreateWalletTest().main()
|
CreateWalletTest().main()
|
||||||
|
|
Loading…
Reference in a new issue