|
| 1 | +#!/usr/bin/env python3 |
| 2 | +# Copyright (c) 2021 The Bitcoin Core developers |
| 3 | +# Distributed under the MIT software license, see the accompanying |
| 4 | +# file COPYING or http://www.opensource.org/licenses/mit-license.php. |
| 5 | +"""Test the scanblocks RPC call.""" |
| 6 | +from test_framework.test_framework import BitcoinTestFramework |
| 7 | +from test_framework.util import assert_equal, assert_raises_rpc_error |
| 8 | + |
| 9 | + |
| 10 | +class ScanblocksTest(BitcoinTestFramework): |
| 11 | + def set_test_params(self): |
| 12 | + self.num_nodes = 2 |
| 13 | + self.extra_args = [["-blockfilterindex=1"], []] |
| 14 | + |
| 15 | + def skip_test_if_missing_module(self): |
| 16 | + self.skip_if_no_wallet() |
| 17 | + |
| 18 | + def run_test(self): |
| 19 | + node = self.nodes[0] |
| 20 | + # send 1.0, mempool only |
| 21 | + addr_1 = node.getnewaddress() |
| 22 | + node.sendtoaddress(addr_1, 1.0) |
| 23 | + |
| 24 | + parent_key = "tpubD6NzVbkrYhZ4WaWSyoBvQwbpLkojyoTZPRsgXELWz3Popb3qkjcJyJUGLnL4qHHoQvao8ESaAstxYSnhyswJ76uZPStJRJCTKvosUCJZL5B" |
| 25 | + # send 1.0, mempool only |
| 26 | + # childkey 5 of `parent_key` |
| 27 | + node.sendtoaddress("mkS4HXoTYWRTescLGaUTGbtTTYX5EjJyEE", 1.0) |
| 28 | + |
| 29 | + # mine a block and assure that the mined blockhash is in the filterresult |
| 30 | + blockhash = self.generate(node, 1)[0] |
| 31 | + height = node.getblockheader(blockhash)['height'] |
| 32 | + self.wait_until(lambda: all(i["synced"] for i in node.getindexinfo().values())) |
| 33 | + |
| 34 | + out = node.scanblocks("start", [f"addr({addr_1})"]) |
| 35 | + assert(blockhash in out['relevant_blocks']) |
| 36 | + assert_equal(height, out['to_height']) |
| 37 | + assert_equal(0, out['from_height']) |
| 38 | + |
| 39 | + # mine another block |
| 40 | + blockhash_new = self.generate(node, 1)[0] |
| 41 | + height_new = node.getblockheader(blockhash_new)['height'] |
| 42 | + |
| 43 | + # make sure the blockhash is not in the filter result if we set the start_height |
| 44 | + # to the just mined block (unlikely to hit a false positive) |
| 45 | + assert(blockhash not in node.scanblocks( |
| 46 | + "start", [f"addr({addr_1})"], height_new)['relevant_blocks']) |
| 47 | + |
| 48 | + # make sure the blockhash is present when using the first mined block as start_height |
| 49 | + assert(blockhash in node.scanblocks( |
| 50 | + "start", [f"addr({addr_1})"], height)['relevant_blocks']) |
| 51 | + |
| 52 | + # also test the stop height |
| 53 | + assert(blockhash in node.scanblocks( |
| 54 | + "start", [f"addr({addr_1})"], height, height)['relevant_blocks']) |
| 55 | + |
| 56 | + # use the stop_height to exclude the relevant block |
| 57 | + assert(blockhash not in node.scanblocks( |
| 58 | + "start", [f"addr({addr_1})"], 0, height - 1)['relevant_blocks']) |
| 59 | + |
| 60 | + # make sure the blockhash is present when using the first mined block as start_height |
| 61 | + assert(blockhash in node.scanblocks( |
| 62 | + "start", [{"desc": f"pkh({parent_key}/*)", "range": [0, 100]}], height)['relevant_blocks']) |
| 63 | + |
| 64 | + # test node with disabled blockfilterindex |
| 65 | + assert_raises_rpc_error(-1, "Index is not enabled for filtertype basic", |
| 66 | + self.nodes[1].scanblocks, "start", [f"addr({addr_1})"]) |
| 67 | + |
| 68 | + # test unknown filtertype |
| 69 | + assert_raises_rpc_error(-5, "Unknown filtertype", |
| 70 | + node.scanblocks, "start", [f"addr({addr_1})"], 0, 10, "extended") |
| 71 | + |
| 72 | + # test invalid start_height |
| 73 | + assert_raises_rpc_error(-1, "Invalid start_height", |
| 74 | + node.scanblocks, "start", [f"addr({addr_1})"], 100000000) |
| 75 | + |
| 76 | + # test invalid stop_height |
| 77 | + assert_raises_rpc_error(-1, "Invalid stop_height", |
| 78 | + node.scanblocks, "start", [f"addr({addr_1})"], 10, 0) |
| 79 | + assert_raises_rpc_error(-1, "Invalid stop_height", |
| 80 | + node.scanblocks, "start", [f"addr({addr_1})"], 10, 100000000) |
| 81 | + |
| 82 | + # test accessing the status (must be empty) |
| 83 | + assert_equal(node.scanblocks("status"), None) |
| 84 | + |
| 85 | + # test aborting the current scan (there is no, must return false) |
| 86 | + assert_equal(node.scanblocks("abort"), False) |
| 87 | + |
| 88 | + # test invalid command |
| 89 | + assert_raises_rpc_error(-8, "Invalid command", node.scanblocks, "foobar") |
| 90 | + |
| 91 | + |
| 92 | +if __name__ == '__main__': |
| 93 | + ScanblocksTest().main() |
0 commit comments