diff --git a/doc/release-notes.md b/doc/release-notes.md
--- a/doc/release-notes.md
+++ b/doc/release-notes.md
@@ -5,3 +5,6 @@
This release includes the following features and fixes:
+ - The `-zapwallettxes` startup option has been removed and its functionality removed
+ from the wallet. This functionality has been superseded with the abandon transaction
+ feature.
diff --git a/src/dummywallet.cpp b/src/dummywallet.cpp
--- a/src/dummywallet.cpp
+++ b/src/dummywallet.cpp
@@ -31,7 +31,7 @@
"-keypool=", "-maxapsfee=", "-maxtxfee=", "-mintxfee=",
"-paytxfee=", "-rescan", "-salvagewallet", "-spendzeroconfchange",
"-upgradewallet", "-wallet=", "-walletbroadcast",
- "-walletdir=", "-walletnotify=", "-zapwallettxes=",
+ "-walletdir=", "-walletnotify=",
// Wallet debug options
"-dblogsize=", "-flushwallet", "-privdb", "-walletrejectlongchains"};
argsman.AddHiddenArgs(opts);
diff --git a/src/wallet/init.cpp b/src/wallet/init.cpp
--- a/src/wallet/init.cpp
+++ b/src/wallet/init.cpp
@@ -135,13 +135,6 @@
"shell escaping used to invoke the command.",
ArgsManager::ALLOW_ANY, OptionsCategory::WALLET);
#endif
- argsman.AddArg(
- "-zapwallettxes=",
- "Delete all wallet transactions and only recover those parts of the "
- "blockchain through -rescan on startup (1 = keep tx meta data e.g. "
- "payment request information, 2 = drop tx meta data)",
- ArgsManager::ALLOW_ANY, OptionsCategory::WALLET);
-
argsman.AddArg(
"-dblogsize=",
strprintf("Flush wallet database activity from memory to disk "
@@ -167,6 +160,8 @@
DEFAULT_WALLET_REJECT_LONG_CHAINS),
ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY,
OptionsCategory::WALLET_DEBUG_TEST);
+
+ argsman.AddHiddenArgs({"-zapwallettxes"});
}
bool WalletInit::ParameterInteraction() const {
@@ -180,8 +175,6 @@
return true;
}
- const bool is_multiwallet = gArgs.GetArgs("-wallet").size() > 1;
-
if (gArgs.GetBoolArg("-blocksonly", DEFAULT_BLOCKSONLY) &&
gArgs.SoftSetBoolArg("-walletbroadcast", false)) {
LogPrintf("%s: parameter interaction: -blocksonly=1 -> setting "
@@ -189,26 +182,11 @@
__func__);
}
- bool zapwallettxes = gArgs.GetBoolArg("-zapwallettxes", false);
- // -zapwallettxes implies dropping the mempool on startup
- if (zapwallettxes && gArgs.SoftSetBoolArg("-persistmempool", false)) {
- LogPrintf("%s: parameter interaction: -zapwallettxes enabled -> "
- "setting -persistmempool=0\n",
- __func__);
- }
-
- // -zapwallettxes implies a rescan
- if (zapwallettxes) {
- if (is_multiwallet) {
- return InitError(strprintf(
- Untranslated("%s is only allowed with a single wallet file"),
- "-zapwallettxes"));
- }
- if (gArgs.SoftSetBoolArg("-rescan", true)) {
- LogPrintf("%s: parameter interaction: -zapwallettxes enabled -> "
- "setting -rescan=1\n",
- __func__);
- }
+ if (gArgs.IsArgSet("-zapwallettxes")) {
+ return InitError(
+ Untranslated("-zapwallettxes has been removed. If you are "
+ "attempting to remove a stuck transaction from your "
+ "wallet, please use abandontransaction instead."));
}
if (gArgs.GetBoolArg("-sysperms", false)) {
diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp
--- a/src/wallet/rpcwallet.cpp
+++ b/src/wallet/rpcwallet.cpp
@@ -3102,7 +3102,7 @@
"Loads a wallet from a wallet file or directory."
"\nNote that all wallet command-line options used when starting "
"bitcoind will be"
- "\napplied to the new wallet (eg -zapwallettxes, rescan, etc).\n",
+ "\napplied to the new wallet (eg -rescan, etc).\n",
{
{"filename", RPCArg::Type::STR, RPCArg::Optional::NO,
"The wallet directory or .dat file."},
diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h
--- a/src/wallet/wallet.h
+++ b/src/wallet/wallet.h
@@ -1288,7 +1288,6 @@
void chainStateFlushed(const CBlockLocator &loc) override;
DBErrors LoadWallet(bool &fFirstRunRet);
- DBErrors ZapWalletTx(std::list &vWtx);
DBErrors ZapSelectTx(std::vector &txIdsIn,
std::vector &txIdsOut)
EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -3540,23 +3540,6 @@
return DBErrors::LOAD_OK;
}
-DBErrors CWallet::ZapWalletTx(std::list &vWtx) {
- DBErrors nZapWalletTxRet = WalletBatch(*database, "cr+").ZapWalletTx(vWtx);
- if (nZapWalletTxRet == DBErrors::NEED_REWRITE) {
- if (database->Rewrite("\x04pool")) {
- for (const auto &spk_man_pair : m_spk_managers) {
- spk_man_pair.second->RewriteDB();
- }
- }
- }
-
- if (nZapWalletTxRet != DBErrors::LOAD_OK) {
- return nZapWalletTxRet;
- }
-
- return DBErrors::LOAD_OK;
-}
-
bool CWallet::SetAddressBookWithDB(WalletBatch &batch,
const CTxDestination &address,
const std::string &strName,
@@ -4196,23 +4179,6 @@
const std::string walletFile =
WalletDataFilePath(location.GetPath()).string();
- // Needed to restore wallet transaction meta data after -zapwallettxes
- std::list vWtx;
-
- if (gArgs.GetBoolArg("-zapwallettxes", false)) {
- chain.initMessage(
- _("Zapping all transactions from wallet...").translated);
-
- std::unique_ptr tempWallet = std::make_unique(
- &chain, location, CreateWalletDatabase(location.GetPath()));
- DBErrors nZapWalletRet = tempWallet->ZapWalletTx(vWtx);
- if (nZapWalletRet != DBErrors::LOAD_OK) {
- error =
- strprintf(_("Error loading %s: Wallet corrupted"), walletFile);
- return nullptr;
- }
- }
-
chain.initMessage(_("Loading wallet...").translated);
int64_t nStart = GetTimeMillis();
@@ -4512,29 +4478,6 @@
}
walletInstance->chainStateFlushed(chain.getTipLocator());
walletInstance->database->IncrementUpdateCounter();
-
- // Restore wallet transaction metadata after -zapwallettxes=1
- if (gArgs.GetBoolArg("-zapwallettxes", false) &&
- gArgs.GetArg("-zapwallettxes", "1") != "2") {
- WalletBatch batch(*walletInstance->database);
-
- for (const CWalletTx &wtxOld : vWtx) {
- const TxId txid = wtxOld.GetId();
- std::map::iterator mi =
- walletInstance->mapWallet.find(txid);
- if (mi != walletInstance->mapWallet.end()) {
- const CWalletTx *copyFrom = &wtxOld;
- CWalletTx *copyTo = &mi->second;
- copyTo->mapValue = copyFrom->mapValue;
- copyTo->vOrderForm = copyFrom->vOrderForm;
- copyTo->nTimeReceived = copyFrom->nTimeReceived;
- copyTo->nTimeSmart = copyFrom->nTimeSmart;
- copyTo->fFromMe = copyFrom->fFromMe;
- copyTo->nOrderPos = copyFrom->nOrderPos;
- batch.WriteTx(*copyTo);
- }
- }
- }
}
{
diff --git a/src/wallet/walletdb.h b/src/wallet/walletdb.h
--- a/src/wallet/walletdb.h
+++ b/src/wallet/walletdb.h
@@ -267,7 +267,6 @@
DBErrors LoadWallet(CWallet *pwallet);
DBErrors FindWalletTx(std::vector &txIds, std::list &vWtx);
- DBErrors ZapWalletTx(std::list &vWtx);
DBErrors ZapSelectTx(std::vector &txIdsIn,
std::vector &txIdsOut);
/* Function to determine if a certain KV/key-type is a key (cryptographical
diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp
--- a/src/wallet/walletdb.cpp
+++ b/src/wallet/walletdb.cpp
@@ -1032,24 +1032,6 @@
return DBErrors::LOAD_OK;
}
-DBErrors WalletBatch::ZapWalletTx(std::list &vWtx) {
- // Build list of wallet TXs.
- std::vector txIds;
- DBErrors err = FindWalletTx(txIds, vWtx);
- if (err != DBErrors::LOAD_OK) {
- return err;
- }
-
- // Erase each wallet TX.
- for (const TxId &txid : txIds) {
- if (!EraseTx(txid)) {
- return DBErrors::CORRUPT;
- }
- }
-
- return DBErrors::LOAD_OK;
-}
-
void MaybeCompactWalletDB() {
static std::atomic fOneThread;
if (fOneThread.exchange(true)) {
diff --git a/test/functional/wallet_basic.py b/test/functional/wallet_basic.py
--- a/test/functional/wallet_basic.py
+++ b/test/functional/wallet_basic.py
@@ -490,8 +490,6 @@
maintenance = [
'-rescan',
'-reindex',
- '-zapwallettxes=1',
- '-zapwallettxes=2',
]
chainlimit = 6
for m in maintenance:
diff --git a/test/functional/wallet_multiwallet.py b/test/functional/wallet_multiwallet.py
--- a/test/functional/wallet_multiwallet.py
+++ b/test/functional/wallet_multiwallet.py
@@ -157,26 +157,6 @@
self.nodes[0].assert_start_raises_init_error(
['-walletdir=' + not_a_dir], 'Error: Specified -walletdir "' + not_a_dir + '" is not a directory')
- self.log.info("Do not allow -zapwallettxes with multiwallet")
- self.nodes[0].assert_start_raises_init_error(
- [
- '-zapwallettxes',
- '-wallet=w1',
- '-wallet=w2'],
- "Error: -zapwallettxes is only allowed with a single wallet file")
- self.nodes[0].assert_start_raises_init_error(
- [
- '-zapwallettxes=1',
- '-wallet=w1',
- '-wallet=w2'],
- "Error: -zapwallettxes is only allowed with a single wallet file")
- self.nodes[0].assert_start_raises_init_error(
- [
- '-zapwallettxes=2',
- '-wallet=w1',
- '-wallet=w2'],
- "Error: -zapwallettxes is only allowed with a single wallet file")
-
# if wallets/ doesn't exist, datadir should be the default wallet dir
wallet_dir2 = data_dir('walletdir')
os.rename(wallet_dir(), wallet_dir2)
diff --git a/test/functional/wallet_zapwallettxes.py b/test/functional/wallet_zapwallettxes.py
deleted file mode 100755
--- a/test/functional/wallet_zapwallettxes.py
+++ /dev/null
@@ -1,86 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (c) 2014-2016 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 the zapwallettxes functionality.
-
-- start two bitcoind nodes
-- create two transactions on node 0 - one is confirmed and one is unconfirmed.
-- restart node 0 and verify that both the confirmed and the unconfirmed
- transactions are still available.
-- restart node 0 with zapwallettxes and persistmempool, and verify that both
- the confirmed and the unconfirmed transactions are still available.
-- restart node 0 with just zapwallettxes and verify that the confirmed
- transactions are still available, but that the unconfirmed transaction has
- been zapped.
-"""
-from test_framework.test_framework import BitcoinTestFramework
-from test_framework.util import (
- assert_equal,
- assert_raises_rpc_error,
-)
-
-
-class ZapWalletTXesTest (BitcoinTestFramework):
- def set_test_params(self):
- self.setup_clean_chain = True
- self.num_nodes = 2
-
- def skip_test_if_missing_module(self):
- self.skip_if_no_wallet()
-
- def run_test(self):
- self.log.info("Mining blocks...")
- self.nodes[0].generate(1)
- self.sync_all()
- self.nodes[1].generate(100)
- self.sync_all()
-
- # This transaction will be confirmed
- txid1 = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 10)
-
- self.nodes[0].generate(1)
- self.sync_all()
-
- # This transaction will not be confirmed
- txid2 = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 20)
-
- # Confirmed and unconfirmed transactions are now in the wallet.
- assert_equal(self.nodes[0].gettransaction(txid1)['txid'], txid1)
- assert_equal(self.nodes[0].gettransaction(txid2)['txid'], txid2)
-
- # Restart node0. Both confirmed and unconfirmed transactions remain
- # in the wallet.
- self.restart_node(0)
-
- assert_equal(self.nodes[0].gettransaction(txid1)['txid'], txid1)
- assert_equal(self.nodes[0].gettransaction(txid2)['txid'], txid2)
-
- # Restart node0 with zapwallettxes and persistmempool. The unconfirmed
- # transaction is zapped from the wallet, but is re-added when the
- # mempool is reloaded.
- self.restart_node(0, ["-persistmempool=1", "-zapwallettxes=2"])
-
- self.wait_until(lambda: self.nodes[0].getmempoolinfo()['size'] == 1,
- timeout=3)
- # Flush mempool to wallet
- self.nodes[0].syncwithvalidationinterfacequeue()
-
- assert_equal(self.nodes[0].gettransaction(txid1)['txid'], txid1)
- assert_equal(self.nodes[0].gettransaction(txid2)['txid'], txid2)
-
- # Restart node0 with zapwallettxes, but not persistmempool.
- # The unconfirmed transaction is zapped and is no longer in the wallet.
- self.restart_node(0, ["-zapwallettxes=2"])
-
- # tx1 is still be available because it was confirmed
- assert_equal(self.nodes[0].gettransaction(txid1)['txid'], txid1)
-
- # This will raise an exception because the unconfirmed transaction has
- # been zapped
- assert_raises_rpc_error(-5, 'Invalid or non-wallet transaction id',
- self.nodes[0].gettransaction, txid2)
-
-
-if __name__ == '__main__':
- ZapWalletTXesTest().main()
diff --git a/test/lint/check-doc.py b/test/lint/check-doc.py
--- a/test/lint/check-doc.py
+++ b/test/lint/check-doc.py
@@ -48,6 +48,8 @@
'-forcecompactdb',
'-parkdeepreorg',
'-automaticunparking',
+ # Removed arguments that now just print a helpful error message
+ '-zapwallettxes',
# Remove after November 2020 upgrade
'-axionactivationtime',
'-replayprotectionactivationtime',