Page MenuHomePhabricator

D4921.id15444.diff
No OneTemporary

D4921.id15444.diff

diff --git a/doc/release-notes.md b/doc/release-notes.md
--- a/doc/release-notes.md
+++ b/doc/release-notes.md
@@ -16,3 +16,10 @@
your balance, unless they are explicitly watched (using `importaddress` or
`importmulti` with hex script argument). `signrawtransaction*` also still
works for them.
+ - The RPC `createwallet` now has an optional `blank` argument that can be used
+ to create a blank wallet. Blank wallets do not have any keys or HD seed.
+ They cannot be opened in software older than 0.20.11
+ Once a blank wallet has a HD seed set (by using `sethdseed`) or private keys,
+ scripts, addresses, and other watch only things have been imported, the wallet
+ is no longer blank and can be opened in 0.20.x.
+ Encrypting a blank wallet will also set a HD seed for it.
diff --git a/src/interfaces/wallet.h b/src/interfaces/wallet.h
--- a/src/interfaces/wallet.h
+++ b/src/interfaces/wallet.h
@@ -222,6 +222,9 @@
// Return whether HD enabled.
virtual bool hdEnabled() = 0;
+ // Return whether the wallet is blank.
+ virtual bool canGetAddresses() = 0;
+
// Check if a certain wallet flag is set.
virtual bool IsWalletFlagSet(uint64_t flag) = 0;
diff --git a/src/interfaces/wallet.cpp b/src/interfaces/wallet.cpp
--- a/src/interfaces/wallet.cpp
+++ b/src/interfaces/wallet.cpp
@@ -393,6 +393,7 @@
OutputType getDefaultAddressType() override {
return m_wallet.m_default_address_type;
}
+ bool canGetAddresses() override { return m_wallet.CanGetAddresses(); }
bool IsWalletFlagSet(uint64_t flag) override {
return m_wallet.IsWalletFlagSet(flag);
}
diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp
--- a/src/qt/walletmodel.cpp
+++ b/src/qt/walletmodel.cpp
@@ -506,15 +506,7 @@
}
bool WalletModel::canGetAddresses() const {
- // The wallet can provide a fresh address if:
- // * hdEnabled(): an HD seed is present; or
- // * it is a legacy wallet, because:
- // * !hdEnabled(): an HD seed is not present; and
- // * !IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS): private keys
- // have not been disabled (which results in hdEnabled() == true)
- return m_wallet->hdEnabled() ||
- (!m_wallet->hdEnabled() &&
- !m_wallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS));
+ return m_wallet->canGetAddresses();
}
QString WalletModel::getWalletName() const {
diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp
--- a/src/rpc/client.cpp
+++ b/src/rpc/client.cpp
@@ -157,6 +157,7 @@
{"rescanblockchain", 0, "start_height"},
{"rescanblockchain", 1, "stop_height"},
{"createwallet", 1, "disable_private_keys"},
+ {"createwallet", 2, "blank"},
};
class CRPCConvertTable {
diff --git a/src/wallet/crypter.cpp b/src/wallet/crypter.cpp
--- a/src/wallet/crypter.cpp
+++ b/src/wallet/crypter.cpp
@@ -206,7 +206,8 @@
return false;
}
- bool keyPass = false;
+ // Always pass when there are no encrypted keys
+ bool keyPass = mapCryptedKeys.empty();
bool keyFail = false;
CryptedKeyMap::const_iterator mi = mapCryptedKeys.begin();
for (; mi != mapCryptedKeys.end(); ++mi) {
diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp
--- a/src/wallet/rpcwallet.cpp
+++ b/src/wallet/rpcwallet.cpp
@@ -180,6 +180,7 @@
HelpExampleRpc("getnewaddress", ""));
}
+ // 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");
@@ -187,6 +188,11 @@
LOCK(pwallet->cs_wallet);
+ if (!pwallet->CanGetAddresses()) {
+ 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
std::string label;
if (!request.params[0].isNull()) {
@@ -307,6 +313,7 @@
HelpExampleRpc("getrawchangeaddress", ""));
}
+ // 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");
@@ -314,6 +321,11 @@
LOCK(pwallet->cs_wallet);
+ if (!pwallet->CanGetAddresses(true)) {
+ throw JSONRPCError(RPC_WALLET_ERROR,
+ "Error: This wallet has no available keys");
+ }
+
if (!pwallet->IsLocked()) {
pwallet->TopUpKeyPool();
}
@@ -3781,7 +3793,7 @@
static UniValue createwallet(const Config &config,
const JSONRPCRequest &request) {
if (request.fHelp || request.params.size() < 1 ||
- request.params.size() > 2) {
+ request.params.size() > 3) {
throw std::runtime_error(
"createwallet \"wallet_name\" ( disable_private_keys )\n"
"\nCreates and loads a new wallet.\n"
@@ -3792,6 +3804,9 @@
"2. disable_private_keys (boolean, optional, default: false) "
"Disable the possibility of private keys (only watchonlys are "
"possible in this mode).\n"
+ "3. blank (boolean, optional, default: false) Create a blank "
+ "wallet. A blank wallet has no keys or HD seed. One can be set "
+ "using sethdseed.\n"
"\nResult:\n"
"{\n"
" \"name\" : <wallet_name>, (string) The wallet name if "
@@ -3810,9 +3825,13 @@
std::string error;
std::string warning;
- bool disable_privatekeys = false;
- if (!request.params[1].isNull()) {
- disable_privatekeys = request.params[1].get_bool();
+ uint64_t flags = 0;
+ if (!request.params[1].isNull() && request.params[1].get_bool()) {
+ flags |= WALLET_FLAG_DISABLE_PRIVATE_KEYS;
+ }
+
+ if (!request.params[2].isNull() && request.params[2].get_bool()) {
+ flags |= WALLET_FLAG_BLANK_WALLET;
}
WalletLocation location(request.params[0].get_str());
@@ -3828,9 +3847,8 @@
"Wallet file verification failed: " + error);
}
- std::shared_ptr<CWallet> const wallet = CWallet::CreateWalletFromFile(
- chainParams, location,
- (disable_privatekeys ? uint64_t(WALLET_FLAG_DISABLE_PRIVATE_KEYS) : 0));
+ std::shared_ptr<CWallet> const wallet =
+ CWallet::CreateWalletFromFile(chainParams, location, flags);
if (!wallet) {
throw JSONRPCError(RPC_WALLET_ERROR, "Wallet creation failed.");
}
@@ -5063,7 +5081,7 @@
LOCK2(cs_main, pwallet->cs_wallet);
// Do not do anything to non-HD wallets
- if (!pwallet->IsHDEnabled()) {
+ if (!pwallet->CanSupportFeature(FEATURE_HD)) {
throw JSONRPCError(
RPC_WALLET_ERROR,
"Cannot set a HD seed on a non-HD wallet. Start with "
@@ -5410,7 +5428,7 @@
{ "wallet", "abandontransaction", abandontransaction, {"txid"} },
{ "wallet", "addmultisigaddress", addmultisigaddress, {"nrequired","keys","label|account"} },
{ "wallet", "backupwallet", backupwallet, {"destination"} },
- { "wallet", "createwallet", createwallet, {"wallet_name", "disable_private_keys"} },
+ { "wallet", "createwallet", createwallet, {"wallet_name", "disable_private_keys", "blank"} },
{ "wallet", "encryptwallet", encryptwallet, {"passphrase"} },
{ "wallet", "getaddressinfo", getaddressinfo, {"address"} },
{ "wallet", "getbalance", getbalance, {"account|dummy","minconf","include_watchonly"} },
diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp
--- a/src/wallet/test/wallet_tests.cpp
+++ b/src/wallet/test/wallet_tests.cpp
@@ -404,6 +404,7 @@
BOOST_FIXTURE_TEST_CASE(wallet_disableprivkeys, TestChain100Setup) {
std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(
Params(), WalletLocation(), WalletDatabase::CreateDummy());
+ wallet->SetMinVersion(FEATURE_LATEST);
wallet->SetWalletFlag(WALLET_FLAG_DISABLE_PRIVATE_KEYS);
BOOST_CHECK(!wallet->TopUpKeyPool(1000));
CPubKey pubkey;
diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h
--- a/src/wallet/wallet.h
+++ b/src/wallet/wallet.h
@@ -109,10 +109,22 @@
// Will enforce the rule that the wallet can't contain any private keys
// (only watch-only/pubkeys).
WALLET_FLAG_DISABLE_PRIVATE_KEYS = (1ULL << 32),
+
+ //! Flag set when a wallet contains no HD seed and no private keys, scripts,
+ //! addresses, and other watch only things, and is therefore "blank."
+ //!
+ //! The only function this flag serves is to distinguish a blank wallet from
+ //! a newly created wallet when the wallet database is loaded, to avoid
+ //! initialization that should only happen on first run.
+ //!
+ //! This flag is also a mandatory flag to prevent previous versions of
+ //! bitcoin from opening the wallet, thinking it was newly created, and
+ //! then improperly reinitializing it.
+ WALLET_FLAG_BLANK_WALLET = (1ULL << 33),
};
static constexpr uint64_t g_known_wallet_flags =
- WALLET_FLAG_DISABLE_PRIVATE_KEYS;
+ WALLET_FLAG_DISABLE_PRIVATE_KEYS | WALLET_FLAG_BLANK_WALLET;
/** A key pool entry */
class CKeyPool {
@@ -1355,6 +1367,15 @@
/* Returns true if HD is enabled */
bool IsHDEnabled() const;
+ /* Returns true if the wallet can generate new keys */
+ bool CanGenerateKeys();
+
+ /**
+ * Returns true if the wallet can give out new addresses. This means it has
+ * keys in the keypool or can generate new keys.
+ */
+ bool CanGetAddresses(bool internal = false);
+
/* Generates a new HD seed (will not be activated) */
CPubKey GenerateNewSeed();
@@ -1398,6 +1419,11 @@
*/
void SetWalletFlag(uint64_t flags);
+ /**
+ * Unsets a single wallet flag.
+ */
+ void UnsetWalletFlag(uint64_t flag);
+
/**
* Check if a certain wallet flag is set.
*/
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -161,6 +161,7 @@
CPubKey CWallet::GenerateNewKey(WalletBatch &batch, bool internal) {
assert(!IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS));
+ assert(!IsWalletFlagSet(WALLET_FLAG_BLANK_WALLET));
// mapKeyMetadata
AssertLockHeld(cs_wallet);
// default to compressed public keys if we want 0.6.0 wallets
@@ -172,7 +173,8 @@
int64_t nCreationTime = GetTime();
CKeyMetadata metadata(nCreationTime);
- // use HD key derivation if HD was enabled during wallet creation
+ // use HD key derivation if HD was enabled during wallet creation and a seed
+ // is present
if (IsHDEnabled()) {
DeriveNewChildKey(
batch, metadata, secret,
@@ -299,12 +301,13 @@
RemoveWatchOnly(script);
}
- if (IsCrypted()) {
- return true;
+ if (!IsCrypted()) {
+ return batch.WriteKey(pubkey, secret.GetPrivKey(),
+ mapKeyMetadata[pubkey.GetID()]);
}
- return batch.WriteKey(pubkey, secret.GetPrivKey(),
- mapKeyMetadata[pubkey.GetID()]);
+ UnsetWalletFlag(WALLET_FLAG_BLANK_WALLET);
+ return true;
}
bool CWallet::AddKeyPubKey(const CKey &secret, const CPubKey &pubkey) {
@@ -367,9 +370,12 @@
if (!CCryptoKeyStore::AddCScript(redeemScript)) {
return false;
}
-
- return WalletBatch(*database).WriteCScript(Hash160(redeemScript),
- redeemScript);
+ if (WalletBatch(*database).WriteCScript(Hash160(redeemScript),
+ redeemScript)) {
+ UnsetWalletFlag(WALLET_FLAG_BLANK_WALLET);
+ return true;
+ }
+ return false;
}
bool CWallet::LoadCScript(const CScript &redeemScript) {
@@ -400,7 +406,11 @@
const CKeyMetadata &meta = m_script_metadata[CScriptID(dest)];
UpdateTimeFirstKey(meta.nCreateTime);
NotifyWatchonlyChanged(true);
- return WalletBatch(*database).WriteWatchOnly(dest, meta);
+ if (WalletBatch(*database).WriteWatchOnly(dest, meta)) {
+ UnsetWalletFlag(WALLET_FLAG_BLANK_WALLET);
+ return true;
+ }
+ return false;
}
bool CWallet::AddWatchOnly(const CScript &dest, int64_t nCreateTime) {
@@ -1585,6 +1595,7 @@
newHdChain.seed_id = seed.GetID();
SetHDChain(newHdChain, false);
NotifyCanGetAddressesChanged();
+ UnsetWalletFlag(WALLET_FLAG_BLANK_WALLET);
}
void CWallet::SetHDChain(const CHDChain &chain, bool memonly) {
@@ -1601,6 +1612,29 @@
return !hdChain.seed_id.IsNull();
}
+bool CWallet::CanGenerateKeys() {
+ // A wallet can generate keys if it has an HD seed (IsHDEnabled) or it is a
+ // non-HD wallet (pre FEATURE_HD)
+ LOCK(cs_wallet);
+ return IsHDEnabled() || !CanSupportFeature(FEATURE_HD);
+}
+
+bool CWallet::CanGetAddresses(bool internal) {
+ LOCK(cs_wallet);
+ // Check if the keypool has keys
+ bool keypool_has_keys;
+ if (internal && CanSupportFeature(FEATURE_HD_SPLIT)) {
+ keypool_has_keys = setInternalKeyPool.size() > 0;
+ } else {
+ keypool_has_keys = KeypoolCountExternalKeys() > 0;
+ }
+ // If the keypool doesn't have keys, check if we can generate them
+ if (!keypool_has_keys) {
+ return CanGenerateKeys();
+ }
+ return keypool_has_keys;
+}
+
void CWallet::SetWalletFlag(uint64_t flags) {
LOCK(cs_wallet);
m_wallet_flags |= flags;
@@ -1610,6 +1644,15 @@
}
}
+void CWallet::UnsetWalletFlag(uint64_t flag) {
+ LOCK(cs_wallet);
+ m_wallet_flags &= ~flag;
+ if (!WalletBatch(*database).WriteWalletFlags(m_wallet_flags)) {
+ throw std::runtime_error(std::string(__func__) +
+ ": writing wallet flags failed");
+ }
+}
+
bool CWallet::IsWalletFlagSet(uint64_t flag) {
return (m_wallet_flags & flag);
}
@@ -3430,7 +3473,8 @@
fFirstRunRet = mapKeys.empty() && mapCryptedKeys.empty() &&
mapWatchKeys.empty() && setWatchOnly.empty() &&
mapScripts.empty() &&
- !IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS);
+ !IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS) &&
+ !IsWalletFlagSet(WALLET_FLAG_BLANK_WALLET);
}
if (nLoadWalletRet != DBErrors::LOAD_OK) {
@@ -3620,7 +3664,7 @@
}
bool CWallet::TopUpKeyPool(unsigned int kpSize) {
- if (IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
+ if (!CanGenerateKeys()) {
return false;
}
{
@@ -3768,7 +3812,7 @@
}
bool CWallet::GetKeyFromPool(CPubKey &result, bool internal) {
- if (IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
+ if (!CanGetAddresses(internal)) {
return false;
}
@@ -3998,6 +4042,10 @@
}
bool CReserveKey::GetReservedKey(CPubKey &pubkey, bool internal) {
+ if (!pwallet->CanGetAddresses(internal)) {
+ return false;
+ }
+
if (nIndex == -1) {
CKeyPool keypool;
if (!pwallet->ReserveKeyFromKeyPool(nIndex, keypool, internal)) {
@@ -4530,15 +4578,16 @@
if ((wallet_creation_flags & WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
// selective allow to set flags
walletInstance->SetWalletFlag(WALLET_FLAG_DISABLE_PRIVATE_KEYS);
+ } else if (wallet_creation_flags & WALLET_FLAG_BLANK_WALLET) {
+ walletInstance->SetWalletFlag(WALLET_FLAG_BLANK_WALLET);
} else {
// generate a new seed
CPubKey seed = walletInstance->GenerateNewSeed();
walletInstance->SetHDSeed(seed);
- }
+ } // Otherwise, do not generate a new seed
// Top up the keypool
- if (!walletInstance->IsWalletFlagSet(
- WALLET_FLAG_DISABLE_PRIVATE_KEYS) &&
+ if (walletInstance->CanGenerateKeys() &&
!walletInstance->TopUpKeyPool()) {
InitError(_("Unable to generate initial keys"));
return nullptr;
diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py
--- a/test/functional/test_runner.py
+++ b/test/functional/test_runner.py
@@ -76,8 +76,8 @@
# testname --param3
"wallet_txn_doublespend.py": [["--mineblock"]],
"wallet_txn_clone.py": [["--mineblock"]],
+ "wallet_createwallet.py": [["--usecli"]],
"wallet_multiwallet.py": [["--usecli"]],
- "wallet_disableprivatekeys.py": [["--usecli"]],
}
# Used to limit the number of tests, when list of tests is not provided on command line
@@ -258,8 +258,8 @@
# Remove the test cases that the user has explicitly asked to exclude.
if args.exclude:
- tests_excl = [re.sub(r"\.py$", "", t) +
- ".py" for t in args.exclude.split(',')]
+ tests_excl = [re.sub(r"\.py$", "", t)
+ + ".py" for t in args.exclude.split(',')]
for exclude_test in tests_excl:
if exclude_test in test_list:
test_list.remove(exclude_test)
@@ -438,7 +438,8 @@
update_queue.task_done()
except Empty:
if not on_ci():
- print("Running jobs: {}".format(", ".join([j[1] for j in running_jobs])), end="\r")
+ print("Running jobs: {}".format(
+ ", ".join([j[1] for j in running_jobs])), end="\r")
sys.stdout.flush()
printed_status = True
diff --git a/test/functional/timing.json b/test/functional/timing.json
--- a/test/functional/timing.json
+++ b/test/functional/timing.json
@@ -375,14 +375,6 @@
"name": "wallet_disable.py",
"time": 0
},
- {
- "name": "wallet_disableprivatekeys.py",
- "time": 1
- },
- {
- "name": "wallet_disableprivatekeys.py --usecli",
- "time": 1
- },
{
"name": "wallet_dump.py",
"time": 4
diff --git a/test/functional/wallet_createwallet.py b/test/functional/wallet_createwallet.py
new file mode 100755
--- /dev/null
+++ b/test/functional/wallet_createwallet.py
@@ -0,0 +1,128 @@
+#!/usr/bin/env python3
+# Copyright (c) 2018 The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+"""Test createwallet arguments.
+"""
+
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import (
+ assert_equal,
+ assert_raises_rpc_error,
+)
+
+
+class CreateWalletTest(BitcoinTestFramework):
+ def set_test_params(self):
+ self.setup_clean_chain = False
+ self.num_nodes = 1
+ self.supports_cli = True
+
+ def skip_test_if_missing_module(self):
+ self.skip_if_no_wallet()
+
+ def run_test(self):
+ node = self.nodes[0]
+ # Leave IBD for sethdseed
+ node.generate(1)
+
+ self.nodes[0].createwallet(wallet_name='w0')
+ w0 = node.get_wallet_rpc('w0')
+ address1 = w0.getnewaddress()
+
+ self.log.info("Test disableprivatekeys creation.")
+ self.nodes[0].createwallet(wallet_name='w1', disable_private_keys=True)
+ 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: Private keys are disabled for this wallet", w1.getrawchangeaddress)
+ w1.importpubkey(w0.getaddressinfo(address1)['pubkey'])
+
+ self.log.info('Test that private keys cannot be imported')
+ addr = w0.getnewaddress('', 'legacy')
+ privkey = w0.dumpprivkey(addr)
+ assert_raises_rpc_error(
+ -4, 'Cannot import private keys to a wallet with private keys disabled', w1.importprivkey, privkey)
+ result = w1.importmulti(
+ [{'scriptPubKey': {'address': addr}, 'timestamp': 'now', 'keys': [privkey]}])
+ assert(not result[0]['success'])
+ assert('warning' not in result[0])
+ assert_equal(result[0]['error']['code'], -4)
+ assert_equal(result[0]['error']['message'],
+ 'Cannot import private keys to a wallet 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)
+ 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: Private keys are disabled for this wallet", w2.getrawchangeaddress)
+ w2.importpubkey(w0.getaddressinfo(address1)['pubkey'])
+
+ self.log.info("Test blank creation with private keys enabled.")
+ self.nodes[0].createwallet(
+ wallet_name='w3', disable_private_keys=False, blank=True)
+ w3 = node.get_wallet_rpc('w3')
+ assert_equal(w3.getwalletinfo()['keypoolsize'], 0)
+ assert_raises_rpc_error(-4,
+ "Error: This wallet has no available keys", w3.getnewaddress)
+ assert_raises_rpc_error(-4, "Error: This wallet has no available keys",
+ w3.getrawchangeaddress)
+ # Import private key
+ w3.importprivkey(w0.dumpprivkey(address1))
+ # Imported private keys are currently ignored by the keypool
+ assert_equal(w3.getwalletinfo()['keypoolsize'], 0)
+ assert_raises_rpc_error(-4,
+ "Error: This wallet has no available keys", w3.getnewaddress)
+ # Set the seed
+ w3.sethdseed()
+ assert_equal(w3.getwalletinfo()['keypoolsize'], 1)
+ w3.getnewaddress()
+ w3.getrawchangeaddress()
+
+ self.log.info(
+ "Test blank creation with privkeys enabled and then encryption")
+ self.nodes[0].createwallet(
+ wallet_name='w4', disable_private_keys=False, blank=True)
+ w4 = node.get_wallet_rpc('w4')
+ assert_equal(w4.getwalletinfo()['keypoolsize'], 0)
+ assert_raises_rpc_error(-4,
+ "Error: This wallet has no available keys", w4.getnewaddress)
+ assert_raises_rpc_error(-4, "Error: This wallet has no available keys",
+ w4.getrawchangeaddress)
+ # Encrypt the wallet. Nothing should change about the keypool
+ w4.encryptwallet('pass')
+ assert_raises_rpc_error(-4,
+ "Error: This wallet has no available keys", w4.getnewaddress)
+ assert_raises_rpc_error(-4, "Error: This wallet has no available keys",
+ w4.getrawchangeaddress)
+ # Now set a seed and it should work. Wallet should also be encrypted
+ w4.walletpassphrase('pass', 2)
+ w4.sethdseed()
+ w4.getnewaddress()
+ w4.getrawchangeaddress()
+
+ self.log.info(
+ "Test blank creation with privkeys disabled and then encryption")
+ self.nodes[0].createwallet(
+ wallet_name='w5', disable_private_keys=True, blank=True)
+
+ w5 = node.get_wallet_rpc('w5')
+ 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: Private keys are disabled for this wallet", w5.getrawchangeaddress)
+ # Encrypt the wallet
+ w5.encryptwallet('pass')
+ assert_raises_rpc_error(
+ -4, "Error: Private keys are disabled for this wallet", w5.getnewaddress)
+ assert_raises_rpc_error(
+ -4, "Error: Private keys are disabled for this wallet", w5.getrawchangeaddress)
+
+
+if __name__ == '__main__':
+ CreateWalletTest().main()
diff --git a/test/functional/wallet_disableprivatekeys.py b/test/functional/wallet_disableprivatekeys.py
deleted file mode 100755
--- a/test/functional/wallet_disableprivatekeys.py
+++ /dev/null
@@ -1,49 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (c) 2018 The Bitcoin Core developers
-# Distributed under the MIT software license, see the accompanying
-# file COPYING or http://www.opensource.org/licenses/mit-license.php.
-"""Test disable-privatekeys mode.
-"""
-
-from test_framework.test_framework import BitcoinTestFramework
-from test_framework.util import (
- assert_equal,
- assert_raises_rpc_error,
-)
-
-
-class DisablePrivateKeysTest(BitcoinTestFramework):
- def set_test_params(self):
- self.setup_clean_chain = False
- self.num_nodes = 1
- self.supports_cli = True
-
- def run_test(self):
- node = self.nodes[0]
- self.log.info("Test disableprivatekeys creation.")
- self.nodes[0].createwallet('w1', True)
- self.nodes[0].createwallet('w2')
- w1 = node.get_wallet_rpc('w1')
- w2 = node.get_wallet_rpc('w2')
- assert_raises_rpc_error(
- -4, "Error: Private keys are disabled for this wallet", w1.getnewaddress)
- assert_raises_rpc_error(
- -4, "Error: Private keys are disabled for this wallet", w1.getrawchangeaddress)
- w1.importpubkey(w2.getaddressinfo(w2.getnewaddress())['pubkey'])
-
- self.log.info('Test that private keys cannot be imported')
- addr = w2.getnewaddress('', 'legacy')
- privkey = w2.dumpprivkey(addr)
- assert_raises_rpc_error(
- -4, 'Cannot import private keys to a wallet with private keys disabled', w1.importprivkey, privkey)
- result = w1.importmulti(
- [{'scriptPubKey': {'address': addr}, 'timestamp': 'now', 'keys': [privkey]}])
- assert(not result[0]['success'])
- assert('warning' not in result[0])
- assert_equal(result[0]['error']['code'], -4)
- assert_equal(result[0]['error']['message'],
- 'Cannot import private keys to a wallet with private keys disabled')
-
-
-if __name__ == '__main__':
- DisablePrivateKeysTest().main()

File Metadata

Mime Type
text/plain
Expires
Tue, May 20, 21:58 (18 h, 4 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
5865063
Default Alt Text
D4921.id15444.diff (26 KB)

Event Timeline