Merge #10330: [wallet] fix zapwallettxes interaction with persistent mempool
4c3b538
[logs] fix zapwallettxes startup logs (John Newbery)e7a2181
[wallet] fix zapwallettxes interaction with persistent mempool (John Newbery)ff7365e
[tests] fix flake8 warnings in zapwallettxes.py (John Newbery) Pull request description: 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. This PR also fixes the zapwallettxes.py functional test, which did not properly test this feature. The test line: ```py assert_raises(JSONRPCException, self.nodes[0].gettransaction, [txid3]) #there must be a expection because the unconfirmed wallettx0 must be gone by now ``` is not actually testing the presence of the transaction since the RPC is being called incorrectly (with an array instead of a string). The `assert_raises()` passes since an assert is raised, but it's not the one the test writer had in mind! Fixes #9710 . Tree-SHA512: e3236efc7a2fd2b3bf1d9e2e8a7726d470c57f5d95cf41b7bde264edc8817bd36a6f3feff52f8de8db0ef64b7247c88b24e7ff7cefaa706cba86fe4e2135a508
This commit is contained in:
commit
bf0a08be28
2 changed files with 59 additions and 57 deletions
|
@ -4048,13 +4048,19 @@ bool CWallet::ParameterInteraction()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// -zapwallettx implies a rescan
|
int zapwallettxes = GetArg("-zapwallettxes", 0);
|
||||||
if (GetBoolArg("-zapwallettxes", false)) {
|
// -zapwallettxes implies dropping the mempool on startup
|
||||||
|
if (zapwallettxes != 0 && SoftSetBoolArg("-persistmempool", false)) {
|
||||||
|
LogPrintf("%s: parameter interaction: -zapwallettxes=%s -> setting -persistmempool=0\n", __func__, zapwallettxes);
|
||||||
|
}
|
||||||
|
|
||||||
|
// -zapwallettxes implies a rescan
|
||||||
|
if (zapwallettxes != 0) {
|
||||||
if (is_multiwallet) {
|
if (is_multiwallet) {
|
||||||
return InitError(strprintf("%s is only allowed with a single wallet file", "-zapwallettxes"));
|
return InitError(strprintf("%s is only allowed with a single wallet file", "-zapwallettxes"));
|
||||||
}
|
}
|
||||||
if (SoftSetBoolArg("-rescan", true)) {
|
if (SoftSetBoolArg("-rescan", true)) {
|
||||||
LogPrintf("%s: parameter interaction: -zapwallettxes=<mode> -> setting -rescan=1\n", __func__);
|
LogPrintf("%s: parameter interaction: -zapwallettxes=%s -> setting -rescan=1\n", __func__, zapwallettxes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,77 +4,73 @@
|
||||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
"""Test the zapwallettxes functionality.
|
"""Test the zapwallettxes functionality.
|
||||||
|
|
||||||
- start three bitcoind nodes
|
- start two bitcoind nodes
|
||||||
- create four transactions on node 0 - two are confirmed and two are
|
- create two transactions on node 0 - one is confirmed and one is unconfirmed.
|
||||||
unconfirmed.
|
- restart node 0 and verify that both the confirmed and the unconfirmed
|
||||||
- restart node 1 and verify that both the confirmed and the unconfirmed
|
|
||||||
transactions are still available.
|
transactions are still available.
|
||||||
- restart node 0 and verify that the confirmed transactions are still
|
- restart node 0 with zapwallettxes and persistmempool, and verify that both
|
||||||
available, but that the unconfirmed transaction has been zapped.
|
the confirmed and the unconfirmed transactions are still available.
|
||||||
|
- restart node 0 with just zapwallettxed 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.test_framework import BitcoinTestFramework
|
||||||
from test_framework.util import *
|
from test_framework.util import (assert_equal,
|
||||||
|
assert_raises_jsonrpc,
|
||||||
|
)
|
||||||
|
|
||||||
class ZapWalletTXesTest (BitcoinTestFramework):
|
class ZapWalletTXesTest (BitcoinTestFramework):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.setup_clean_chain = True
|
self.setup_clean_chain = True
|
||||||
self.num_nodes = 3
|
self.num_nodes = 2
|
||||||
|
|
||||||
def setup_network(self):
|
def run_test(self):
|
||||||
super().setup_network()
|
|
||||||
connect_nodes_bi(self.nodes,0,2)
|
|
||||||
|
|
||||||
def run_test (self):
|
|
||||||
self.log.info("Mining blocks...")
|
self.log.info("Mining blocks...")
|
||||||
self.nodes[0].generate(1)
|
self.nodes[0].generate(1)
|
||||||
self.sync_all()
|
self.sync_all()
|
||||||
self.nodes[1].generate(101)
|
self.nodes[1].generate(100)
|
||||||
self.sync_all()
|
|
||||||
|
|
||||||
assert_equal(self.nodes[0].getbalance(), 50)
|
|
||||||
|
|
||||||
txid0 = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 11)
|
|
||||||
txid1 = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 10)
|
|
||||||
self.sync_all()
|
self.sync_all()
|
||||||
|
|
||||||
|
# This transaction will be confirmed
|
||||||
|
txid1 = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 10)
|
||||||
|
|
||||||
self.nodes[0].generate(1)
|
self.nodes[0].generate(1)
|
||||||
self.sync_all()
|
self.sync_all()
|
||||||
|
|
||||||
txid2 = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 11)
|
|
||||||
txid3 = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 10)
|
|
||||||
|
|
||||||
tx0 = self.nodes[0].gettransaction(txid0)
|
|
||||||
assert_equal(tx0['txid'], txid0) #tx0 must be available (confirmed)
|
|
||||||
|
|
||||||
tx1 = self.nodes[0].gettransaction(txid1)
|
|
||||||
assert_equal(tx1['txid'], txid1) #tx1 must be available (confirmed)
|
|
||||||
|
|
||||||
tx2 = self.nodes[0].gettransaction(txid2)
|
|
||||||
assert_equal(tx2['txid'], txid2) #tx2 must be available (unconfirmed)
|
|
||||||
|
|
||||||
tx3 = self.nodes[0].gettransaction(txid3)
|
|
||||||
assert_equal(tx3['txid'], txid3) #tx3 must be available (unconfirmed)
|
|
||||||
|
|
||||||
#restart bitcoind
|
|
||||||
self.stop_node(0)
|
|
||||||
self.nodes[0] = self.start_node(0,self.options.tmpdir)
|
|
||||||
|
|
||||||
tx3 = self.nodes[0].gettransaction(txid3)
|
|
||||||
assert_equal(tx3['txid'], txid3) #tx must be available (unconfirmed)
|
|
||||||
|
|
||||||
self.stop_node(0)
|
|
||||||
|
|
||||||
#restart bitcoind with zapwallettxes
|
|
||||||
self.nodes[0] = self.start_node(0,self.options.tmpdir, ["-zapwallettxes=1"])
|
|
||||||
|
|
||||||
assert_raises(JSONRPCException, self.nodes[0].gettransaction, [txid3])
|
|
||||||
#there must be an exception because the unconfirmed wallettx0 must be gone by now
|
|
||||||
|
|
||||||
tx0 = self.nodes[0].gettransaction(txid0)
|
# This transaction will not be confirmed
|
||||||
assert_equal(tx0['txid'], txid0) #tx0 (confirmed) must still be available because it was 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)
|
||||||
|
|
||||||
|
# Stop-start node0. Both confirmed and unconfirmed transactions remain in the wallet.
|
||||||
|
self.stop_node(0)
|
||||||
|
self.nodes[0] = self.start_node(0, self.options.tmpdir)
|
||||||
|
|
||||||
|
assert_equal(self.nodes[0].gettransaction(txid1)['txid'], txid1)
|
||||||
|
assert_equal(self.nodes[0].gettransaction(txid2)['txid'], txid2)
|
||||||
|
|
||||||
|
# Stop node0 and restart with zapwallettxes and persistmempool. The unconfirmed
|
||||||
|
# transaction is zapped from the wallet, but is re-added when the mempool is reloaded.
|
||||||
|
self.stop_node(0)
|
||||||
|
self.nodes[0] = self.start_node(0, self.options.tmpdir, ["-persistmempool=1", "-zapwallettxes=2"])
|
||||||
|
|
||||||
|
assert_equal(self.nodes[0].gettransaction(txid1)['txid'], txid1)
|
||||||
|
assert_equal(self.nodes[0].gettransaction(txid2)['txid'], txid2)
|
||||||
|
|
||||||
|
# Stop node0 and restart with zapwallettxes, but not persistmempool.
|
||||||
|
# The unconfirmed transaction is zapped and is no longer in the wallet.
|
||||||
|
self.stop_node(0)
|
||||||
|
self.nodes[0] = self.start_node(0, self.options.tmpdir, ["-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_jsonrpc(-5, 'Invalid or non-wallet transaction id', self.nodes[0].gettransaction, txid2)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
ZapWalletTXesTest ().main ()
|
ZapWalletTXesTest().main()
|
||||||
|
|
Loading…
Reference in a new issue