|
2 | 2 | # Copyright (c) 2017-2018 The Bitcoin Core developers
|
3 | 3 | # Distributed under the MIT software license, see the accompanying
|
4 | 4 | # file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
5 |
| -"""Test resendwallettransactions RPC.""" |
| 5 | +"""Test that the wallet resends transactions periodically.""" |
| 6 | +from collections import defaultdict |
| 7 | +import time |
6 | 8 |
|
| 9 | +from test_framework.blocktools import create_block, create_coinbase |
| 10 | +from test_framework.messages import ToHex |
| 11 | +from test_framework.mininode import P2PInterface, mininode_lock |
7 | 12 | from test_framework.test_framework import BitcoinTestFramework
|
8 |
| -from test_framework.util import assert_equal, assert_raises_rpc_error |
| 13 | +from test_framework.util import assert_equal, wait_until |
| 14 | + |
| 15 | +class P2PStoreTxInvs(P2PInterface): |
| 16 | + def __init__(self): |
| 17 | + super().__init__() |
| 18 | + self.tx_invs_received = defaultdict(int) |
| 19 | + |
| 20 | + def on_inv(self, message): |
| 21 | + # Store how many times invs have been received for each tx. |
| 22 | + for i in message.inv: |
| 23 | + if i.type == 1: |
| 24 | + # save txid |
| 25 | + self.tx_invs_received[i.hash] += 1 |
9 | 26 |
|
10 | 27 | class ResendWalletTransactionsTest(BitcoinTestFramework):
|
11 | 28 | def set_test_params(self):
|
12 | 29 | self.num_nodes = 1
|
13 |
| - self.extra_args = [['--walletbroadcast=false']] |
14 | 30 |
|
15 | 31 | def skip_test_if_missing_module(self):
|
16 | 32 | self.skip_if_no_wallet()
|
17 | 33 |
|
18 | 34 | def run_test(self):
|
19 |
| - # Should raise RPC_WALLET_ERROR (-4) if walletbroadcast is disabled. |
20 |
| - assert_raises_rpc_error(-4, "Error: Wallet transaction broadcasting is disabled with -walletbroadcast", self.nodes[0].resendwallettransactions) |
| 35 | + node = self.nodes[0] # alias |
| 36 | + |
| 37 | + node.add_p2p_connection(P2PStoreTxInvs()) |
| 38 | + |
| 39 | + self.log.info("Create a new transaction and wait until it's broadcast") |
| 40 | + txid = int(node.sendtoaddress(node.getnewaddress(), 1), 16) |
| 41 | + |
| 42 | + # Can take a few seconds due to transaction trickling |
| 43 | + wait_until(lambda: node.p2p.tx_invs_received[txid] >= 1, lock=mininode_lock) |
| 44 | + |
| 45 | + # Add a second peer since txs aren't rebroadcast to the same peer (see filterInventoryKnown) |
| 46 | + node.add_p2p_connection(P2PStoreTxInvs()) |
| 47 | + |
| 48 | + self.log.info("Create a block") |
| 49 | + # Create and submit a block without the transaction. |
| 50 | + # Transactions are only rebroadcast if there has been a block at least five minutes |
| 51 | + # after the last time we tried to broadcast. Use mocktime and give an extra minute to be sure. |
| 52 | + block_time = int(time.time()) + 6 * 60 |
| 53 | + node.setmocktime(block_time) |
| 54 | + block = create_block(int(node.getbestblockhash(), 16), create_coinbase(node.getblockchaininfo()['blocks']), block_time) |
| 55 | + block.nVersion = 3 |
| 56 | + block.rehash() |
| 57 | + block.solve() |
| 58 | + node.submitblock(ToHex(block)) |
21 | 59 |
|
22 |
| - # Should return an empty array if there aren't unconfirmed wallet transactions. |
23 |
| - self.stop_node(0) |
24 |
| - self.start_node(0, extra_args=[]) |
25 |
| - assert_equal(self.nodes[0].resendwallettransactions(), []) |
| 60 | + # Transaction should not be rebroadcast |
| 61 | + node.p2ps[1].sync_with_ping() |
| 62 | + assert_equal(node.p2ps[1].tx_invs_received[txid], 0) |
26 | 63 |
|
27 |
| - # Should return an array with the unconfirmed wallet transaction. |
28 |
| - txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 1) |
29 |
| - assert_equal(self.nodes[0].resendwallettransactions(), [txid]) |
| 64 | + self.log.info("Transaction should be rebroadcast after 30 minutes") |
| 65 | + # Use mocktime and give an extra 5 minutes to be sure. |
| 66 | + rebroadcast_time = int(time.time()) + 41 * 60 |
| 67 | + node.setmocktime(rebroadcast_time) |
| 68 | + wait_until(lambda: node.p2ps[1].tx_invs_received[txid] >= 1, lock=mininode_lock) |
30 | 69 |
|
31 | 70 | if __name__ == '__main__':
|
32 | 71 | ResendWalletTransactionsTest().main()
|
0 commit comments