Skip to content

Commit 2b0c41d

Browse files
committed
harvester_new_sp concurrent, add strength back
1 parent bbc9fc0 commit 2b0c41d

15 files changed

+102
-46
lines changed

chia/_tests/farmer_harvester/test_farmer_harvester.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -341,7 +341,7 @@ async def test_v2_partial_proofs_new_sp_hash(
341341
partial_proofs=[b"test_partial_proof_1"],
342342
signage_point_index=uint8(0),
343343
plot_size=uint8(32),
344-
difficulty=uint64(1000),
344+
plot_strength=uint64(1000),
345345
pool_public_key=None,
346346
pool_contract_puzzle_hash=bytes32(b"4" * 32),
347347
plot_public_key=G1Element(),
@@ -371,7 +371,7 @@ async def test_v2_partial_proofs_missing_sp_hash(
371371
partial_proofs=[b"test_partial_proof_1"],
372372
signage_point_index=uint8(0),
373373
plot_size=uint8(32),
374-
difficulty=uint64(1000),
374+
plot_strength=uint64(1000),
375375
pool_public_key=None,
376376
pool_contract_puzzle_hash=bytes32(b"4" * 32),
377377
plot_public_key=G1Element(),
@@ -414,7 +414,7 @@ async def test_v2_partial_proofs_with_existing_sp(
414414
partial_proofs=[b"test_partial_proof_1", b"test_partial_proof_2"],
415415
signage_point_index=uint8(0),
416416
plot_size=uint8(32),
417-
difficulty=uint64(1000),
417+
plot_strength=uint64(1000),
418418
pool_public_key=G1Element(),
419419
pool_contract_puzzle_hash=bytes32(b"4" * 32),
420420
plot_public_key=G1Element(),
@@ -448,7 +448,7 @@ async def test_solution_response_handler(
448448
partial_proofs=[b"test_partial_proof_for_quality"],
449449
signage_point_index=uint8(0),
450450
plot_size=uint8(32),
451-
difficulty=uint64(1000),
451+
plot_strength=uint64(1000),
452452
pool_public_key=G1Element(),
453453
pool_contract_puzzle_hash=bytes32(b"4" * 32),
454454
plot_public_key=G1Element(),
@@ -525,7 +525,7 @@ async def test_solution_response_empty_proof(
525525
partial_proofs=[b"test_partial_proof_for_quality"],
526526
signage_point_index=uint8(0),
527527
plot_size=uint8(32),
528-
difficulty=uint64(1000),
528+
plot_strength=uint64(1000),
529529
pool_public_key=G1Element(),
530530
pool_contract_puzzle_hash=bytes32(b"4" * 32),
531531
plot_public_key=G1Element(),
@@ -587,7 +587,7 @@ async def test_v2_partial_proofs_solver_exception(
587587
partial_proofs=[b"test_partial_proof_1"],
588588
signage_point_index=uint8(0),
589589
plot_size=uint8(32),
590-
difficulty=uint64(1000),
590+
plot_strength=uint64(1000),
591591
pool_public_key=G1Element(),
592592
pool_contract_puzzle_hash=bytes32(b"4" * 32),
593593
plot_public_key=G1Element(),

chia/_tests/solver/test_solver_service.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
import pytest
77
from chia_rs import ConsensusConstants
8+
from chia_rs.sized_ints import uint64
89

910
from chia.protocols.outbound_message import Message
1011
from chia.protocols.solver_protocol import SolverInfo
@@ -22,7 +23,7 @@ async def test_solver_api_methods(blockchain_constants: ConsensusConstants, tmp_
2223
solver = solver_service._node
2324
solver_api = solver_service._api
2425
assert solver_api.ready() is True
25-
test_info = SolverInfo(partial_proof=b"test_partial_proof_42")
26+
test_info = SolverInfo(partial_proof=b"test_partial_proof_42", plot_strength=uint64(1500))
2627
expected_proof = b"test_proof_data_12345"
2728
with patch.object(solver, "solve", return_value=expected_proof):
2829
api_result = await solver_api.solve(test_info)
@@ -42,13 +43,13 @@ async def test_solver_error_handling(
4243
self_hostname, solver_service.rpc_server.listen_port, solver_service.root_path, solver_service.config
4344
)
4445
try:
45-
await solver_rpc_client.solve("invalid_hex")
46+
await solver_rpc_client.solve("invalid_hex", uint64(1000))
4647
assert False, "should have raised exception for invalid hex"
4748
except Exception:
4849
pass # expected
4950
# test solver handles exception in solve method
5051
solver = solver_service._node
51-
test_info = SolverInfo(partial_proof=b"test_partial_proof_zeros")
52+
test_info = SolverInfo(partial_proof=b"test_partial_proof_zeros", plot_strength=uint64(1000))
5253
with patch.object(solver, "solve", side_effect=RuntimeError("test error")):
5354
# solver api should handle exceptions gracefully
5455
result = await solver_service._api.solve(test_info)

chia/_tests/util/network_protocol_data.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1106,6 +1106,6 @@
11061106
)
11071107

11081108
# SOLVER PROTOCOL
1109-
solver_info = solver_protocol.SolverInfo(partial_proof=b"partial-proof")
1109+
solver_info = solver_protocol.SolverInfo(partial_proof=b"partial-proof", plot_strength=uint64(2))
11101110

11111111
solver_response = solver_protocol.SolverResponse(b"partial-proof", b"full-proof")
8 Bytes
Binary file not shown.

chia/_tests/util/protocol_messages_json.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@
7272
"partial_proofs": ["0x7061727469616c2d70726f6f6631", "0x7061727469616c2d70726f6f6632"],
7373
"signage_point_index": 4,
7474
"plot_size": 32,
75-
"difficulty": 100000,
75+
"plot_strength": 100000,
7676
"pool_public_key": "0xa04c6b5ac7dfb935f6feecfdd72348ccf1d4be4fe7e26acf271ea3b7d308da61e0a308f7a62495328a81f5147b66634c",
7777
"pool_contract_puzzle_hash": "0x91240fbacdf93b44c0571caa74fd99f163d4c5d7deaedac87125528721493f7a",
7878
"plot_public_key": "0xa04c6b5ac7dfb935f6feecfdd72348ccf1d4be4fe7e26acf271ea3b7d308da61e0a308f7a62495328a81f5147b66634c",
@@ -2715,7 +2715,7 @@
27152715

27162716
error_with_data_json: dict[str, Any] = {"code": 1, "message": "Unknown", "data": "0x65787472612064617461"}
27172717

2718-
solver_info_json: dict[str, Any] = {"partial_proof": "0x7061727469616c2d70726f6f66"}
2718+
solver_info_json: dict[str, Any] = {"partial_proof": "0x7061727469616c2d70726f6f66", "plot_strength": 2}
27192719

27202720
solver_response_json: dict[str, Any] = {
27212721
"partial_proof": "0x7061727469616c2d70726f6f66",

chia/cmds/solver.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,14 +49,23 @@ def get_state_cmd(
4949
type=str,
5050
required=True,
5151
)
52+
@click.option(
53+
"-s",
54+
"--plot_strength",
55+
help="Plot plot_strength (default: 1000)",
56+
type=int,
57+
default=1000,
58+
show_default=True,
59+
)
5260
@click.pass_context
5361
def solve_cmd(
5462
ctx: click.Context,
5563
solver_rpc_port: Optional[int],
5664
partial_proof: str,
65+
plot_strength: int,
5766
) -> None:
5867
import asyncio
5968

6069
from chia.cmds.solver_funcs import solve_partial_proof
6170

62-
asyncio.run(solve_partial_proof(ChiaCliContext.set_default(ctx), solver_rpc_port, partial_proof))
71+
asyncio.run(solve_partial_proof(ChiaCliContext.set_default(ctx), solver_rpc_port, partial_proof, plot_strength))

chia/cmds/solver_funcs.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
import json
44
from typing import Optional
55

6+
from chia_rs.sized_ints import uint64
7+
68
from chia.cmds.cmd_classes import ChiaCliContext
79
from chia.cmds.cmds_util import get_any_service_client
810
from chia.solver.solver_rpc_client import SolverRpcClient
@@ -25,11 +27,12 @@ async def solve_partial_proof(
2527
ctx: ChiaCliContext,
2628
solver_rpc_port: Optional[int],
2729
partial_proof: str,
30+
plot_strength: int,
2831
) -> None:
2932
"""Solve a partial proof via RPC."""
3033
try:
3134
async with get_any_service_client(SolverRpcClient, ctx.root_path, solver_rpc_port) as (client, _):
32-
response = await client.solve(partial_proof)
35+
response = await client.solve(partial_proof, plot_strength=uint64(plot_strength))
3336
print(json.dumps(response, indent=2))
3437
except Exception as e:
3538
print(f"Failed to solve partial proof: {e}")

chia/farmer/farmer_api.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -505,7 +505,7 @@ async def partial_proofs(self, partial_proof_data: PartialProofsData, peer: WSCh
505505

506506
# Process each quality chain through solver service to get full proofs
507507
for partial_proof in partial_proof_data.partial_proofs:
508-
solver_info = SolverInfo(partial_proof=partial_proof)
508+
solver_info = SolverInfo(partial_proof=partial_proof, plot_strength=partial_proof_data.plot_strength)
509509

510510
try:
511511
# store pending request data for matching with response

chia/harvester/harvester_api.py

Lines changed: 58 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import asyncio
44
import logging
55
import time
6+
from collections.abc import Awaitable, Sequence
67
from pathlib import Path
78
from typing import TYPE_CHECKING, ClassVar, Optional, cast
89

@@ -65,6 +66,47 @@ def _plot_passes_filter(self, plot_info: PlotInfo, challenge: harvester_protocol
6566
challenge.sp_hash,
6667
)
6768

69+
async def _handle_v1_responses(
70+
self,
71+
awaitables: Sequence[Awaitable[tuple[Path, list[harvester_protocol.NewProofOfSpace]]]],
72+
start_time: float,
73+
peer: WSChiaConnection,
74+
) -> int:
75+
proofs_found = 0
76+
for filename_sublist_awaitable in asyncio.as_completed(awaitables):
77+
filename, sublist = await filename_sublist_awaitable
78+
time_taken = time.monotonic() - start_time
79+
if time_taken > 8:
80+
self.harvester.log.warning(
81+
f"Looking up qualities on {filename} took: {time_taken}. This should be below 8 seconds"
82+
f" to minimize risk of losing rewards."
83+
)
84+
for response in sublist:
85+
proofs_found += 1
86+
msg = make_msg(ProtocolMessageTypes.new_proof_of_space, response)
87+
await peer.send_message(msg)
88+
return proofs_found
89+
90+
async def _handle_v2_responses(
91+
self, v2_awaitables: Sequence[Awaitable[Optional[PartialProofsData]]], start_time: float, peer: WSChiaConnection
92+
) -> int:
93+
partial_proofs_found = 0
94+
for quality_awaitable in asyncio.as_completed(v2_awaitables):
95+
partial_proofs_data = await quality_awaitable
96+
if partial_proofs_data is None:
97+
continue
98+
time_taken = time.monotonic() - start_time
99+
if time_taken > 8:
100+
self.harvester.log.warning(
101+
f"Looking up partial proofs on {partial_proofs_data.plot_identifier}"
102+
f"took: {time_taken}. This should be below 8 seconds"
103+
f"to minimize risk of losing rewards."
104+
)
105+
partial_proofs_found += len(partial_proofs_data.partial_proofs)
106+
msg = make_msg(ProtocolMessageTypes.partial_proofs, partial_proofs_data)
107+
await peer.send_message(msg)
108+
return partial_proofs_found
109+
68110
@metadata.request(peer_required=True)
69111
async def harvester_handshake(
70112
self, harvester_handshake: harvester_protocol.HarvesterHandshake, peer: WSChiaConnection
@@ -354,30 +396,22 @@ async def lookup_challenge(
354396
total_proofs_found = 0
355397
total_v2_partial_proofs_found = 0
356398

357-
# Process V1 plot responses (existing flow)
358-
for filename_sublist_awaitable in asyncio.as_completed(awaitables):
359-
filename, sublist = await filename_sublist_awaitable
360-
time_taken = time.monotonic() - start
361-
if time_taken > 8:
362-
self.harvester.log.warning(
363-
f"Looking up qualities on {filename} took: {time_taken}. This should be below 8 seconds"
364-
f" to minimize risk of losing rewards."
365-
)
366-
else:
367-
pass
368-
# self.harvester.log.info(f"Looking up qualities on {filename} took: {time_taken}")
369-
for response in sublist:
370-
total_proofs_found += 1
371-
msg = make_msg(ProtocolMessageTypes.new_proof_of_space, response)
372-
await peer.send_message(msg)
373-
374-
# Process V2 plot quality collections (new flow)
375-
for quality_awaitable in asyncio.as_completed(v2_awaitables):
376-
partial_proofs_data = await quality_awaitable
377-
if partial_proofs_data is not None:
378-
total_v2_partial_proofs_found += len(partial_proofs_data.partial_proofs)
379-
msg = make_msg(ProtocolMessageTypes.partial_proofs, partial_proofs_data)
380-
await peer.send_message(msg)
399+
# run both concurrently
400+
tasks = []
401+
if awaitables:
402+
tasks.append(self._handle_v1_responses(awaitables, start, peer))
403+
if v2_awaitables:
404+
tasks.append(self._handle_v2_responses(v2_awaitables, start, peer))
405+
406+
if tasks:
407+
results = await asyncio.gather(*tasks)
408+
if len(results) == 2:
409+
total_proofs_found, total_v2_partial_proofs_found = results
410+
elif len(results) == 1:
411+
if awaitables:
412+
total_proofs_found = results[0]
413+
else:
414+
total_v2_partial_proofs_found = results[0]
381415

382416
now = uint64(time.time())
383417

chia/protocols/harvester_protocol.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ class PartialProofsData(Streamable):
7272
partial_proofs: list[bytes] # 16 * k bits blobs instead of 32-byte quality strings
7373
signage_point_index: uint8
7474
plot_size: uint8
75-
difficulty: uint64
75+
plot_strength: uint64
7676
pool_public_key: Optional[G1Element]
7777
pool_contract_puzzle_hash: Optional[bytes32]
7878
plot_public_key: G1Element

0 commit comments

Comments
 (0)