Changeset View
Changeset View
Standalone View
Standalone View
test/functional/mempool_persist.py
Show All 31 Lines | - Remove node0 mempool.dat and verify savemempool RPC recreates it | ||||
and verify that node1 can load it and has 5 transactions in its | and verify that node1 can load it and has 5 transactions in its | ||||
mempool. | mempool. | ||||
- Verify that savemempool throws when the RPC is called if | - Verify that savemempool throws when the RPC is called if | ||||
node1 can't write to disk. | node1 can't write to disk. | ||||
""" | """ | ||||
from decimal import Decimal | from decimal import Decimal | ||||
import os | import os | ||||
import time | |||||
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_equal, | ||||
assert_raises_rpc_error, | assert_raises_rpc_error, | ||||
wait_until | wait_until | ||||
) | ) | ||||
Show All 27 Lines | def run_test(self): | ||||
"transactions in its mempool and node1 does not. " | "transactions in its mempool and node1 does not. " | ||||
"Verify that node2 calculates its balance correctly " | "Verify that node2 calculates its balance correctly " | ||||
"after loading wallet transactions.") | "after loading wallet transactions.") | ||||
self.stop_nodes() | self.stop_nodes() | ||||
# Give this one a head-start, so we can be "extra-sure" that it didn't load anything later | # Give this one a head-start, so we can be "extra-sure" that it didn't load anything later | ||||
self.start_node(1) | self.start_node(1) | ||||
self.start_node(0) | self.start_node(0) | ||||
self.start_node(2) | self.start_node(2) | ||||
# Give bitcoind a second to reload the mempool | wait_until(lambda: self.nodes[0].getmempoolinfo()["loaded"], timeout=1) | ||||
wait_until(lambda: len(self.nodes[0].getrawmempool()) == 5, timeout=1) | wait_until(lambda: self.nodes[2].getmempoolinfo()["loaded"], timeout=1) | ||||
wait_until(lambda: len(self.nodes[2].getrawmempool()) == 5, timeout=1) | assert_equal(len(self.nodes[0].getrawmempool()), 5) | ||||
assert_equal(len(self.nodes[2].getrawmempool()), 5) | |||||
# The others have loaded their mempool. If node_1 loaded anything, we'd probably notice by now: | # The others have loaded their mempool. If node_1 loaded anything, we'd probably notice by now: | ||||
assert_equal(len(self.nodes[1].getrawmempool()), 0) | assert_equal(len(self.nodes[1].getrawmempool()), 0) | ||||
# Verify accounting of mempool transactions after restart is correct | # Verify accounting of mempool transactions after restart is correct | ||||
# Flush mempool to wallet | # Flush mempool to wallet | ||||
self.nodes[2].syncwithvalidationinterfacequeue() | self.nodes[2].syncwithvalidationinterfacequeue() | ||||
assert_equal(node2_balance, self.nodes[2].getbalance()) | assert_equal(node2_balance, self.nodes[2].getbalance()) | ||||
self.log.debug( | self.log.debug( | ||||
"Stop-start node0 with -persistmempool=0. Verify that it doesn't load its mempool.dat file.") | "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"]) | self.start_node(0, extra_args=["-persistmempool=0"]) | ||||
# Give bitcoind a second to reload the mempool | wait_until(lambda: self.nodes[0].getmempoolinfo()["loaded"]) | ||||
time.sleep(1) | |||||
assert_equal(len(self.nodes[0].getrawmempool()), 0) | assert_equal(len(self.nodes[0].getrawmempool()), 0) | ||||
self.log.debug( | self.log.debug( | ||||
"Stop-start node0. Verify that it has the transactions in its mempool.") | "Stop-start node0. Verify that it has the transactions in its mempool.") | ||||
self.stop_nodes() | self.stop_nodes() | ||||
self.start_node(0) | self.start_node(0) | ||||
wait_until(lambda: len(self.nodes[0].getrawmempool()) == 5) | wait_until(lambda: self.nodes[0].getmempoolinfo()["loaded"]) | ||||
assert_equal(len(self.nodes[0].getrawmempool()), 5) | |||||
mempooldat0 = os.path.join( | mempooldat0 = os.path.join( | ||||
self.nodes[0].datadir, 'regtest', 'mempool.dat') | self.nodes[0].datadir, 'regtest', 'mempool.dat') | ||||
mempooldat1 = os.path.join( | mempooldat1 = os.path.join( | ||||
self.nodes[1].datadir, 'regtest', 'mempool.dat') | self.nodes[1].datadir, 'regtest', 'mempool.dat') | ||||
self.log.debug( | self.log.debug( | ||||
"Remove the mempool.dat file. Verify that savemempool to disk via RPC re-creates it") | "Remove the mempool.dat file. Verify that savemempool to disk via RPC re-creates it") | ||||
os.remove(mempooldat0) | os.remove(mempooldat0) | ||||
self.nodes[0].savemempool() | self.nodes[0].savemempool() | ||||
assert os.path.isfile(mempooldat0) | assert os.path.isfile(mempooldat0) | ||||
self.log.debug( | self.log.debug( | ||||
"Stop nodes, make node1 use mempool.dat from node0. Verify it has 5 transactions") | "Stop nodes, make node1 use mempool.dat from node0. Verify it has 5 transactions") | ||||
os.rename(mempooldat0, mempooldat1) | os.rename(mempooldat0, mempooldat1) | ||||
self.stop_nodes() | self.stop_nodes() | ||||
self.start_node(1, extra_args=[]) | self.start_node(1, extra_args=[]) | ||||
wait_until(lambda: len(self.nodes[1].getrawmempool()) == 5) | wait_until(lambda: self.nodes[1].getmempoolinfo()["loaded"]) | ||||
assert_equal(len(self.nodes[1].getrawmempool()), 5) | |||||
self.log.debug( | self.log.debug( | ||||
"Prevent bitcoind from writing mempool.dat to disk. Verify that `savemempool` fails") | "Prevent bitcoind from writing mempool.dat to disk. Verify that `savemempool` fails") | ||||
# to test the exception we are setting bad permissions on a tmp file called mempool.dat.new | # to test the exception we are setting bad permissions on a tmp file called mempool.dat.new | ||||
# which is an implementation detail that could change and break this test | # which is an implementation detail that could change and break this test | ||||
mempooldotnew1 = mempooldat1 + '.new' | mempooldotnew1 = mempooldat1 + '.new' | ||||
with os.fdopen(os.open(mempooldotnew1, os.O_CREAT, 0o000), 'w'): | with os.fdopen(os.open(mempooldotnew1, os.O_CREAT, 0o000), 'w'): | ||||
pass | pass | ||||
assert_raises_rpc_error(-1, "Unable to dump mempool to disk", | assert_raises_rpc_error(-1, "Unable to dump mempool to disk", | ||||
self.nodes[1].savemempool) | self.nodes[1].savemempool) | ||||
os.remove(mempooldotnew1) | os.remove(mempooldotnew1) | ||||
if __name__ == '__main__': | if __name__ == '__main__': | ||||
MempoolPersistTest().main() | MempoolPersistTest().main() |