Skip to content

Commit 867c3fb

Browse files
committed
stub chiapos2 API
1 parent 3c3e160 commit 867c3fb

File tree

7 files changed

+111
-75
lines changed

7 files changed

+111
-75
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,7 +12,7 @@
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,
15+
calculate_plot_strength,
1616
calculate_prefix_bits,
1717
check_plot_size,
1818
make_pos,
@@ -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_plot_strength(DEFAULT_CONSTANTS, height) == strength
224224

225225

226226
@pytest.mark.parametrize(

chia/_tests/plotting/test_prover.py

Lines changed: 6 additions & 6 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_error(self) -> None:
30+
def test_v2_prover_get_compression_level(self) -> None:
3031
prover = V2Prover("/nonexistent/path/test.plot2")
31-
with pytest.raises(NotImplementedError, match="V2 plot format does not support compression level"):
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")
@@ -39,12 +39,12 @@ def test_v2_prover_get_id_raises_error(self) -> None:
3939
def test_v2_prover_get_qualities_for_challenge_raises_error(self) -> None:
4040
prover = V2Prover("/nonexistent/path/test.plot2")
4141
with pytest.raises(NotImplementedError, match="V2 plot format is not yet implemented"):
42-
prover.get_qualities_for_challenge(bytes32(b"1" * 32))
42+
prover.get_qualities_for_challenge(bytes32.random(), uint8(2))
4343

4444
def test_v2_prover_get_full_proof_raises_error(self) -> None:
4545
prover = V2Prover("/nonexistent/path/test.plot2")
46-
with pytest.raises(NotImplementedError, match="V2 plot format require solver to get full proof"):
47-
prover.get_full_proof(bytes32(b"1" * 32), 0)
46+
with pytest.raises(AssertionError, match="V2 plots don't have full proofs"):
47+
prover.get_full_proof(bytes32.random(), 0)
4848

4949
def test_v2_prover_bytes_raises_error(self) -> None:
5050
prover = V2Prover("/nonexistent/path/test.plot2")

chia/harvester/harvester_api.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
from chia.server.api_protocol import ApiMetadata
2727
from chia.server.ws_connection import WSChiaConnection
2828
from chia.types.blockchain_format.proof_of_space import (
29+
calculate_plot_strength,
2930
calculate_pos_challenge,
3031
calculate_prefix_bits,
3132
generate_plot_public_key,
@@ -110,6 +111,8 @@ async def new_signage_point_harvester(
110111
start = time.monotonic()
111112
assert len(new_challenge.challenge_hash) == 32
112113

114+
plot_strength = calculate_plot_strength(self.harvester.constants, new_challenge.last_tx_height)
115+
113116
loop = asyncio.get_running_loop()
114117

115118
def blocking_lookup_v2_partial_proofs(filename: Path, plot_info: PlotInfo) -> Optional[PartialProofsData]:
@@ -121,7 +124,7 @@ def blocking_lookup_v2_partial_proofs(filename: Path, plot_info: PlotInfo) -> Op
121124
new_challenge.challenge_hash,
122125
new_challenge.sp_hash,
123126
)
124-
partial_proofs = plot_info.prover.get_partial_proofs_for_challenge(sp_challenge_hash)
127+
partial_proofs = plot_info.prover.get_partial_proofs_for_challenge(sp_challenge_hash, plot_strength)
125128

126129
# If no partial proofs are found, return None
127130
if partial_proofs is None or len(partial_proofs) == 0:
@@ -190,7 +193,7 @@ def blocking_lookup(filename: Path, plot_info: PlotInfo) -> list[tuple[bytes32,
190193
new_challenge.sp_hash,
191194
)
192195
try:
193-
quality_strings = plot_info.prover.get_qualities_for_challenge(sp_challenge_hash)
196+
quality_strings = plot_info.prover.get_qualities_for_challenge(sp_challenge_hash, plot_strength)
194197
except RuntimeError as e:
195198
if str(e) == "Timeout waiting for context queue.":
196199
self.harvester.log.warning(

chia/plotting/check_plots.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
from chia_rs.sized_ints import uint8, uint32
1313
from chiapos import Verifier
1414

15+
from chia.consensus.default_constants import DEFAULT_CONSTANTS
1516
from chia.plotting.manager import PlotManager
1617
from chia.plotting.util import (
1718
PlotInfo,
@@ -173,7 +174,9 @@ def process_plot(plot_path: Path, plot_info: PlotInfo, num_start: int, num_end:
173174
# Some plot errors cause get_qualities_for_challenge to throw a RuntimeError
174175
try:
175176
quality_start_time = round(time() * 1000)
176-
for index, quality_str in enumerate(pr.get_qualities_for_challenge(challenge)):
177+
for index, quality_str in enumerate(
178+
pr.get_qualities_for_challenge(challenge, DEFAULT_CONSTANTS.PLOT_DIFFICULTY_INITIAL)
179+
):
177180
quality_spent_time = round(time() * 1000) - quality_start_time
178181
if quality_spent_time > 8000:
179182
log.warning(

chia/plotting/prover.py

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
from chia_rs.sized_ints import uint8
99
from chiapos import DiskProver
1010

11+
from chia.types.blockchain_format.proof_of_space import quality_for_partial_proof
12+
1113
if TYPE_CHECKING:
1214
from chiapos import DiskProver
1315

@@ -27,8 +29,13 @@ def get_compression_level(self) -> uint8: ...
2729
def get_version(self) -> PlotVersion: ...
2830
def __bytes__(self) -> bytes: ...
2931
def get_id(self) -> bytes32: ...
30-
def get_qualities_for_challenge(self, challenge: bytes32) -> list[bytes32]: ...
31-
def get_partial_proofs_for_challenge(self, challenge: bytes32) -> list[bytes]: ...
32+
def get_qualities_for_challenge(self, challenge: bytes32, plot_strength: uint8) -> list[bytes32]: ...
33+
34+
# this is only supported by v2 plots
35+
def get_partial_proofs_for_challenge(self, challenge: bytes32, plot_strength: uint8) -> list[bytes]: ...
36+
37+
# this is only supported by v1 plots. v2 plots first get the partial proof
38+
# and turn it into a full proof by calling solve_proof(), or pass it to the solver service
3239
def get_full_proof(self, challenge: bytes32, index: int, parallel_read: bool = True) -> bytes: ...
3340

3441
@classmethod
@@ -56,7 +63,8 @@ def get_memo(self) -> bytes:
5663
raise NotImplementedError("V2 plot format is not yet implemented")
5764

5865
def get_compression_level(self) -> uint8:
59-
raise NotImplementedError("V2 plot format does not support compression level")
66+
# v2 plots are never compressed
67+
return uint8(0)
6068

6169
def get_version(self) -> PlotVersion:
6270
return PlotVersion.V2
@@ -69,17 +77,18 @@ def get_id(self) -> bytes32:
6977
# TODO: Extract plot ID from V2 plot file
7078
raise NotImplementedError("V2 plot format is not yet implemented")
7179

72-
def get_qualities_for_challenge(self, challenge: bytes32) -> list[bytes32]:
80+
def get_partial_proofs_for_challenge(self, challenge: bytes, plot_strength: uint8) -> list[bytes]:
7381
# TODO: todo_v2_plots Implement plot quality lookup
7482
raise NotImplementedError("V2 plot format is not yet implemented")
7583

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)
78-
raise NotImplementedError("V2 plot format is not yet implemented")
84+
def get_qualities_for_challenge(self, challenge: bytes32, plot_strength: uint8) -> list[bytes32]:
85+
return [
86+
quality_for_partial_proof(partial, challenge)
87+
for partial in self.get_partial_proofs_for_challenge(challenge, plot_strength)
88+
]
7989

8090
def get_full_proof(self, challenge: bytes32, index: int, parallel_read: bool = True) -> bytes:
81-
# TODO: todo_v2_plots Implement plot proof generation
82-
raise NotImplementedError("V2 plot format require solver to get full proof")
91+
raise AssertionError("V2 plots don't have full proofs")
8392

8493
@classmethod
8594
def from_bytes(cls, data: bytes) -> V2Prover:
@@ -117,11 +126,11 @@ def __bytes__(self) -> bytes:
117126
def get_id(self) -> bytes32:
118127
return bytes32(self._disk_prover.get_id())
119128

120-
def get_qualities_for_challenge(self, challenge: bytes32) -> list[bytes32]:
121-
return [bytes32(quality) for quality in self._disk_prover.get_qualities_for_challenge(challenge)]
129+
def get_partial_proofs_for_challenge(self, challenge: bytes32, plot_strength: uint8) -> list[bytes]:
130+
raise AssertionError("V1 plot format doesn't use partial proofs")
122131

123-
def get_partial_proofs_for_challenge(self, challenge: bytes32) -> list[bytes]:
124-
raise NotImplementedError("V1 does not implement quality chains, only qualities")
132+
def get_qualities_for_challenge(self, challenge: bytes32, plot_strength: uint8) -> list[bytes32]:
133+
return [bytes32(quality) for quality in self._disk_prover.get_qualities_for_challenge(challenge)]
125134

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

chia/simulator/block_tools.py

Lines changed: 45 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@
8989
from chia.types.blockchain_format.coin import Coin
9090
from chia.types.blockchain_format.program import DEFAULT_FLAGS, INFINITE_COST, Program, _run, run_with_cost
9191
from chia.types.blockchain_format.proof_of_space import (
92+
calculate_plot_strength,
9293
calculate_pos_challenge,
9394
calculate_prefix_bits,
9495
generate_plot_public_key,
@@ -1500,51 +1501,57 @@ def get_pospaces_for_challenge(
15001501
found_proofs: list[tuple[uint64, ProofOfSpace]] = []
15011502
rng = random.Random()
15021503
rng.seed(seed)
1504+
1505+
plot_strength = calculate_plot_strength(constants, height)
15031506
for plot_info in self.plot_manager.plots.values():
15041507
plot_id: bytes32 = plot_info.prover.get_id()
15051508
if force_plot_id is not None and plot_id != force_plot_id:
15061509
continue
15071510
prefix_bits = calculate_prefix_bits(constants, height, plot_info.prover.get_size())
1508-
if passes_plot_filter(prefix_bits, plot_id, challenge_hash, signage_point):
1509-
new_challenge: bytes32 = calculate_pos_challenge(plot_id, challenge_hash, signage_point)
1510-
qualities = plot_info.prover.get_qualities_for_challenge(new_challenge)
1511+
if not passes_plot_filter(prefix_bits, plot_id, challenge_hash, signage_point):
1512+
continue
15111513

1512-
for proof_index, quality_str in enumerate(qualities):
1513-
required_iters = calculate_iterations_quality(
1514-
constants,
1515-
quality_str,
1516-
plot_info.prover.get_size(),
1517-
difficulty,
1518-
signage_point,
1519-
sub_slot_iters,
1520-
prev_transaction_b_height,
1521-
)
1522-
if required_iters < calculate_sp_interval_iters(constants, sub_slot_iters):
1523-
proof_xs: bytes = plot_info.prover.get_full_proof(new_challenge, proof_index)
1514+
new_challenge: bytes32 = calculate_pos_challenge(plot_id, challenge_hash, signage_point)
1515+
qualities = plot_info.prover.get_qualities_for_challenge(new_challenge, plot_strength)
15241516

1525-
# Look up local_sk from plot to save locked memory
1526-
(
1527-
pool_public_key_or_puzzle_hash,
1528-
farmer_public_key,
1529-
local_master_sk,
1530-
) = parse_plot_info(plot_info.prover.get_memo())
1531-
local_sk = master_sk_to_local_sk(local_master_sk)
1532-
1533-
if isinstance(pool_public_key_or_puzzle_hash, G1Element):
1534-
include_taproot = False
1535-
else:
1536-
assert isinstance(pool_public_key_or_puzzle_hash, bytes32)
1537-
include_taproot = True
1538-
plot_pk = generate_plot_public_key(local_sk.get_g1(), farmer_public_key, include_taproot)
1539-
proof_of_space: ProofOfSpace = make_pos(
1540-
new_challenge,
1541-
plot_info.pool_public_key,
1542-
plot_info.pool_contract_puzzle_hash,
1543-
plot_pk,
1544-
plot_info.prover.get_size(),
1545-
proof_xs,
1546-
)
1547-
found_proofs.append((required_iters, proof_of_space))
1517+
for proof_index, quality_str in enumerate(qualities):
1518+
required_iters = calculate_iterations_quality(
1519+
constants,
1520+
quality_str,
1521+
plot_info.prover.get_size(),
1522+
difficulty,
1523+
signage_point,
1524+
sub_slot_iters,
1525+
prev_transaction_b_height,
1526+
)
1527+
if required_iters >= calculate_sp_interval_iters(constants, sub_slot_iters):
1528+
continue
1529+
1530+
proof_xs: bytes = plot_info.prover.get_full_proof(new_challenge, proof_index)
1531+
1532+
# Look up local_sk from plot to save locked memory
1533+
(
1534+
pool_public_key_or_puzzle_hash,
1535+
farmer_public_key,
1536+
local_master_sk,
1537+
) = parse_plot_info(plot_info.prover.get_memo())
1538+
local_sk = master_sk_to_local_sk(local_master_sk)
1539+
1540+
if isinstance(pool_public_key_or_puzzle_hash, G1Element):
1541+
include_taproot = False
1542+
else:
1543+
assert isinstance(pool_public_key_or_puzzle_hash, bytes32)
1544+
include_taproot = True
1545+
plot_pk = generate_plot_public_key(local_sk.get_g1(), farmer_public_key, include_taproot)
1546+
proof_of_space: ProofOfSpace = make_pos(
1547+
new_challenge,
1548+
plot_info.pool_public_key,
1549+
plot_info.pool_contract_puzzle_hash,
1550+
plot_pk,
1551+
plot_info.prover.get_size(),
1552+
proof_xs,
1553+
)
1554+
found_proofs.append((required_iters, proof_of_space))
15481555
random_sample = found_proofs
15491556
if len(found_proofs) >= 1:
15501557
if rng.random() < 0.1:

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, 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+
plot_strength = calculate_plot_strength(constants, height)
146+
return validate_proof_v2(plot_id, plot_size.size_v2, 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_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)