merge bitcoin#23047: Use MiniWallet in mempool_persist

This commit is contained in:
Kittywhiskers Van Gogh 2021-09-20 15:22:15 +02:00
parent 234f22a72e
commit 4db9108b74
No known key found for this signature in database
GPG Key ID: 30CD0C065E5C4AAD
2 changed files with 42 additions and 25 deletions

View File

@ -44,6 +44,7 @@ from test_framework.util import (
assert_equal, assert_equal,
assert_greater_than_or_equal, assert_raises_rpc_error, assert_greater_than_or_equal, assert_raises_rpc_error,
) )
from test_framework.wallet import MiniWallet
class MempoolPersistTest(BitcoinTestFramework): class MempoolPersistTest(BitcoinTestFramework):
@ -51,15 +52,26 @@ class MempoolPersistTest(BitcoinTestFramework):
self.num_nodes = 3 self.num_nodes = 3
self.extra_args = [[], ["-persistmempool=0"], []] self.extra_args = [[], ["-persistmempool=0"], []]
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
def run_test(self): def run_test(self):
self.mini_wallet = MiniWallet(self.nodes[2])
self.mini_wallet.rescan_utxos()
if self.is_sqlite_compiled():
self.nodes[2].createwallet(
wallet_name="watch",
descriptors=True,
disable_private_keys=True,
load_on_startup=False,
)
wallet_watch = self.nodes[2].get_wallet_rpc("watch")
assert_equal([{'success': True}], wallet_watch.importdescriptors([{'desc': self.mini_wallet.get_descriptor(), 'timestamp': 0}]))
self.log.debug("Send 5 transactions from node2 (to its own address)") self.log.debug("Send 5 transactions from node2 (to its own address)")
tx_creation_time_lower = self.mocktime tx_creation_time_lower = self.mocktime
for _ in range(5): for _ in range(5):
last_txid = self.nodes[2].sendtoaddress(self.nodes[2].getnewaddress(), Decimal("10")) last_txid = self.mini_wallet.send_self_transfer(from_node=self.nodes[2])["txid"]
node2_balance = self.nodes[2].getbalance() if self.is_sqlite_compiled():
self.nodes[2].syncwithvalidationinterfacequeue() # Flush mempool to wallet
node2_balance = wallet_watch.getbalance()
self.sync_all() self.sync_all()
tx_creation_time_higher = self.mocktime tx_creation_time_higher = self.mocktime
@ -80,16 +92,16 @@ class MempoolPersistTest(BitcoinTestFramework):
assert_equal(total_fee_old, self.nodes[0].getmempoolinfo()['total_fee']) assert_equal(total_fee_old, self.nodes[0].getmempoolinfo()['total_fee'])
assert_equal(total_fee_old, sum(v['fees']['base'] for k, v in self.nodes[0].getrawmempool(verbose=True).items())) assert_equal(total_fee_old, sum(v['fees']['base'] for k, v in self.nodes[0].getrawmempool(verbose=True).items()))
tx_creation_time = self.nodes[0].getmempoolentry(txid=last_txid)['time'] last_entry = self.nodes[0].getmempoolentry(txid=last_txid)
tx_creation_time = last_entry['time']
assert_greater_than_or_equal(tx_creation_time, tx_creation_time_lower) assert_greater_than_or_equal(tx_creation_time, tx_creation_time_lower)
assert_greater_than_or_equal(tx_creation_time_higher, tx_creation_time) assert_greater_than_or_equal(tx_creation_time_higher, tx_creation_time)
# disconnect nodes & make a txn that remains in the unbroadcast set. # disconnect nodes & make a txn that remains in the unbroadcast set.
self.disconnect_nodes(0, 1) self.disconnect_nodes(0, 1)
assert(len(self.nodes[0].getpeerinfo()) == 0) assert_equal(len(self.nodes[0].getpeerinfo()), 0)
assert(len(self.nodes[0].p2ps) == 0) assert_equal(len(self.nodes[0].p2ps), 0)
self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), Decimal("12")) self.mini_wallet.send_self_transfer(from_node=self.nodes[0])
self.connect_nodes(0, 2)
self.log.debug("Stop-start the nodes. Verify that node0 has the transactions in its mempool and node1 does not. Verify that node2 calculates its balance correctly after loading wallet transactions.") self.log.debug("Stop-start the nodes. Verify that node0 has the transactions in its mempool and node1 does not. Verify that node2 calculates its balance correctly after loading wallet transactions.")
self.stop_nodes() self.stop_nodes()
@ -109,17 +121,19 @@ class MempoolPersistTest(BitcoinTestFramework):
fees = self.nodes[0].getmempoolentry(txid=last_txid)['fees'] fees = self.nodes[0].getmempoolentry(txid=last_txid)['fees']
assert_equal(fees['base'] + Decimal('0.00001000'), fees['modified']) assert_equal(fees['base'] + Decimal('0.00001000'), fees['modified'])
self.log.debug('Verify time is loaded correctly') self.log.debug('Verify all fields are loaded correctly')
assert_equal(tx_creation_time, self.nodes[0].getmempoolentry(txid=last_txid)['time']) assert_equal(last_entry, self.nodes[0].getmempoolentry(txid=last_txid))
# Verify accounting of mempool transactions after restart is correct # Verify accounting of mempool transactions after restart is correct
if self.is_sqlite_compiled():
self.nodes[2].loadwallet("watch")
wallet_watch = self.nodes[2].get_wallet_rpc("watch")
self.nodes[2].syncwithvalidationinterfacequeue() # Flush mempool to wallet self.nodes[2].syncwithvalidationinterfacequeue() # Flush mempool to wallet
assert_equal(node2_balance, self.nodes[2].getbalance()) assert_equal(node2_balance, wallet_watch.getbalance())
# start node0 with wallet disabled so wallet transactions don't get resubmitted
self.log.debug("Stop-start node0 with -persistmempool=0. Verify that it doesn't load its mempool.dat file.") self.log.debug("Stop-start node0 with -persistmempool=0. Verify that it doesn't load its mempool.dat file.")
self.stop_nodes() self.stop_nodes()
self.start_node(0, extra_args=["-persistmempool=0", "-disablewallet"]) self.start_node(0, extra_args=["-persistmempool=0"])
assert self.nodes[0].getmempoolinfo()["loaded"] assert self.nodes[0].getmempoolinfo()["loaded"]
assert_equal(len(self.nodes[0].getrawmempool()), 0) assert_equal(len(self.nodes[0].getrawmempool()), 0)
@ -163,18 +177,18 @@ class MempoolPersistTest(BitcoinTestFramework):
# ensure node0 doesn't have any connections # ensure node0 doesn't have any connections
# make a transaction that will remain in the unbroadcast set # make a transaction that will remain in the unbroadcast set
assert(len(node0.getpeerinfo()) == 0) assert_equal(len(node0.getpeerinfo()), 0)
assert(len(node0.p2ps) == 0) assert_equal(len(node0.p2ps), 0)
node0.sendtoaddress(self.nodes[1].getnewaddress(), Decimal("12")) self.mini_wallet.send_self_transfer(from_node=node0)
# shutdown, then startup with wallet disabled # shutdown, then startup with wallet disabled
self.stop_nodes() self.restart_node(0, extra_args=["-disablewallet"])
self.start_node(0, extra_args=["-disablewallet"])
# check that txn gets broadcast due to unbroadcast logic # check that txn gets broadcast due to unbroadcast logic
# conn = node0.add_p2p_connection(P2PTxInvStore()) # conn = node0.add_p2p_connection(P2PTxInvStore())
# node0.mockscheduler(16 * 60) # 15 min + 1 for buffer # node0.mockscheduler(16 * 60) # 15 min + 1 for buffer
# self.wait_until(lambda: len(conn.get_invs()) == 1) # self.wait_until(lambda: len(conn.get_invs()) == 1)
if __name__ == '__main__':
if __name__ == "__main__":
MempoolPersistTest().main() MempoolPersistTest().main()

View File

@ -81,7 +81,7 @@ class MiniWallet:
def rescan_utxos(self): def rescan_utxos(self):
"""Drop all utxos and rescan the utxo set""" """Drop all utxos and rescan the utxo set"""
self._utxos = [] self._utxos = []
res = self._test_node.scantxoutset(action="start", scanobjects=[f'raw({self._scriptPubKey.hex()})']) res = self._test_node.scantxoutset(action="start", scanobjects=[self.get_descriptor()])
assert_equal(True, res['success']) assert_equal(True, res['success'])
for utxo in res['unspents']: for utxo in res['unspents']:
self._utxos.append({'txid': utxo['txid'], 'vout': utxo['vout'], 'value': utxo['amount'], 'height': utxo['height']}) self._utxos.append({'txid': utxo['txid'], 'vout': utxo['vout'], 'value': utxo['amount'], 'height': utxo['height']})
@ -116,13 +116,16 @@ class MiniWallet:
def generate(self, num_blocks): def generate(self, num_blocks):
"""Generate blocks with coinbase outputs to the internal address, and append the outputs to the internal list""" """Generate blocks with coinbase outputs to the internal address, and append the outputs to the internal list"""
blocks = self._test_node.generatetodescriptor(num_blocks, f'raw({self._scriptPubKey.hex()})') blocks = self._test_node.generatetodescriptor(num_blocks, self.get_descriptor())
for b in blocks: for b in blocks:
block_info = self._test_node.getblock(blockhash=b, verbosity=2) block_info = self._test_node.getblock(blockhash=b, verbosity=2)
cb_tx = block_info['tx'][0] cb_tx = block_info['tx'][0]
self._utxos.append({'txid': cb_tx['txid'], 'vout': 0, 'value': cb_tx['vout'][0]['value'], 'height': block_info['height']}) self._utxos.append({'txid': cb_tx['txid'], 'vout': 0, 'value': cb_tx['vout'][0]['value'], 'height': block_info['height']})
return blocks return blocks
def get_descriptor(self):
return self._test_node.getdescriptorinfo(f'raw({self._scriptPubKey.hex()})')['descriptor']
def get_address(self): def get_address(self):
return self._address return self._address