Changeset View
Changeset View
Standalone View
Standalone View
test/functional/wallet_reorgsrestore.py
Show All 26 Lines | def set_test_params(self): | ||||
self.extra_args = [["-noparkdeepreorg"]] * self.num_nodes | self.extra_args = [["-noparkdeepreorg"]] * self.num_nodes | ||||
def skip_test_if_missing_module(self): | def skip_test_if_missing_module(self): | ||||
self.skip_if_no_wallet() | self.skip_if_no_wallet() | ||||
def run_test(self): | def run_test(self): | ||||
# Send a tx from which to conflict outputs later | # Send a tx from which to conflict outputs later | ||||
txid_conflict_from = self.nodes[0].sendtoaddress( | txid_conflict_from = self.nodes[0].sendtoaddress( | ||||
self.nodes[0].getnewaddress(), Decimal("10000000")) | self.nodes[0].getnewaddress(), Decimal("10000000") | ||||
) | |||||
self.generate(self.nodes[0], 1) | self.generate(self.nodes[0], 1) | ||||
# Disconnect node1 from others to reorg its chain later | # Disconnect node1 from others to reorg its chain later | ||||
self.disconnect_nodes(0, 1) | self.disconnect_nodes(0, 1) | ||||
self.disconnect_nodes(1, 2) | self.disconnect_nodes(1, 2) | ||||
self.connect_nodes(0, 2) | self.connect_nodes(0, 2) | ||||
# Send a tx to be unconfirmed later | # Send a tx to be unconfirmed later | ||||
txid = self.nodes[0].sendtoaddress( | txid = self.nodes[0].sendtoaddress( | ||||
self.nodes[0].getnewaddress(), Decimal("10000000")) | self.nodes[0].getnewaddress(), Decimal("10000000") | ||||
) | |||||
tx = self.nodes[0].gettransaction(txid) | tx = self.nodes[0].gettransaction(txid) | ||||
self.generate(self.nodes[0], 4, sync_fun=self.no_op) | self.generate(self.nodes[0], 4, sync_fun=self.no_op) | ||||
tx_before_reorg = self.nodes[0].gettransaction(txid) | tx_before_reorg = self.nodes[0].gettransaction(txid) | ||||
assert_equal(tx_before_reorg["confirmations"], 4) | assert_equal(tx_before_reorg["confirmations"], 4) | ||||
# Disconnect node0 from node2 to broadcast a conflict on their | # Disconnect node0 from node2 to broadcast a conflict on their | ||||
# respective chains | # respective chains | ||||
self.disconnect_nodes(0, 2) | self.disconnect_nodes(0, 2) | ||||
nA = next(tx_out["vout"] for tx_out in self.nodes[0].gettransaction( | nA = next( | ||||
txid_conflict_from)["details"] if tx_out["amount"] == Decimal("10000000")) | tx_out["vout"] | ||||
for tx_out in self.nodes[0].gettransaction(txid_conflict_from)["details"] | |||||
if tx_out["amount"] == Decimal("10000000") | |||||
) | |||||
inputs = [] | inputs = [] | ||||
inputs.append({"txid": txid_conflict_from, "vout": nA}) | inputs.append({"txid": txid_conflict_from, "vout": nA}) | ||||
outputs_1 = {} | outputs_1 = {} | ||||
outputs_2 = {} | outputs_2 = {} | ||||
# Create a conflicted tx broadcast on node0 chain and conflicting tx | # Create a conflicted tx broadcast on node0 chain and conflicting tx | ||||
# broadcast on node1 chain. Both spend from txid_conflict_from | # broadcast on node1 chain. Both spend from txid_conflict_from | ||||
outputs_1[self.nodes[0].getnewaddress()] = Decimal("9999980") | outputs_1[self.nodes[0].getnewaddress()] = Decimal("9999980") | ||||
outputs_2[self.nodes[0].getnewaddress()] = Decimal("9999980") | outputs_2[self.nodes[0].getnewaddress()] = Decimal("9999980") | ||||
conflicted = self.nodes[0].signrawtransactionwithwallet( | conflicted = self.nodes[0].signrawtransactionwithwallet( | ||||
self.nodes[0].createrawtransaction(inputs, outputs_1)) | self.nodes[0].createrawtransaction(inputs, outputs_1) | ||||
) | |||||
conflicting = self.nodes[0].signrawtransactionwithwallet( | conflicting = self.nodes[0].signrawtransactionwithwallet( | ||||
self.nodes[0].createrawtransaction(inputs, outputs_2)) | self.nodes[0].createrawtransaction(inputs, outputs_2) | ||||
) | |||||
conflicted_txid = self.nodes[0].sendrawtransaction(conflicted["hex"]) | conflicted_txid = self.nodes[0].sendrawtransaction(conflicted["hex"]) | ||||
self.generate(self.nodes[0], 1, sync_fun=self.no_op) | self.generate(self.nodes[0], 1, sync_fun=self.no_op) | ||||
conflicting_txid = self.nodes[2].sendrawtransaction(conflicting["hex"]) | conflicting_txid = self.nodes[2].sendrawtransaction(conflicting["hex"]) | ||||
self.generate(self.nodes[2], 9, sync_fun=self.no_op) | self.generate(self.nodes[2], 9, sync_fun=self.no_op) | ||||
# Reconnect node0 and node2 and check that conflicted_txid is | # Reconnect node0 and node2 and check that conflicted_txid is | ||||
# effectively conflicted | # effectively conflicted | ||||
Show All 11 Lines | def run_test(self): | ||||
self.generate(self.nodes[1], 9, sync_fun=self.no_op) | self.generate(self.nodes[1], 9, sync_fun=self.no_op) | ||||
self.nodes[1].sendrawtransaction(tx["hex"]) | self.nodes[1].sendrawtransaction(tx["hex"]) | ||||
self.generate(self.nodes[1], 1, sync_fun=self.no_op) | self.generate(self.nodes[1], 1, sync_fun=self.no_op) | ||||
self.nodes[1].sendrawtransaction(conflicted["hex"]) | self.nodes[1].sendrawtransaction(conflicted["hex"]) | ||||
self.generate(self.nodes[1], 1, sync_fun=self.no_op) | self.generate(self.nodes[1], 1, sync_fun=self.no_op) | ||||
# Node0 wallet file is loaded on longest sync'ed node1 | # Node0 wallet file is loaded on longest sync'ed node1 | ||||
self.stop_node(1) | self.stop_node(1) | ||||
self.nodes[0].backupwallet( | self.nodes[0].backupwallet(os.path.join(self.nodes[0].datadir, "wallet.bak")) | ||||
os.path.join( | |||||
self.nodes[0].datadir, | |||||
'wallet.bak')) | |||||
shutil.copyfile( | shutil.copyfile( | ||||
os.path.join( | os.path.join(self.nodes[0].datadir, "wallet.bak"), | ||||
self.nodes[0].datadir, | |||||
'wallet.bak'), | |||||
os.path.join( | os.path.join( | ||||
self.nodes[1].datadir, | self.nodes[1].datadir, | ||||
self.chain, | self.chain, | ||||
self.default_wallet_name, | self.default_wallet_name, | ||||
self.wallet_data_filename)) | self.wallet_data_filename, | ||||
), | |||||
) | |||||
self.start_node(1) | self.start_node(1) | ||||
tx_after_reorg = self.nodes[1].gettransaction(txid) | tx_after_reorg = self.nodes[1].gettransaction(txid) | ||||
# Check that normal confirmed tx is confirmed again but with different | # Check that normal confirmed tx is confirmed again but with different | ||||
# blockhash | # blockhash | ||||
assert_equal(tx_after_reorg["confirmations"], 2) | assert_equal(tx_after_reorg["confirmations"], 2) | ||||
assert tx_before_reorg["blockhash"] != tx_after_reorg["blockhash"] | assert tx_before_reorg["blockhash"] != tx_after_reorg["blockhash"] | ||||
conflicted_after_reorg = self.nodes[1].gettransaction(conflicted_txid) | conflicted_after_reorg = self.nodes[1].gettransaction(conflicted_txid) | ||||
# Check that conflicted tx is confirmed again with blockhash different | # Check that conflicted tx is confirmed again with blockhash different | ||||
# than previously conflicting tx | # than previously conflicting tx | ||||
assert_equal(conflicted_after_reorg["confirmations"], 1) | assert_equal(conflicted_after_reorg["confirmations"], 1) | ||||
assert conflicting["blockhash"] != conflicted_after_reorg["blockhash"] | assert conflicting["blockhash"] != conflicted_after_reorg["blockhash"] | ||||
if __name__ == '__main__': | if __name__ == "__main__": | ||||
ReorgsRestoreTest().main() | ReorgsRestoreTest().main() |