147 lines
5.9 KiB
Python
147 lines
5.9 KiB
Python
import logging
|
|
from collections import Counter
|
|
from pathlib import Path
|
|
from typing import Dict, List
|
|
|
|
from blspy import G1Element
|
|
from chiapos import Verifier
|
|
|
|
from chia.plotting.plot_tools import find_duplicate_plot_IDs, get_plot_filenames, load_plots, parse_plot_info
|
|
from chia.util.config import load_config
|
|
from chia.util.hash import std_hash
|
|
from chia.util.keychain import Keychain
|
|
from chia.wallet.derive_keys import master_sk_to_farmer_sk, master_sk_to_local_sk
|
|
|
|
log = logging.getLogger(__name__)
|
|
|
|
|
|
def check_plots(root_path, num, challenge_start, grep_string, list_duplicates, debug_show_memo):
|
|
config = load_config(root_path, "config.yaml")
|
|
if num is not None:
|
|
if num == 0:
|
|
log.warning("Not opening plot files")
|
|
else:
|
|
if num < 5:
|
|
log.warning(f"{num} challenges is too low, setting it to the minimum of 5")
|
|
num = 5
|
|
if num < 30:
|
|
log.warning("Use 30 challenges (our default) for balance of speed and accurate results")
|
|
else:
|
|
num = 30
|
|
|
|
if challenge_start is not None:
|
|
num_start = challenge_start
|
|
num_end = num_start + num
|
|
else:
|
|
num_start = 0
|
|
num_end = num
|
|
challenges = num_end - num_start
|
|
|
|
if list_duplicates:
|
|
log.warning("Checking for duplicate Plot IDs")
|
|
log.info("Plot filenames expected to end with -[64 char plot ID].plot")
|
|
|
|
show_memo: bool = debug_show_memo
|
|
|
|
if list_duplicates:
|
|
plot_filenames: Dict[Path, List[Path]] = get_plot_filenames(config["harvester"])
|
|
all_filenames: List[Path] = []
|
|
for paths in plot_filenames.values():
|
|
all_filenames += paths
|
|
find_duplicate_plot_IDs(all_filenames)
|
|
|
|
if num == 0:
|
|
return None
|
|
|
|
v = Verifier()
|
|
log.info("Loading plots in config.yaml using plot_tools loading code\n")
|
|
kc: Keychain = Keychain()
|
|
pks = [master_sk_to_farmer_sk(sk).get_g1() for sk, _ in kc.get_all_private_keys()]
|
|
pool_public_keys = [G1Element.from_bytes(bytes.fromhex(pk)) for pk in config["farmer"]["pool_public_keys"]]
|
|
_, provers, failed_to_open_filenames, no_key_filenames = load_plots(
|
|
{},
|
|
{},
|
|
pks,
|
|
pool_public_keys,
|
|
grep_string,
|
|
show_memo,
|
|
root_path,
|
|
open_no_key_filenames=True,
|
|
)
|
|
if len(provers) > 0:
|
|
log.info("")
|
|
log.info("")
|
|
log.info(f"Starting to test each plot with {num} challenges each\n")
|
|
total_good_plots: Counter = Counter()
|
|
total_bad_plots = 0
|
|
total_size = 0
|
|
bad_plots_list: List[Path] = []
|
|
|
|
for plot_path, plot_info in provers.items():
|
|
pr = plot_info.prover
|
|
log.info(f"Testing plot {plot_path} k={pr.get_size()}")
|
|
log.info(f"\tPool public key: {plot_info.pool_public_key}")
|
|
|
|
# Look up local_sk from plot to save locked memory
|
|
(
|
|
pool_public_key_or_puzzle_hash,
|
|
farmer_public_key,
|
|
local_master_sk,
|
|
) = parse_plot_info(pr.get_memo())
|
|
local_sk = master_sk_to_local_sk(local_master_sk)
|
|
log.info(f"\tFarmer public key: {farmer_public_key}")
|
|
log.info(f"\tLocal sk: {local_sk}")
|
|
total_proofs = 0
|
|
caught_exception: bool = False
|
|
for i in range(num_start, num_end):
|
|
challenge = std_hash(i.to_bytes(32, "big"))
|
|
# Some plot errors cause get_qualities_for_challenge to throw a RuntimeError
|
|
try:
|
|
for index, quality_str in enumerate(pr.get_qualities_for_challenge(challenge)):
|
|
# Other plot errors cause get_full_proof or validate_proof to throw an AssertionError
|
|
try:
|
|
proof = pr.get_full_proof(challenge, index)
|
|
total_proofs += 1
|
|
ver_quality_str = v.validate_proof(pr.get_id(), pr.get_size(), challenge, proof)
|
|
assert quality_str == ver_quality_str
|
|
except AssertionError as e:
|
|
log.error(f"{type(e)}: {e} error in proving/verifying for plot {plot_path}")
|
|
caught_exception = True
|
|
except KeyboardInterrupt:
|
|
log.warning("Interrupted, closing")
|
|
return None
|
|
except SystemExit:
|
|
log.warning("System is shutting down.")
|
|
return None
|
|
except Exception as e:
|
|
log.error(f"{type(e)}: {e} error in getting challenge qualities for plot {plot_path}")
|
|
caught_exception = True
|
|
if caught_exception is True:
|
|
break
|
|
if total_proofs > 0 and caught_exception is False:
|
|
log.info(f"\tProofs {total_proofs} / {challenges}, {round(total_proofs/float(challenges), 4)}")
|
|
total_good_plots[pr.get_size()] += 1
|
|
total_size += plot_path.stat().st_size
|
|
else:
|
|
total_bad_plots += 1
|
|
log.error(f"\tProofs {total_proofs} / {challenges}, {round(total_proofs/float(challenges), 4)}")
|
|
bad_plots_list.append(plot_path)
|
|
log.info("")
|
|
log.info("")
|
|
log.info("Summary")
|
|
total_plots: int = sum(list(total_good_plots.values()))
|
|
log.info(f"Found {total_plots} valid plots, total size {total_size / (1024 * 1024 * 1024 * 1024):.5f} TiB")
|
|
for (k, count) in sorted(dict(total_good_plots).items()):
|
|
log.info(f"{count} plots of size {k}")
|
|
grand_total_bad = total_bad_plots + len(failed_to_open_filenames)
|
|
if grand_total_bad > 0:
|
|
log.warning(f"{grand_total_bad} invalid plots found:")
|
|
for bad_plot_path in bad_plots_list:
|
|
log.warning(f"{bad_plot_path}")
|
|
if len(no_key_filenames) > 0:
|
|
log.warning(
|
|
f"There are {len(no_key_filenames)} plots with a farmer or pool public key that "
|
|
f"is not on this machine. The farmer private key must be in the keychain in order to "
|
|
f"farm them, use 'chia keys' to transfer keys. The pool public keys must be in the config.yaml"
|
|
)
|