Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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(
AssertionError, 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, required_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 AssertionError("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, required_plot_strength: uint8) -> list[bytes]:
# TODO: todo_v2_plots Implement plot partial proof 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, required_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