Changeset View
Changeset View
Standalone View
Standalone View
qa/rpc-tests/abandonconflict.py
Show All 13 Lines | class AbandonConflictTest(BitcoinTestFramework): | ||||
def __init__(self): | def __init__(self): | ||||
super().__init__() | super().__init__() | ||||
self.num_nodes = 2 | self.num_nodes = 2 | ||||
self.setup_clean_chain = False | self.setup_clean_chain = False | ||||
def setup_network(self): | def setup_network(self): | ||||
self.nodes = [] | self.nodes = [] | ||||
self.nodes.append( | self.nodes.append( | ||||
start_node(0, self.options.tmpdir, ["-debug", | start_node(0, self.options.tmpdir, | ||||
"-logtimemicros", | ["-logtimemicros", "-minrelaytxfee=0.00001"])) | ||||
"-minrelaytxfee=0.00001"])) | |||||
self.nodes.append( | self.nodes.append( | ||||
start_node(1, self.options.tmpdir, ["-debug", | start_node(1, self.options.tmpdir, ["-logtimemicros"])) | ||||
"-logtimemicros"])) | |||||
connect_nodes(self.nodes[0], 1) | connect_nodes(self.nodes[0], 1) | ||||
def run_test(self): | def run_test(self): | ||||
self.nodes[1].generate(100) | self.nodes[1].generate(100) | ||||
sync_blocks(self.nodes) | sync_blocks(self.nodes) | ||||
balance = self.nodes[0].getbalance() | balance = self.nodes[0].getbalance() | ||||
txA = self.nodes[0].sendtoaddress( | txA = self.nodes[0].sendtoaddress( | ||||
self.nodes[0].getnewaddress(), Decimal("10")) | self.nodes[0].getnewaddress(), Decimal("10")) | ||||
▲ Show 20 Lines • Show All 52 Lines • ▼ Show 20 Lines | def run_test(self): | ||||
assert_equal(newbalance, balance - Decimal("30") + Decimal("24.9996")) | assert_equal(newbalance, balance - Decimal("30") + Decimal("24.9996")) | ||||
balance = newbalance | balance = newbalance | ||||
# Restart the node with a higher min relay fee so the parent tx is no longer in mempool | # Restart the node with a higher min relay fee so the parent tx is no longer in mempool | ||||
# TODO: redo with eviction | # TODO: redo with eviction | ||||
# Note had to make sure tx did not have AllowFree priority | # Note had to make sure tx did not have AllowFree priority | ||||
stop_node(self.nodes[0], 0) | stop_node(self.nodes[0], 0) | ||||
self.nodes[0] = start_node(0, self.options.tmpdir, [ | self.nodes[0] = start_node(0, self.options.tmpdir, [ | ||||
"-debug", "-logtimemicros", | "-logtimemicros", | ||||
"-minrelaytxfee=0.0001"]) | "-minrelaytxfee=0.0001"]) | ||||
# Verify txs no longer in mempool | # Verify txs no longer in mempool | ||||
assert_equal(len(self.nodes[0].getrawmempool()), 0) | assert_equal(len(self.nodes[0].getrawmempool()), 0) | ||||
# Not in mempool txs from self should only reduce balance | # Not in mempool txs from self should only reduce balance | ||||
# inputs are still spent, but change not received | # inputs are still spent, but change not received | ||||
newbalance = self.nodes[0].getbalance() | newbalance = self.nodes[0].getbalance() | ||||
Show All 14 Lines | def run_test(self): | ||||
newbalance = self.nodes[0].getbalance() | newbalance = self.nodes[0].getbalance() | ||||
assert_equal(newbalance, balance + Decimal("30")) | assert_equal(newbalance, balance + Decimal("30")) | ||||
balance = newbalance | balance = newbalance | ||||
# Verify that even with a low min relay fee, the tx is not reaccepted | # Verify that even with a low min relay fee, the tx is not reaccepted | ||||
# from wallet on startup once abandoned | # from wallet on startup once abandoned | ||||
stop_node(self.nodes[0], 0) | stop_node(self.nodes[0], 0) | ||||
self.nodes[0] = start_node(0, self.options.tmpdir, [ | self.nodes[0] = start_node(0, self.options.tmpdir, [ | ||||
"-debug", "-logtimemicros", | "-logtimemicros", | ||||
"-minrelaytxfee=0.00001"]) | "-minrelaytxfee=0.00001"]) | ||||
assert_equal(len(self.nodes[0].getrawmempool()), 0) | assert_equal(len(self.nodes[0].getrawmempool()), 0) | ||||
assert_equal(self.nodes[0].getbalance(), balance) | assert_equal(self.nodes[0].getbalance(), balance) | ||||
# But if its received again then it is unabandoned | # But if its received again then it is unabandoned | ||||
# And since now in mempool, the change is available | # And since now in mempool, the change is available | ||||
# But its child tx remains abandoned | # But its child tx remains abandoned | ||||
self.nodes[0].sendrawtransaction(signed["hex"]) | self.nodes[0].sendrawtransaction(signed["hex"]) | ||||
newbalance = self.nodes[0].getbalance() | newbalance = self.nodes[0].getbalance() | ||||
assert_equal(newbalance, balance - Decimal("20") + Decimal("14.99998")) | assert_equal(newbalance, balance - Decimal("20") + Decimal("14.99998")) | ||||
balance = newbalance | balance = newbalance | ||||
# Send child tx again so its unabandoned | # Send child tx again so its unabandoned | ||||
self.nodes[0].sendrawtransaction(signed2["hex"]) | self.nodes[0].sendrawtransaction(signed2["hex"]) | ||||
newbalance = self.nodes[0].getbalance() | newbalance = self.nodes[0].getbalance() | ||||
assert_equal(newbalance, balance - Decimal("10") | assert_equal(newbalance, balance - Decimal("10") | ||||
- Decimal("14.99998") + Decimal("24.9996")) | - Decimal("14.99998") + Decimal("24.9996")) | ||||
balance = newbalance | balance = newbalance | ||||
# Remove using high relay fee again | # Remove using high relay fee again | ||||
stop_node(self.nodes[0], 0) | stop_node(self.nodes[0], 0) | ||||
self.nodes[0] = start_node(0, self.options.tmpdir, [ | self.nodes[0] = start_node(0, self.options.tmpdir, [ | ||||
"-debug", "-logtimemicros", | "-logtimemicros", | ||||
"-minrelaytxfee=0.0001"]) | "-minrelaytxfee=0.0001"]) | ||||
assert_equal(len(self.nodes[0].getrawmempool()), 0) | assert_equal(len(self.nodes[0].getrawmempool()), 0) | ||||
newbalance = self.nodes[0].getbalance() | newbalance = self.nodes[0].getbalance() | ||||
assert_equal(newbalance, balance - Decimal("24.9996")) | assert_equal(newbalance, balance - Decimal("24.9996")) | ||||
balance = newbalance | balance = newbalance | ||||
# Create a double spend of AB1 by spending again from only A's 10 output | # Create a double spend of AB1 by spending again from only A's 10 output | ||||
# Mine double spend from node 1 | # Mine double spend from node 1 | ||||
Show All 16 Lines | def run_test(self): | ||||
balance = newbalance | balance = newbalance | ||||
# There is currently a minor bug around this and so this test doesn't work. See Issue #7315 | # There is currently a minor bug around this and so this test doesn't work. See Issue #7315 | ||||
# Invalidate the block with the double spend and B's 10 BTC output should no longer be available | # Invalidate the block with the double spend and B's 10 BTC output should no longer be available | ||||
# Don't think C's should either | # Don't think C's should either | ||||
self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash()) | self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash()) | ||||
newbalance = self.nodes[0].getbalance() | newbalance = self.nodes[0].getbalance() | ||||
# assert_equal(newbalance, balance - Decimal("10")) | # assert_equal(newbalance, balance - Decimal("10")) | ||||
print( | self.log.info( | ||||
"If balance has not declined after invalidateblock then out of mempool wallet tx which is no longer") | "If balance has not declined after invalidateblock then out of mempool wallet tx which is no longer") | ||||
print( | self.log.info( | ||||
"conflicted has not resumed causing its inputs to be seen as spent. See Issue #7315") | "conflicted has not resumed causing its inputs to be seen as spent. See Issue #7315") | ||||
print(str(balance) + " -> " + str(newbalance) + " ?") | self.log.info(str(balance) + " -> " + str(newbalance) + " ?") | ||||
if __name__ == '__main__': | if __name__ == '__main__': | ||||
AbandonConflictTest().main() | AbandonConflictTest().main() |