Skip to content

Commit e7a2181

Browse files
committed
[wallet] fix zapwallettxes interaction with persistent mempool
zapwallettxes previously did not interact well with persistent mempool. zapwallettxes would cause wallet transactions to be zapped, but they would then be reloaded from the mempool on startup. This commit softsets persistmempool to false if zapwallettxes is enabled so transactions are actually zapped.
1 parent ff7365e commit e7a2181

File tree

2 files changed

+41
-44
lines changed

2 files changed

+41
-44
lines changed

src/wallet/wallet.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4043,6 +4043,11 @@ bool CWallet::ParameterInteraction()
40434043
}
40444044
}
40454045

4046+
// -zapwallettx implies dropping the mempool on startup
4047+
if (GetBoolArg("-zapwallettxes", false) && SoftSetBoolArg("-persistmempool", false)) {
4048+
LogPrintf("%s: parameter interaction: -zapwallettxes=<mode> -> setting -persistmempool=0\n", __func__);
4049+
}
4050+
40464051
// -zapwallettx implies a rescan
40474052
if (GetBoolArg("-zapwallettxes", false)) {
40484053
if (is_multiwallet) {

test/functional/zapwallettxes.py

Lines changed: 36 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -4,81 +4,73 @@
44
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
55
"""Test the zapwallettxes functionality.
66
7-
- start three bitcoind nodes
8-
- create four transactions on node 0 - two are confirmed and two are
9-
unconfirmed.
10-
- restart node 1 and verify that both the confirmed and the unconfirmed
7+
- start two bitcoind nodes
8+
- create two transactions on node 0 - one is confirmed and one is unconfirmed.
9+
- restart node 0 and verify that both the confirmed and the unconfirmed
1110
transactions are still available.
12-
- restart node 0 and verify that the confirmed transactions are still
13-
available, but that the unconfirmed transaction has been zapped.
11+
- restart node 0 with zapwallettxes and persistmempool, and verify that both
12+
the confirmed and the unconfirmed transactions are still available.
13+
- restart node 0 with just zapwallettxed and verify that the confirmed
14+
transactions are still available, but that the unconfirmed transaction has
15+
been zapped.
1416
"""
1517
from test_framework.test_framework import BitcoinTestFramework
1618
from test_framework.util import (assert_equal,
17-
assert_raises,
18-
bitcoind_processes,
19-
connect_nodes_bi,
20-
JSONRPCException,
19+
assert_raises_jsonrpc,
2120
)
2221

2322
class ZapWalletTXesTest (BitcoinTestFramework):
2423

2524
def __init__(self):
2625
super().__init__()
2726
self.setup_clean_chain = True
28-
self.num_nodes = 3
29-
30-
def setup_network(self):
31-
super().setup_network()
32-
connect_nodes_bi(self.nodes, 0, 2)
27+
self.num_nodes = 2
3328

3429
def run_test(self):
3530
self.log.info("Mining blocks...")
3631
self.nodes[0].generate(1)
3732
self.sync_all()
38-
self.nodes[1].generate(101)
33+
self.nodes[1].generate(100)
3934
self.sync_all()
4035

41-
assert_equal(self.nodes[0].getbalance(), 50)
36+
# This transaction will be confirmed
37+
txid1 = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 10)
4238

43-
txid0 = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 11)
44-
txid1 = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 10)
45-
self.sync_all()
4639
self.nodes[0].generate(1)
4740
self.sync_all()
4841

49-
txid2 = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 11)
50-
txid3 = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 10)
51-
52-
tx0 = self.nodes[0].gettransaction(txid0)
53-
assert_equal(tx0['txid'], txid0) # tx0 must be available (confirmed)
42+
# This transaction will not be confirmed
43+
txid2 = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 20)
5444

55-
tx1 = self.nodes[0].gettransaction(txid1)
56-
assert_equal(tx1['txid'], txid1) # tx1 must be available (confirmed)
45+
# Confirmed and unconfirmed transactions are now in the wallet.
46+
assert_equal(self.nodes[0].gettransaction(txid1)['txid'], txid1)
47+
assert_equal(self.nodes[0].gettransaction(txid2)['txid'], txid2)
5748

58-
tx2 = self.nodes[0].gettransaction(txid2)
59-
assert_equal(tx2['txid'], txid2) # tx2 must be available (unconfirmed)
49+
# Stop-start node0. Both confirmed and unconfirmed transactions remain in the wallet.
50+
self.stop_node(0)
51+
self.nodes[0] = self.start_node(0, self.options.tmpdir)
6052

61-
tx3 = self.nodes[0].gettransaction(txid3)
62-
assert_equal(tx3['txid'], txid3) # tx3 must be available (unconfirmed)
53+
assert_equal(self.nodes[0].gettransaction(txid1)['txid'], txid1)
54+
assert_equal(self.nodes[0].gettransaction(txid2)['txid'], txid2)
6355

64-
#restart bitcoind
56+
# Stop node0 and restart with zapwallettxes and persistmempool. The unconfirmed
57+
# transaction is zapped from the wallet, but is re-added when the mempool is reloaded.
6558
self.stop_node(0)
66-
self.nodes[0] = self.start_node(0,self.options.tmpdir)
67-
68-
tx3 = self.nodes[0].gettransaction(txid3)
69-
assert_equal(tx3['txid'], txid3) # tx must be available (unconfirmed)
59+
self.nodes[0] = self.start_node(0, self.options.tmpdir, ["-persistmempool=1", "-zapwallettxes=2"])
7060

71-
self.stop_node(0)
72-
73-
#restart bitcoind with zapwallettxes
74-
self.nodes[0] = self.start_node(0,self.options.tmpdir, ["-zapwallettxes=1"])
61+
assert_equal(self.nodes[0].gettransaction(txid1)['txid'], txid1)
62+
assert_equal(self.nodes[0].gettransaction(txid2)['txid'], txid2)
7563

76-
assert_raises(JSONRPCException, self.nodes[0].gettransaction, [txid3])
77-
# there must be an exception because the unconfirmed wallettx0 must be gone by now
64+
# Stop node0 and restart with zapwallettxes, but not persistmempool.
65+
# The unconfirmed transaction is zapped and is no longer in the wallet.
66+
self.stop_node(0)
67+
self.nodes[0] = self.start_node(0, self.options.tmpdir, ["-zapwallettxes=2"])
7868

79-
tx0 = self.nodes[0].gettransaction(txid0)
80-
assert_equal(tx0['txid'], txid0) # tx0 (confirmed) must still be available because it was confirmed
69+
# tx1 is still be available because it was confirmed
70+
assert_equal(self.nodes[0].gettransaction(txid1)['txid'], txid1)
8171

72+
# This will raise an exception because the unconfirmed transaction has been zapped
73+
assert_raises_jsonrpc(-5, 'Invalid or non-wallet transaction id', self.nodes[0].gettransaction, txid2)
8274

8375
if __name__ == '__main__':
8476
ZapWalletTXesTest().main()

0 commit comments

Comments
 (0)