|
5 | 5 | """Test the -alertnotify, -blocknotify and -walletnotify options."""
|
6 | 6 | import os
|
7 | 7 |
|
8 |
| -from test_framework.address import ADDRESS_BCRT1_UNSPENDABLE |
| 8 | +from test_framework.address import ADDRESS_BCRT1_UNSPENDABLE, keyhash_to_p2pkh |
9 | 9 | from test_framework.test_framework import BitcoinTestFramework
|
10 | 10 | from test_framework.util import (
|
11 | 11 | assert_equal,
|
12 | 12 | wait_until,
|
13 | 13 | connect_nodes,
|
| 14 | + disconnect_nodes, |
| 15 | + hex_str_to_bytes, |
14 | 16 | )
|
15 | 17 |
|
16 | 18 | # Linux allow all characters other than \x00
|
@@ -81,8 +83,72 @@ def run_test(self):
|
81 | 83 | # directory content should equal the generated transaction hashes
|
82 | 84 | txids_rpc = list(map(lambda t: notify_outputname(self.wallet, t['txid']), self.nodes[1].listtransactions("*", block_count)))
|
83 | 85 | assert_equal(sorted(txids_rpc), sorted(os.listdir(self.walletnotify_dir)))
|
| 86 | + for tx_file in os.listdir(self.walletnotify_dir): |
| 87 | + os.remove(os.path.join(self.walletnotify_dir, tx_file)) |
| 88 | + |
| 89 | + # Conflicting transactions tests. Give node 0 same wallet seed as |
| 90 | + # node 1, generate spends from node 0, and check notifications |
| 91 | + # triggered by node 1 |
| 92 | + self.log.info("test -walletnotify with conflicting transactions") |
| 93 | + self.nodes[0].sethdseed(seed=self.nodes[1].dumpprivkey(keyhash_to_p2pkh(hex_str_to_bytes(self.nodes[1].getwalletinfo()['hdseedid'])[::-1]))) |
| 94 | + self.nodes[0].rescanblockchain() |
| 95 | + self.nodes[0].generatetoaddress(100, ADDRESS_BCRT1_UNSPENDABLE) |
| 96 | + |
| 97 | + # Generate transaction on node 0, sync mempools, and check for |
| 98 | + # notification on node 1. |
| 99 | + tx1 = self.nodes[0].sendtoaddress(address=ADDRESS_BCRT1_UNSPENDABLE, amount=1, replaceable=True) |
| 100 | + assert_equal(tx1 in self.nodes[0].getrawmempool(), True) |
| 101 | + self.sync_mempools() |
| 102 | + self.expect_wallet_notify([tx1]) |
| 103 | + |
| 104 | + # Generate bump transaction, sync mempools, and check for bump1 |
| 105 | + # notification. In the future, per |
| 106 | + # https://github.com/bitcoin/bitcoin/pull/9371, it might be better |
| 107 | + # to have notifications for both tx1 and bump1. |
| 108 | + bump1 = self.nodes[0].bumpfee(tx1)["txid"] |
| 109 | + assert_equal(bump1 in self.nodes[0].getrawmempool(), True) |
| 110 | + self.sync_mempools() |
| 111 | + self.expect_wallet_notify([bump1]) |
| 112 | + |
| 113 | + # Add bump1 transaction to new block, checking for a notification |
| 114 | + # and the correct number of confirmations. |
| 115 | + self.nodes[0].generatetoaddress(1, ADDRESS_BCRT1_UNSPENDABLE) |
| 116 | + self.sync_blocks() |
| 117 | + self.expect_wallet_notify([bump1]) |
| 118 | + assert_equal(self.nodes[1].gettransaction(bump1)["confirmations"], 1) |
| 119 | + |
| 120 | + # Generate a second transaction to be bumped. |
| 121 | + tx2 = self.nodes[0].sendtoaddress(address=ADDRESS_BCRT1_UNSPENDABLE, amount=1, replaceable=True) |
| 122 | + assert_equal(tx2 in self.nodes[0].getrawmempool(), True) |
| 123 | + self.sync_mempools() |
| 124 | + self.expect_wallet_notify([tx2]) |
| 125 | + |
| 126 | + # Bump tx2 as bump2 and generate a block on node 0 while |
| 127 | + # disconnected, then reconnect and check for notifications on node 1 |
| 128 | + # about newly confirmed bump2 and newly conflicted tx2. Currently |
| 129 | + # only the bump2 notification is sent. Ideally, notifications would |
| 130 | + # be sent both for bump2 and tx2, which was the previous behavior |
| 131 | + # before being broken by an accidental change in PR |
| 132 | + # https://github.com/bitcoin/bitcoin/pull/16624. The bug is reported |
| 133 | + # in issue https://github.com/bitcoin/bitcoin/issues/18325. |
| 134 | + disconnect_nodes(self.nodes[0], 1) |
| 135 | + bump2 = self.nodes[0].bumpfee(tx2)["txid"] |
| 136 | + self.nodes[0].generatetoaddress(1, ADDRESS_BCRT1_UNSPENDABLE) |
| 137 | + assert_equal(self.nodes[0].gettransaction(bump2)["confirmations"], 1) |
| 138 | + assert_equal(tx2 in self.nodes[1].getrawmempool(), True) |
| 139 | + connect_nodes(self.nodes[0], 1) |
| 140 | + self.sync_blocks() |
| 141 | + self.expect_wallet_notify([bump2]) |
| 142 | + assert_equal(self.nodes[1].gettransaction(bump2)["confirmations"], 1) |
84 | 143 |
|
85 | 144 | # TODO: add test for `-alertnotify` large fork notifications
|
86 | 145 |
|
| 146 | + def expect_wallet_notify(self, tx_ids): |
| 147 | + wait_until(lambda: len(os.listdir(self.walletnotify_dir)) >= len(tx_ids), timeout=10) |
| 148 | + assert_equal(sorted(notify_outputname(self.wallet, tx_id) for tx_id in tx_ids), sorted(os.listdir(self.walletnotify_dir))) |
| 149 | + for tx_file in os.listdir(self.walletnotify_dir): |
| 150 | + os.remove(os.path.join(self.walletnotify_dir, tx_file)) |
| 151 | + |
| 152 | + |
87 | 153 | if __name__ == '__main__':
|
88 | 154 | NotificationsTest().main()
|
0 commit comments