|
1 | 1 | from __future__ import annotations
|
2 | 2 |
|
3 | 3 | from pathlib import Path
|
4 |
| -from typing import Optional |
5 | 4 | from unittest.mock import patch
|
6 | 5 |
|
7 | 6 | import pytest
|
8 |
| -from chia_rs import ConsensusConstants, FullBlock |
9 |
| -from chia_rs.sized_bytes import bytes32 |
| 7 | +from chia_rs import ConsensusConstants |
10 | 8 | from chia_rs.sized_ints import uint64
|
11 | 9 |
|
12 |
| -from chia._tests.blockchain.blockchain_test_utils import _validate_and_add_block |
13 |
| -from chia.consensus.blockchain import Blockchain |
14 |
| -from chia.consensus.get_block_challenge import get_block_challenge |
15 |
| -from chia.consensus.pot_iterations import is_overflow_block |
| 10 | +from chia.protocols.outbound_message import Message |
16 | 11 | from chia.protocols.solver_protocol import SolverInfo
|
17 | 12 | from chia.simulator.block_tools import create_block_tools_async
|
| 13 | +from chia.simulator.keyring import TempKeyring |
18 | 14 | from chia.simulator.setup_services import setup_solver
|
19 | 15 | from chia.solver.solver_rpc_client import SolverRpcClient
|
20 |
| -from chia.types.blockchain_format.proof_of_space import verify_and_get_quality_string |
21 | 16 |
|
22 | 17 |
|
23 | 18 | @pytest.mark.anyio
|
24 | 19 | async def test_solver_api_methods(blockchain_constants: ConsensusConstants, tmp_path: Path) -> None:
|
25 |
| - bt = await create_block_tools_async(constants=blockchain_constants) |
26 |
| - async with setup_solver(tmp_path, bt, blockchain_constants) as solver_service: |
27 |
| - solver = solver_service._node |
28 |
| - solver_api = solver_service._api |
29 |
| - assert solver_api.ready() is True |
30 |
| - |
31 |
| - # test solve with real SolverInfo |
32 |
| - test_info = SolverInfo(plot_difficulty=uint64(1500), quality_chain=b"test_quality_chain_42") |
33 |
| - |
34 |
| - # test normal solve operation (stub returns None) |
35 |
| - result = solver.solve(test_info) |
36 |
| - assert result is None |
37 |
| - |
38 |
| - # test with mocked return value to verify full flow |
39 |
| - expected_proof = b"test_proof_data_12345" |
40 |
| - with patch.object(solver, "solve", return_value=expected_proof): |
41 |
| - api_result = await solver_api.solve(test_info) |
42 |
| - assert api_result is not None |
43 |
| - # api returns protocol message for peer communication |
44 |
| - from chia.protocols.outbound_message import Message |
45 |
| - |
46 |
| - assert isinstance(api_result, Message) |
47 |
| - |
48 |
| - # test error handling - solver not started |
49 |
| - original_started = solver.started |
50 |
| - solver.started = False |
51 |
| - api_result = await solver_api.solve(test_info) |
52 |
| - assert api_result is None |
53 |
| - solver.started = original_started |
| 20 | + with TempKeyring(populate=True) as keychain: |
| 21 | + bt = await create_block_tools_async(constants=blockchain_constants, keychain=keychain) |
| 22 | + async with setup_solver(tmp_path, bt, blockchain_constants) as solver_service: |
| 23 | + solver = solver_service._node |
| 24 | + solver_api = solver_service._api |
| 25 | + assert solver_api.ready() is True |
| 26 | + test_info = SolverInfo(plot_difficulty=uint64(1500), quality_chain=b"test_quality_chain_42") |
| 27 | + expected_proof = b"test_proof_data_12345" |
| 28 | + with patch.object(solver, "solve", return_value=expected_proof): |
| 29 | + api_result = await solver_api.solve(test_info) |
| 30 | + assert api_result is not None |
| 31 | + assert isinstance(api_result, Message) |
54 | 32 |
|
55 | 33 |
|
56 | 34 | @pytest.mark.anyio
|
57 |
| -async def test_solver_with_real_blocks_and_signage_points( |
58 |
| - blockchain_constants: ConsensusConstants, |
59 |
| - default_400_blocks: list[FullBlock], |
60 |
| - empty_blockchain: Blockchain, |
61 |
| - self_hostname: str, |
62 |
| - tmp_path: Path, |
63 |
| -) -> None: |
64 |
| - blockchain = empty_blockchain |
65 |
| - blocks = default_400_blocks[:3] |
66 |
| - for block in blocks: |
67 |
| - await _validate_and_add_block(empty_blockchain, block) |
68 |
| - block = blocks[-1] # always use the last block |
69 |
| - overflow = is_overflow_block(blockchain_constants, block.reward_chain_block.signage_point_index) |
70 |
| - challenge = get_block_challenge(blockchain_constants, block, blockchain, False, overflow, False) |
71 |
| - assert block.reward_chain_block.pos_ss_cc_challenge_hash == challenge |
72 |
| - if block.reward_chain_block.challenge_chain_sp_vdf is None: |
73 |
| - challenge_chain_sp: bytes32 = challenge |
74 |
| - else: |
75 |
| - challenge_chain_sp = block.reward_chain_block.challenge_chain_sp_vdf.output.get_hash() |
76 |
| - # extract real quality data from blocks using chia's proof of space verification |
77 |
| - pos = block.reward_chain_block.proof_of_space |
78 |
| - # calculate real quality string from proof of space data |
79 |
| - quality_string: Optional[bytes32] = verify_and_get_quality_string( |
80 |
| - block.reward_chain_block.proof_of_space, |
81 |
| - blockchain_constants, |
82 |
| - challenge, |
83 |
| - challenge_chain_sp, |
84 |
| - height=block.reward_chain_block.height, |
85 |
| - ) |
86 |
| - |
87 |
| - assert quality_string is not None |
88 |
| - quality_hex = quality_string.hex() |
89 |
| - |
90 |
| - # test solver with real blockchain quality |
91 |
| - plot_size = pos.size() |
92 |
| - k_size = plot_size.size_v1 if plot_size.size_v1 is not None else plot_size.size_v2 |
93 |
| - assert k_size is not None |
94 |
| - bt = await create_block_tools_async(constants=blockchain_constants) |
95 |
| - async with setup_solver(tmp_path, bt, blockchain_constants) as solver_service: |
96 |
| - assert solver_service.rpc_server is not None |
97 |
| - solver_rpc_client = await SolverRpcClient.create( |
98 |
| - self_hostname, solver_service.rpc_server.listen_port, solver_service.root_path, solver_service.config |
99 |
| - ) |
100 |
| - solve_response = await solver_rpc_client.solve(quality_hex, int(k_size), 1000) |
101 |
| - assert solve_response["success"] is True |
102 |
| - assert "proof" in solve_response |
103 |
| - # stub implementation returns None, real implementation would return actual proof |
104 |
| - assert solve_response["proof"] is None |
105 |
| - |
106 |
| - |
107 |
| -@pytest.mark.anyio |
108 |
| -async def test_solver_error_handling_and_edge_cases( |
| 35 | +async def test_solver_error_handling( |
109 | 36 | blockchain_constants: ConsensusConstants, self_hostname: str, tmp_path: Path
|
110 | 37 | ) -> None:
|
111 |
| - bt = await create_block_tools_async(constants=blockchain_constants) |
112 |
| - async with setup_solver(tmp_path, bt, blockchain_constants) as solver_service: |
113 |
| - assert solver_service.rpc_server is not None |
114 |
| - solver_rpc_client = await SolverRpcClient.create( |
115 |
| - self_hostname, solver_service.rpc_server.listen_port, solver_service.root_path, solver_service.config |
116 |
| - ) |
117 |
| - |
118 |
| - # test invalid quality string format |
119 |
| - try: |
120 |
| - await solver_rpc_client.solve("invalid_hex") |
121 |
| - assert False, "should have raised exception for invalid hex" |
122 |
| - except Exception: |
123 |
| - pass # expected |
124 |
| - |
125 |
| - # test edge case parameters |
126 |
| - valid_quality = "1234567890abcdef" * 4 |
127 |
| - |
128 |
| - # test with edge case plot sizes and difficulties |
129 |
| - edge_cases = [ |
130 |
| - (18, 1), # minimum plot size, minimum difficulty |
131 |
| - (50, 999999), # large plot size, high difficulty |
132 |
| - ] |
133 |
| - |
134 |
| - for plot_size, difficulty in edge_cases: |
135 |
| - response = await solver_rpc_client.solve(valid_quality, plot_size, difficulty) |
136 |
| - assert response["success"] is True |
137 |
| - assert "proof" in response |
138 |
| - |
139 |
| - # test solver handles exception in solve method |
140 |
| - solver = solver_service._node |
141 |
| - test_info = SolverInfo(plot_difficulty=uint64(1000), quality_chain=b"test_quality_chain_zeros") |
142 |
| - |
143 |
| - with patch.object(solver, "solve", side_effect=RuntimeError("test error")): |
144 |
| - # solver api should handle exceptions gracefully |
145 |
| - result = await solver_service._api.solve(test_info) |
146 |
| - assert result is None # api returns None on error |
| 38 | + with TempKeyring(populate=True) as keychain: |
| 39 | + bt = await create_block_tools_async(constants=blockchain_constants, keychain=keychain) |
| 40 | + async with setup_solver(tmp_path, bt, blockchain_constants) as solver_service: |
| 41 | + assert solver_service.rpc_server is not None |
| 42 | + solver_rpc_client = await SolverRpcClient.create( |
| 43 | + self_hostname, solver_service.rpc_server.listen_port, solver_service.root_path, solver_service.config |
| 44 | + ) |
| 45 | + try: |
| 46 | + await solver_rpc_client.solve("invalid_hex") |
| 47 | + assert False, "should have raised exception for invalid hex" |
| 48 | + except Exception: |
| 49 | + pass # expected |
| 50 | + # test solver handles exception in solve method |
| 51 | + solver = solver_service._node |
| 52 | + test_info = SolverInfo(plot_difficulty=uint64(1000), quality_chain=b"test_quality_chain_zeros") |
| 53 | + with patch.object(solver, "solve", side_effect=RuntimeError("test error")): |
| 54 | + # solver api should handle exceptions gracefully |
| 55 | + result = await solver_service._api.solve(test_info) |
| 56 | + assert result is None # api returns None on error |
0 commit comments