Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F14864730
D4921.id15444.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
26 KB
Subscribers
None
D4921.id15444.diff
View Options
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
Details
Attached
Mime Type
text/plain
Expires
Tue, May 20, 21:58 (20 h, 18 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
5865063
Default Alt Text
D4921.id15444.diff (26 KB)
Attached To
D4921: [wallet] Support creating a blank wallet
Event Timeline
Log In to Comment