Skip to content

Commit e4961d9

Browse files
authored
[CHIA-3654] [CHIA-3537] [CHIA-3673] stub chiapos2 API (#19969)
* stub chiapos2 API * update block tools to support v2 plots when generating chains, as well as using the solve_proof() stub in the solver * review comments
1 parent 9a47aa2 commit e4961d9

File tree

8 files changed

+96
-40
lines changed

8 files changed

+96
-40
lines changed

chia/_tests/core/custom_types/test_proof_of_space.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212
from chia._tests.util.misc import Marks, datacases
1313
from chia.consensus.default_constants import DEFAULT_CONSTANTS
1414
from chia.types.blockchain_format.proof_of_space import (
15-
calculate_plot_difficulty,
1615
calculate_prefix_bits,
16+
calculate_required_plot_strength,
1717
check_plot_size,
1818
make_pos,
1919
passes_plot_filter,
@@ -201,7 +201,7 @@ def test_verify_and_get_quality_string_v2(caplog: pytest.LogCaptureFixture, case
201201

202202

203203
@pytest.mark.parametrize(
204-
"height, difficulty",
204+
"height, strength",
205205
[
206206
(0, 2),
207207
(DEFAULT_CONSTANTS.HARD_FORK_HEIGHT, 2),
@@ -219,8 +219,8 @@ def test_verify_and_get_quality_string_v2(caplog: pytest.LogCaptureFixture, case
219219
(DEFAULT_CONSTANTS.PLOT_DIFFICULTY_8_HEIGHT + 1000000, 8),
220220
],
221221
)
222-
def test_calculate_plot_difficulty(height: uint32, difficulty: uint8) -> None:
223-
assert calculate_plot_difficulty(DEFAULT_CONSTANTS, height) == difficulty
222+
def test_calculate_plot_strength(height: uint32, strength: uint8) -> None:
223+
assert calculate_required_plot_strength(DEFAULT_CONSTANTS, height) == strength
224224

225225

226226
@pytest.mark.parametrize(

chia/_tests/plotting/test_prover.py

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

77
import pytest
88
from chia_rs.sized_bytes import bytes32
9+
from chia_rs.sized_ints import uint8
910

1011
from chia.plotting.prover import PlotVersion, V1Prover, V2Prover, get_prover_from_bytes, get_prover_from_file
1112

@@ -26,10 +27,9 @@ def test_v2_prover_get_memo_raises_error(self) -> None:
2627
with pytest.raises(NotImplementedError, match="V2 plot format is not yet implemented"):
2728
prover.get_memo()
2829

29-
def test_v2_prover_get_compression_level_raises_assertion_error(self) -> None:
30+
def test_v2_prover_get_compression_level(self) -> None:
3031
prover = V2Prover("/nonexistent/path/test.plot2")
31-
with pytest.raises(AssertionError, match="get_compression_level\\(\\) should never be called on V2 plots"):
32-
prover.get_compression_level()
32+
assert prover.get_compression_level() == uint8(0)
3333

3434
def test_v2_prover_get_id_raises_error(self) -> None:
3535
prover = V2Prover("/nonexistent/path/test.plot2")
@@ -38,7 +38,9 @@ def test_v2_prover_get_id_raises_error(self) -> None:
3838

3939
def test_v2_prover_get_qualities_for_challenge_raises_error(self) -> None:
4040
prover = V2Prover("/nonexistent/path/test.plot2")
41-
with pytest.raises(NotImplementedError, match="V2 plot format is not yet implemented"):
41+
with pytest.raises(
42+
AssertionError, match="V2 plot format does not support qualities directly, use partial proofs"
43+
):
4244
prover.get_qualities_for_challenge(bytes32(b"1" * 32))
4345

4446
def test_v2_prover_get_full_proof_raises_error(self) -> None:

chia/consensus/pos_quality.py

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
from __future__ import annotations
22

33
from chia_rs import PlotSize
4-
from chia_rs.sized_bytes import bytes32
54
from chia_rs.sized_ints import uint64
65

76
# The actual space in bytes of a plot, is _expected_plot_size(k) * UI_ACTUAL_SPACE_CONSTANT_FACTO
@@ -23,11 +22,6 @@
2322
}
2423

2524

26-
def quality_for_partial_proof(partial_proof: bytes, challenge: bytes32) -> bytes32:
27-
# TODO todo_v2_plots real implementaion
28-
return challenge
29-
30-
3125
def _expected_plot_size(size: PlotSize) -> uint64:
3226
"""
3327
Given the plot size parameter k (which is between 32 and 59), computes the

chia/harvester/harvester_api.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
from chia_rs.sized_bytes import bytes32
1212
from chia_rs.sized_ints import uint32, uint64
1313

14-
from chia.consensus.pos_quality import quality_for_partial_proof
1514
from chia.consensus.pot_iterations import (
1615
calculate_iterations_quality,
1716
calculate_sp_interval_iters,
@@ -29,9 +28,11 @@
2928
from chia.types.blockchain_format.proof_of_space import (
3029
calculate_pos_challenge,
3130
calculate_prefix_bits,
31+
calculate_required_plot_strength,
3232
generate_plot_public_key,
3333
make_pos,
3434
passes_plot_filter,
35+
quality_for_partial_proof,
3536
)
3637
from chia.wallet.derive_keys import master_sk_to_local_sk
3738

@@ -152,6 +153,10 @@ async def new_signage_point_harvester(
152153
start = time.monotonic()
153154
assert len(new_challenge.challenge_hash) == 32
154155

156+
required_plot_strength = calculate_required_plot_strength(
157+
self.harvester.constants, new_challenge.last_tx_height
158+
)
159+
155160
loop = asyncio.get_running_loop()
156161

157162
def blocking_lookup_v2_partial_proofs(filename: Path, plot_info: PlotInfo) -> Optional[PartialProofsData]:
@@ -163,7 +168,9 @@ def blocking_lookup_v2_partial_proofs(filename: Path, plot_info: PlotInfo) -> Op
163168
new_challenge.challenge_hash,
164169
new_challenge.sp_hash,
165170
)
166-
partial_proofs = plot_info.prover.get_partial_proofs_for_challenge(sp_challenge_hash)
171+
partial_proofs = plot_info.prover.get_partial_proofs_for_challenge(
172+
sp_challenge_hash, required_plot_strength
173+
)
167174

168175
# If no partial proofs are found, return None
169176
if len(partial_proofs) == 0:

chia/plotting/prover.py

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,12 @@ def get_version(self) -> PlotVersion: ...
2828
def __bytes__(self) -> bytes: ...
2929
def get_id(self) -> bytes32: ...
3030
def get_qualities_for_challenge(self, challenge: bytes32) -> list[bytes32]: ...
31-
def get_partial_proofs_for_challenge(self, challenge: bytes32) -> list[bytes]: ...
31+
32+
# this is only supported by v2 plots
33+
def get_partial_proofs_for_challenge(self, challenge: bytes32, required_plot_strength: uint8) -> list[bytes]: ...
34+
35+
# this is only supported by v1 plots. v2 plots first get the partial proof
36+
# and turn it into a full proof by calling solve_proof(), or pass it to the solver service
3237
def get_full_proof(self, challenge: bytes32, index: int, parallel_read: bool = True) -> bytes: ...
3338

3439
@classmethod
@@ -56,7 +61,8 @@ def get_memo(self) -> bytes:
5661
raise NotImplementedError("V2 plot format is not yet implemented")
5762

5863
def get_compression_level(self) -> uint8:
59-
raise AssertionError("get_compression_level() should never be called on V2 plots")
64+
# v2 plots are never compressed
65+
return uint8(0)
6066

6167
def get_version(self) -> PlotVersion:
6268
return PlotVersion.V2
@@ -70,11 +76,10 @@ def get_id(self) -> bytes32:
7076
raise NotImplementedError("V2 plot format is not yet implemented")
7177

7278
def get_qualities_for_challenge(self, challenge: bytes32) -> list[bytes32]:
73-
# TODO: todo_v2_plots Implement plot quality lookup
74-
raise NotImplementedError("V2 plot format is not yet implemented")
79+
raise AssertionError("V2 plot format does not support qualities directly, use partial proofs")
7580

76-
def get_partial_proofs_for_challenge(self, challenge: bytes32) -> list[bytes]:
77-
# TODO: todo_v2_plots Implement quality chain lookup (16 * k bits blobs)
81+
def get_partial_proofs_for_challenge(self, challenge: bytes, required_plot_strength: uint8) -> list[bytes]:
82+
# TODO: todo_v2_plots Implement plot partial proof lookup
7883
raise NotImplementedError("V2 plot format is not yet implemented")
7984

8085
def get_full_proof(self, challenge: bytes32, index: int, parallel_read: bool = True) -> bytes:
@@ -119,8 +124,8 @@ def get_id(self) -> bytes32:
119124
def get_qualities_for_challenge(self, challenge: bytes32) -> list[bytes32]:
120125
return [bytes32(quality) for quality in self._disk_prover.get_qualities_for_challenge(challenge)]
121126

122-
def get_partial_proofs_for_challenge(self, challenge: bytes32) -> list[bytes]:
123-
raise AssertionError("V1 does not implement quality chains, only qualities")
127+
def get_partial_proofs_for_challenge(self, challenge: bytes32, required_plot_strength: uint8) -> list[bytes]:
128+
raise AssertionError("V1 plot format doesn't use partial proofs")
124129

125130
def get_full_proof(self, challenge: bytes32, index: int, parallel_read: bool = True) -> bytes:
126131
return bytes(self._disk_prover.get_full_proof(challenge, index, parallel_read))

chia/simulator/block_tools.py

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
from dataclasses import dataclass, replace
1515
from pathlib import Path
1616
from random import Random
17-
from typing import Any, Callable, Optional
17+
from typing import Any, Callable, Optional, Union
1818

1919
import anyio
2020
from chia_puzzles_py.programs import CHIALISP_DESERIALISATION, ROM_BOOTSTRAP_GENERATOR
@@ -64,6 +64,7 @@
6464
from chia.full_node.bundle_tools import simple_solution_generator, simple_solution_generator_backrefs
6565
from chia.plotting.create_plots import PlotKeys, create_plots
6666
from chia.plotting.manager import PlotManager
67+
from chia.plotting.prover import PlotVersion
6768
from chia.plotting.util import (
6869
Params,
6970
PlotRefreshEvents,
@@ -91,10 +92,13 @@
9192
from chia.types.blockchain_format.proof_of_space import (
9293
calculate_pos_challenge,
9394
calculate_prefix_bits,
95+
calculate_required_plot_strength,
9496
generate_plot_public_key,
9597
generate_taproot_sk,
9698
make_pos,
9799
passes_plot_filter,
100+
quality_for_partial_proof,
101+
solve_proof,
98102
)
99103
from chia.types.blockchain_format.serialized_program import SerializedProgram
100104
from chia.types.blockchain_format.vdf import VDFInfo, VDFProof
@@ -1500,6 +1504,9 @@ def get_pospaces_for_challenge(
15001504
found_proofs: list[tuple[uint64, ProofOfSpace]] = []
15011505
rng = random.Random()
15021506
rng.seed(seed)
1507+
1508+
required_plot_strength = calculate_required_plot_strength(constants, prev_transaction_b_height)
1509+
15031510
for plot_info in self.plot_manager.plots.values():
15041511
plot_id: bytes32 = plot_info.prover.get_id()
15051512
if force_plot_id is not None and plot_id != force_plot_id:
@@ -1508,10 +1515,29 @@ def get_pospaces_for_challenge(
15081515
if not passes_plot_filter(prefix_bits, plot_id, challenge_hash, signage_point):
15091516
continue
15101517

1518+
# v2 plots aren't valid until after the hard fork
1519+
if (
1520+
prev_transaction_b_height < constants.HARD_FORK2_HEIGHT
1521+
and plot_info.prover.get_version() == PlotVersion.V2
1522+
):
1523+
continue
1524+
15111525
new_challenge: bytes32 = calculate_pos_challenge(plot_id, challenge_hash, signage_point)
1512-
qualities = plot_info.prover.get_qualities_for_challenge(new_challenge)
15131526

1514-
for proof_index, quality_str in enumerate(qualities):
1527+
# these are either qualities (v1) or partial proofs (v2)
1528+
proofs: Sequence[Union[bytes32, bytes]]
1529+
v = plot_info.prover.get_version()
1530+
if v == PlotVersion.V1:
1531+
proofs = plot_info.prover.get_qualities_for_challenge(new_challenge)
1532+
else:
1533+
proofs = plot_info.prover.get_partial_proofs_for_challenge(new_challenge, required_plot_strength)
1534+
1535+
for proof_index, proof in enumerate(proofs):
1536+
if v == PlotVersion.V2:
1537+
quality_str = quality_for_partial_proof(proof, new_challenge)
1538+
elif v == PlotVersion.V1:
1539+
quality_str = bytes32(proof)
1540+
15151541
required_iters = calculate_iterations_quality(
15161542
constants,
15171543
quality_str,
@@ -1524,7 +1550,11 @@ def get_pospaces_for_challenge(
15241550
if required_iters >= calculate_sp_interval_iters(constants, sub_slot_iters):
15251551
continue
15261552

1527-
proof_xs: bytes = plot_info.prover.get_full_proof(new_challenge, proof_index)
1553+
proof_xs: bytes
1554+
if v == PlotVersion.V1:
1555+
proof_xs = plot_info.prover.get_full_proof(new_challenge, proof_index)
1556+
else:
1557+
proof_xs = solve_proof(proof)
15281558

15291559
# Look up local_sk from plot to save locked memory
15301560
(

chia/solver/solver.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
from chia.rpc.rpc_server import StateChangedProtocol, default_get_connections
1515
from chia.server.server import ChiaServer
1616
from chia.server.ws_connection import WSChiaConnection
17+
from chia.types.blockchain_format.proof_of_space import solve_proof
1718

1819
log = logging.getLogger(__name__)
1920

@@ -67,7 +68,10 @@ async def manage(self) -> AsyncIterator[None]:
6768

6869
def solve(self, partial_proof: bytes) -> Optional[bytes]:
6970
self.log.debug(f"Solve request: partial={partial_proof.hex()}")
70-
# TODO todo_v2_plots implement actualy calling the solver
71+
try:
72+
return solve_proof(partial_proof)
73+
except Exception:
74+
self.log.exception("solve_proof()")
7175
return None
7276

7377
def get_connections(self, request_node_type: Optional[NodeType]) -> list[dict[str, Any]]:

chia/types/blockchain_format/proof_of_space.py

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,28 @@
1313

1414
log = logging.getLogger(__name__)
1515

16+
# These are temporary stubs for chiapos2, that we build against until it's ready to be integrated.
17+
18+
19+
# returns quality string for v2 plot, or None if invalid
20+
def validate_proof_v2(
21+
plot_id: bytes32, size: uint8, required_plot_strength: uint8, challenge: bytes32, proof: bytes
22+
) -> Optional[bytes32]:
23+
# TODO: todo_v2_plots call into new chiapos library
24+
raise NotImplementedError
25+
26+
27+
# this is compute intensive, solving a partial proof returning a full proof
28+
def solve_proof(partial_proof: bytes) -> bytes:
29+
# TODO: todo_v2_plots call into new chiapos library
30+
raise NotImplementedError
31+
32+
33+
# given a partial proof, computes the quality. This is used to compute required iters.
34+
def quality_for_partial_proof(partial_proof: bytes, challenge: bytes32) -> bytes32:
35+
# TODO: todo_v2_plots call into new chiapos library
36+
return std_hash(partial_proof + challenge)
37+
1638

1739
def make_pos(
1840
challenge: bytes32,
@@ -49,14 +71,6 @@ def get_plot_id(pos: ProofOfSpace) -> bytes32:
4971
return calculate_plot_id_pk(pos.pool_public_key, pos.plot_public_key)
5072

5173

52-
# returns quality string for v2 plot, or None if invalid
53-
def validate_proof_v2(
54-
plot_id: bytes32, size: uint8, difficulty: uint8, challenge: bytes32, proof: bytes
55-
) -> Optional[bytes32]:
56-
# TODO: todo_v2_plots call into new chiapos library
57-
raise NotImplementedError
58-
59-
6074
def check_plot_size(constants: ConsensusConstants, ps: PlotSize) -> bool:
6175
size_v1 = ps.size_v1
6276
if size_v1 is not None:
@@ -128,8 +142,8 @@ def verify_and_get_quality_string(
128142
# === V2 plots ===
129143
assert plot_size.size_v2 is not None
130144

131-
plot_difficulty = calculate_plot_difficulty(constants, height)
132-
return validate_proof_v2(plot_id, plot_size.size_v2, plot_difficulty, pos.challenge, bytes(pos.proof))
145+
required_plot_strength = calculate_required_plot_strength(constants, height)
146+
return validate_proof_v2(plot_id, plot_size.size_v2, required_plot_strength, pos.challenge, bytes(pos.proof))
133147

134148

135149
def passes_plot_filter(
@@ -167,7 +181,7 @@ def calculate_prefix_bits(constants: ConsensusConstants, height: uint32, plot_si
167181
return max(0, prefix_bits)
168182

169183

170-
def calculate_plot_difficulty(constants: ConsensusConstants, height: uint32) -> uint8:
184+
def calculate_required_plot_strength(constants: ConsensusConstants, height: uint32) -> uint8:
171185
if height < constants.PLOT_DIFFICULTY_4_HEIGHT:
172186
return constants.PLOT_DIFFICULTY_INITIAL
173187
if height < constants.PLOT_DIFFICULTY_5_HEIGHT:

0 commit comments

Comments
 (0)