|
40 | 40 | assert_equal,
|
41 | 41 | assert_raises_rpc_error,
|
42 | 42 | )
|
43 |
| - |
| 43 | +import struct |
44 | 44 |
|
45 | 45 | START_HEIGHT = 199
|
46 | 46 | SNAPSHOT_BASE_HEIGHT = 299
|
@@ -68,23 +68,35 @@ def setup_network(self):
|
68 | 68 |
|
69 | 69 | def test_invalid_snapshot_scenarios(self, valid_snapshot_path):
|
70 | 70 | self.log.info("Test different scenarios of loading invalid snapshot files")
|
71 |
| - self.log.info(" - snapshot file refering to a block that is not in the assumeutxo parameters") |
72 | 71 | with open(valid_snapshot_path, 'rb') as f:
|
73 | 72 | valid_snapshot_contents = f.read()
|
| 73 | + bad_snapshot_path = valid_snapshot_path + '.mod' |
74 | 74 |
|
| 75 | + self.log.info(" - snapshot file refering to a block that is not in the assumeutxo parameters") |
75 | 76 | # we can only test this with a block that is already known, as otherwise the `loadtxoutset` RPC
|
76 | 77 | # would time out (waiting to see the hash in the headers chain), rather than error immediately
|
77 | 78 | bad_snapshot_height = SNAPSHOT_BASE_HEIGHT - 1
|
78 |
| - bad_snapshot_path = valid_snapshot_path + '.mod' |
79 | 79 | with open(bad_snapshot_path, 'wb') as f:
|
80 | 80 | bad_snapshot_block_hash = self.nodes[0].getblockhash(bad_snapshot_height)
|
81 | 81 | # block hash of the snapshot base is stored right at the start (first 32 bytes)
|
82 | 82 | f.write(bytes.fromhex(bad_snapshot_block_hash)[::-1] + valid_snapshot_contents[32:])
|
83 | 83 |
|
84 | 84 | expected_log = f"assumeutxo height in snapshot metadata not recognized ({bad_snapshot_height}) - refusing to load snapshot"
|
85 |
| - with self.nodes[1].assert_debug_log(expected_log): |
| 85 | + with self.nodes[1].assert_debug_log([expected_log]): |
86 | 86 | assert_raises_rpc_error(-32603, "Unable to load UTXO snapshot", self.nodes[1].loadtxoutset, bad_snapshot_path)
|
87 | 87 |
|
| 88 | + self.log.info(" - snapshot file with wrong number of coins") |
| 89 | + valid_num_coins = struct.unpack("<I", valid_snapshot_contents[32:32 + 4])[0] |
| 90 | + for off in [-1, +1]: |
| 91 | + with open(bad_snapshot_path, 'wb') as f: |
| 92 | + f.write(valid_snapshot_contents[:32]) |
| 93 | + f.write(struct.pack("<I", valid_num_coins + off)) |
| 94 | + f.write(valid_snapshot_contents[32 + 4:]) |
| 95 | + |
| 96 | + expected_log = f"bad snapshot - coins left over after deserializing 298 coins" if off == -1 else f"bad snapshot format or truncated snapshot after deserializing 299 coins" |
| 97 | + with self.nodes[1].assert_debug_log([expected_log]): |
| 98 | + assert_raises_rpc_error(-32603, "Unable to load UTXO snapshot", self.nodes[1].loadtxoutset, bad_snapshot_path) |
| 99 | + |
88 | 100 | def run_test(self):
|
89 | 101 | """
|
90 | 102 | Bring up two (disconnected) nodes, mine some new blocks on the first,
|
|
0 commit comments