Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions chia/_tests/core/custom_types/test_proof_of_space.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@
from chia._tests.util.misc import Marks, datacases
from chia.consensus.default_constants import DEFAULT_CONSTANTS
from chia.types.blockchain_format.proof_of_space import (
calculate_plot_difficulty,
calculate_prefix_bits,
calculate_required_plot_strength,
check_plot_size,
make_pos,
passes_plot_filter,
Expand Down Expand Up @@ -201,7 +201,7 @@ def test_verify_and_get_quality_string_v2(caplog: pytest.LogCaptureFixture, case


@pytest.mark.parametrize(
"height, difficulty",
"height, strength",
[
(0, 2),
(DEFAULT_CONSTANTS.HARD_FORK_HEIGHT, 2),
Expand All @@ -219,8 +219,8 @@ def test_verify_and_get_quality_string_v2(caplog: pytest.LogCaptureFixture, case
(DEFAULT_CONSTANTS.PLOT_DIFFICULTY_8_HEIGHT + 1000000, 8),
],
)
def test_calculate_plot_difficulty(height: uint32, difficulty: uint8) -> None:
assert calculate_plot_difficulty(DEFAULT_CONSTANTS, height) == difficulty
def test_calculate_plot_strength(height: uint32, strength: uint8) -> None:
assert calculate_required_plot_strength(DEFAULT_CONSTANTS, height) == strength


@pytest.mark.parametrize(
Expand Down
10 changes: 6 additions & 4 deletions chia/_tests/plotting/test_prover.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

import pytest
from chia_rs.sized_bytes import bytes32
from chia_rs.sized_ints import uint8

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

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

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

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

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

def test_v2_prover_get_full_proof_raises_error(self) -> None:
Expand Down
6 changes: 0 additions & 6 deletions chia/consensus/pos_quality.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from __future__ import annotations

from chia_rs import PlotSize
from chia_rs.sized_bytes import bytes32
from chia_rs.sized_ints import uint64

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


def quality_for_partial_proof(partial_proof: bytes, challenge: bytes32) -> bytes32:
# TODO todo_v2_plots real implementaion
return challenge


def _expected_plot_size(size: PlotSize) -> uint64:
"""
Given the plot size parameter k (which is between 32 and 59), computes the
Expand Down
11 changes: 9 additions & 2 deletions chia/harvester/harvester_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
from chia_rs.sized_bytes import bytes32
from chia_rs.sized_ints import uint32, uint64

from chia.consensus.pos_quality import quality_for_partial_proof
from chia.consensus.pot_iterations import (
calculate_iterations_quality,
calculate_sp_interval_iters,
Expand All @@ -29,9 +28,11 @@
from chia.types.blockchain_format.proof_of_space import (
calculate_pos_challenge,
calculate_prefix_bits,
calculate_required_plot_strength,
generate_plot_public_key,
make_pos,
passes_plot_filter,
quality_for_partial_proof,
)
from chia.wallet.derive_keys import master_sk_to_local_sk

Expand Down Expand Up @@ -152,6 +153,10 @@ async def new_signage_point_harvester(
start = time.monotonic()
assert len(new_challenge.challenge_hash) == 32

required_plot_strength = calculate_required_plot_strength(
self.harvester.constants, new_challenge.last_tx_height
)

loop = asyncio.get_running_loop()

def blocking_lookup_v2_partial_proofs(filename: Path, plot_info: PlotInfo) -> Optional[PartialProofsData]:
Expand All @@ -163,7 +168,9 @@ def blocking_lookup_v2_partial_proofs(filename: Path, plot_info: PlotInfo) -> Op
new_challenge.challenge_hash,
new_challenge.sp_hash,
)
partial_proofs = plot_info.prover.get_partial_proofs_for_challenge(sp_challenge_hash)
partial_proofs = plot_info.prover.get_partial_proofs_for_challenge(
sp_challenge_hash, required_plot_strength
)

# If no partial proofs are found, return None
if len(partial_proofs) == 0:
Expand Down
21 changes: 13 additions & 8 deletions chia/plotting/prover.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,12 @@ def get_version(self) -> PlotVersion: ...
def __bytes__(self) -> bytes: ...
def get_id(self) -> bytes32: ...
def get_qualities_for_challenge(self, challenge: bytes32) -> list[bytes32]: ...
def get_partial_proofs_for_challenge(self, challenge: bytes32) -> list[bytes]: ...

# this is only supported by v2 plots
def get_partial_proofs_for_challenge(self, challenge: bytes32, plot_strength: uint8) -> list[bytes]: ...

# this is only supported by v1 plots. v2 plots first get the partial proof
# and turn it into a full proof by calling solve_proof(), or pass it to the solver service
def get_full_proof(self, challenge: bytes32, index: int, parallel_read: bool = True) -> bytes: ...

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

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

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

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

def get_partial_proofs_for_challenge(self, challenge: bytes32) -> list[bytes]:
# TODO: todo_v2_plots Implement quality chain lookup (16 * k bits blobs)
def get_partial_proofs_for_challenge(self, challenge: bytes, plot_strength: uint8) -> list[bytes]:
# TODO: todo_v2_plots Implement plot quality lookup
raise NotImplementedError("V2 plot format is not yet implemented")

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

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

def get_full_proof(self, challenge: bytes32, index: int, parallel_read: bool = True) -> bytes:
return bytes(self._disk_prover.get_full_proof(challenge, index, parallel_read))
Expand Down
38 changes: 34 additions & 4 deletions chia/simulator/block_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from dataclasses import dataclass, replace
from pathlib import Path
from random import Random
from typing import Any, Callable, Optional
from typing import Any, Callable, Optional, Union

import anyio
from chia_puzzles_py.programs import CHIALISP_DESERIALISATION, ROM_BOOTSTRAP_GENERATOR
Expand Down Expand Up @@ -64,6 +64,7 @@
from chia.full_node.bundle_tools import simple_solution_generator, simple_solution_generator_backrefs
from chia.plotting.create_plots import PlotKeys, create_plots
from chia.plotting.manager import PlotManager
from chia.plotting.prover import PlotVersion
from chia.plotting.util import (
Params,
PlotRefreshEvents,
Expand Down Expand Up @@ -91,10 +92,13 @@
from chia.types.blockchain_format.proof_of_space import (
calculate_pos_challenge,
calculate_prefix_bits,
calculate_required_plot_strength,
generate_plot_public_key,
generate_taproot_sk,
make_pos,
passes_plot_filter,
quality_for_partial_proof,
solve_proof,
)
from chia.types.blockchain_format.serialized_program import SerializedProgram
from chia.types.blockchain_format.vdf import VDFInfo, VDFProof
Expand Down Expand Up @@ -1500,6 +1504,9 @@ def get_pospaces_for_challenge(
found_proofs: list[tuple[uint64, ProofOfSpace]] = []
rng = random.Random()
rng.seed(seed)

required_plot_strength = calculate_required_plot_strength(constants, prev_transaction_b_height)

for plot_info in self.plot_manager.plots.values():
plot_id: bytes32 = plot_info.prover.get_id()
if force_plot_id is not None and plot_id != force_plot_id:
Expand All @@ -1508,10 +1515,29 @@ def get_pospaces_for_challenge(
if not passes_plot_filter(prefix_bits, plot_id, challenge_hash, signage_point):
continue

# v2 plots aren't valid until after the hard fork
if (
prev_transaction_b_height < constants.HARD_FORK2_HEIGHT
and plot_info.prover.get_version() == PlotVersion.V2
):
continue

new_challenge: bytes32 = calculate_pos_challenge(plot_id, challenge_hash, signage_point)
qualities = plot_info.prover.get_qualities_for_challenge(new_challenge)

for proof_index, quality_str in enumerate(qualities):
# these are either qualities (v1) or partial proofs (v2)
proofs: Sequence[Union[bytes32, bytes]]
v = plot_info.prover.get_version()
if v == PlotVersion.V1:
proofs = plot_info.prover.get_qualities_for_challenge(new_challenge)
else:
proofs = plot_info.prover.get_partial_proofs_for_challenge(new_challenge, required_plot_strength)

for proof_index, proof in enumerate(proofs):
if v == PlotVersion.V2:
quality_str = quality_for_partial_proof(proof, new_challenge)
elif v == PlotVersion.V1:
quality_str = bytes32(proof)

required_iters = calculate_iterations_quality(
constants,
quality_str,
Expand All @@ -1524,7 +1550,11 @@ def get_pospaces_for_challenge(
if required_iters >= calculate_sp_interval_iters(constants, sub_slot_iters):
continue

proof_xs: bytes = plot_info.prover.get_full_proof(new_challenge, proof_index)
proof_xs: bytes
if v == PlotVersion.V1:
proof_xs = plot_info.prover.get_full_proof(new_challenge, proof_index)
else:
proof_xs = solve_proof(proof)

# Look up local_sk from plot to save locked memory
(
Expand Down
6 changes: 5 additions & 1 deletion chia/solver/solver.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from chia.rpc.rpc_server import StateChangedProtocol, default_get_connections
from chia.server.server import ChiaServer
from chia.server.ws_connection import WSChiaConnection
from chia.types.blockchain_format.proof_of_space import solve_proof

log = logging.getLogger(__name__)

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

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

def get_connections(self, request_node_type: Optional[NodeType]) -> list[dict[str, Any]]:
Expand Down
36 changes: 25 additions & 11 deletions chia/types/blockchain_format/proof_of_space.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,28 @@

log = logging.getLogger(__name__)

# These are temporary stubs for chiapos2, that we build against until it's ready to be integrated.


# returns quality string for v2 plot, or None if invalid
def validate_proof_v2(
plot_id: bytes32, size: uint8, required_plot_strength: uint8, challenge: bytes32, proof: bytes
) -> Optional[bytes32]:
# TODO: todo_v2_plots call into new chiapos library
raise NotImplementedError


# this is compute intensive, solving a partial proof returning a full proof
def solve_proof(partial_proof: bytes) -> bytes:
# TODO: todo_v2_plots call into new chiapos library
raise NotImplementedError


# given a partial proof, computes the quality. This is used to compute required iters.
def quality_for_partial_proof(partial_proof: bytes, challenge: bytes32) -> bytes32:
# TODO: todo_v2_plots call into new chiapos library
return std_hash(partial_proof + challenge)


def make_pos(
challenge: bytes32,
Expand Down Expand Up @@ -49,14 +71,6 @@ def get_plot_id(pos: ProofOfSpace) -> bytes32:
return calculate_plot_id_pk(pos.pool_public_key, pos.plot_public_key)


# returns quality string for v2 plot, or None if invalid
def validate_proof_v2(
plot_id: bytes32, size: uint8, difficulty: uint8, challenge: bytes32, proof: bytes
) -> Optional[bytes32]:
# TODO: todo_v2_plots call into new chiapos library
raise NotImplementedError


def check_plot_size(constants: ConsensusConstants, ps: PlotSize) -> bool:
size_v1 = ps.size_v1
if size_v1 is not None:
Expand Down Expand Up @@ -128,8 +142,8 @@ def verify_and_get_quality_string(
# === V2 plots ===
assert plot_size.size_v2 is not None

plot_difficulty = calculate_plot_difficulty(constants, height)
return validate_proof_v2(plot_id, plot_size.size_v2, plot_difficulty, pos.challenge, bytes(pos.proof))
required_plot_strength = calculate_required_plot_strength(constants, height)
return validate_proof_v2(plot_id, plot_size.size_v2, required_plot_strength, pos.challenge, bytes(pos.proof))


def passes_plot_filter(
Expand Down Expand Up @@ -167,7 +181,7 @@ def calculate_prefix_bits(constants: ConsensusConstants, height: uint32, plot_si
return max(0, prefix_bits)


def calculate_plot_difficulty(constants: ConsensusConstants, height: uint32) -> uint8:
def calculate_required_plot_strength(constants: ConsensusConstants, height: uint32) -> uint8:
if height < constants.PLOT_DIFFICULTY_4_HEIGHT:
return constants.PLOT_DIFFICULTY_INITIAL
if height < constants.PLOT_DIFFICULTY_5_HEIGHT:
Expand Down
Loading