Weight proof optimizations (#1221)

* sub epoch samples optimizations, tests passing

* refactor

* fix sample validation

* fix indentation

* refactor

* dynamic recent chain

* logs

* revert dynamic recent chain

* dynamic recent chain

* tidy

* lint

* fix merge
This commit is contained in:
Almog De Paz 2021-03-11 00:53:42 +02:00 committed by GitHub
parent e50d14b0a9
commit 255bbb14af
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 228 additions and 128 deletions

View File

@ -95,15 +95,19 @@ class WeightProofHandler:
if recent_chain is None:
return None
weight_to_check = _get_weights_for_sampling(random.Random(tip), tip_rec.weight, recent_chain)
summary_heights = self.blockchain.get_ses_heights()
# use second to last ses as seed
seed = self.blockchain.get_ses(summary_heights[-2]).get_hash()
rng = random.Random(seed)
weight_to_check = _get_weights_for_sampling(rng, tip_rec.weight, recent_chain)
prev_ses_block = await self.blockchain.get_block_record_from_db(self.blockchain.height_to_hash(uint32(0)))
if prev_ses_block is None:
return None
sub_epoch_n = uint32(0)
sample_n = uint32(0)
summary_heights = self.blockchain.get_ses_heights()
for idx, ses_height in enumerate(summary_heights):
for sub_epoch_n, ses_height in enumerate(summary_heights):
if ses_height > tip_rec.height:
break
# next sub block
@ -112,11 +116,11 @@ class WeightProofHandler:
log.error("error while building proof")
return None
log.debug(f"handle sub epoch summary {idx} at height: {ses_height} weight: {ses_block.weight}")
log.debug(f"handle sub epoch summary {sub_epoch_n} at height: {ses_height} weight: {ses_block.weight}")
sub_epoch_data.append(_create_sub_epoch_data(ses_block.sub_epoch_summary_included))
# if we have enough sub_epoch samples, dont sample
if sub_epoch_n >= self.MAX_SAMPLES:
if sample_n >= self.MAX_SAMPLES:
log.debug("reached sampled sub epoch cap")
continue
@ -124,14 +128,19 @@ class WeightProofHandler:
if _sample_sub_epoch(prev_ses_block.weight, ses_block.weight, weight_to_check): # type: ignore
segments = await self.blockchain.get_sub_epoch_challenge_segments(ses_block.height)
if segments is None:
segments = await self.__create_sub_epoch_segments(ses_block, prev_ses_block, uint32(idx))
segments = await self.__create_sub_epoch_segments(ses_block, prev_ses_block, uint32(sub_epoch_n))
if segments is None:
log.error(f"failed while building segments for sub epoch {idx}, ses height {ses_height} ")
log.error(
f"failed while building segments for sub epoch {sub_epoch_n}, ses height {ses_height} "
)
return None
await self.blockchain.persist_sub_epoch_challenge_segments(ses_block.height, segments)
log.debug(f"sub epoch {sub_epoch_n} has {len(segments)} segments")
sub_epoch_segments.extend(segments)
sub_epoch_n = uint32(sub_epoch_n + 1)
# choose segment
sampled_seg_index = rng.choice(range(len(segments)))
log.debug(f"sub epoch {sub_epoch_n} sample index {sample_n} sampled segment {sampled_seg_index} ")
# compress other segments by deleting redundant values
sub_epoch_segments.extend(compress_segments(sampled_seg_index, segments))
sample_n = uint32(sample_n + 1)
prev_ses_block = ses_block
log.debug(f"sub_epochs: {len(sub_epoch_data)}")
return WeightProof(sub_epoch_data, sub_epoch_segments, recent_chain)
@ -294,7 +303,7 @@ class WeightProofHandler:
blocks: Dict[bytes32, BlockRecord],
first_in_sub_epoch: bool,
) -> Tuple[Optional[List[SubSlotData]], Optional[VDFInfo]]:
# combine cc vdfs of all reward blocks from the start of the sub slot to end
# append cc vdfs of all reward blocks from the start of the sub slot to end
header_block_sub_rec = blocks[header_block.header_hash]
# find slot start
curr_sub_rec = header_block_sub_rec
@ -326,7 +335,22 @@ class WeightProofHandler:
curr_icc_info = sub_slot.infused_challenge_chain.infused_challenge_chain_end_of_slot_vdf
sub_slots_data.append(handle_finished_slots(sub_slot, curr_icc_info))
tmp_sub_slots_data = []
tmp_sub_slots_data.append(self.handle_block_vdfs(curr, blocks))
ssd = SubSlotData(
None,
None,
None,
None,
None,
curr.reward_chain_block.signage_point_index,
None,
None,
None,
None,
curr.reward_chain_block.challenge_chain_ip_vdf,
curr.reward_chain_block.infused_challenge_chain_ip_vdf,
curr.total_iters,
)
tmp_sub_slots_data.append(ssd)
curr = header_blocks[self.blockchain.height_to_hash(uint32(curr.height + 1))]
if len(tmp_sub_slots_data) > 0:
@ -375,8 +399,6 @@ class WeightProofHandler:
tmp_sub_slots_data.append(self.handle_block_vdfs(curr, blocks))
curr = header_blocks[self.blockchain.height_to_hash(uint32(curr.height + 1))]
if len(tmp_sub_slots_data) > 0:
sub_slots_data.extend(tmp_sub_slots_data)
log.debug(f"slot end vdf end height {curr.height} slots {len(sub_slots_data)} ")
return sub_slots_data, curr.height
@ -440,11 +462,13 @@ class WeightProofHandler:
return False, uint32(0)
constants, summary_bytes, wp_bytes = vars_to_bytes(self.constants, summaries, weight_proof)
log.info("validate sub epoch challenge segments")
if not self.validate_sub_epoch_sampling(sub_epoch_weight_list, weight_proof):
seed = summaries[-2].get_hash()
rng = random.Random(seed)
if not validate_sub_epoch_sampling(rng, sub_epoch_weight_list, weight_proof):
log.error("failed weight proof sub epoch sample validation")
return False, uint32(0)
if not _validate_segments(constants, wp_bytes, summary_bytes):
if not _validate_sub_epoch_segments(constants, rng, wp_bytes, summary_bytes):
return False, uint32(0)
log.info("validate weight proof recent blocks")
if not _validate_recent_blocks(constants, wp_bytes, summary_bytes):
@ -465,14 +489,16 @@ class WeightProofHandler:
log.error("weight proof failed sub epoch data validation")
return False, uint32(0)
if not self.validate_sub_epoch_sampling(sub_epoch_weight_list, weight_proof):
seed = summaries[-2].get_hash()
rng = random.Random(seed)
if not validate_sub_epoch_sampling(rng, sub_epoch_weight_list, weight_proof):
log.error("failed weight proof sub epoch sample validation")
return False, uint32(0)
executor = ProcessPoolExecutor(1)
constants, summary_bytes, wp_bytes = vars_to_bytes(self.constants, summaries, weight_proof)
segment_validation_task = asyncio.get_running_loop().run_in_executor(
executor, _validate_segments, constants, wp_bytes, summary_bytes
executor, _validate_sub_epoch_segments, constants, rng, wp_bytes, summary_bytes
)
recent_blocks_validation_task = asyncio.get_running_loop().run_in_executor(
@ -493,27 +519,6 @@ class WeightProofHandler:
return True, self.get_fork_point(summaries)
def validate_sub_epoch_sampling(self, sub_epoch_weight_list, weight_proof):
tip = weight_proof.recent_chain_data[-1]
weight_to_check = _get_weights_for_sampling(
random.Random(tip.header_hash), tip.weight, weight_proof.recent_chain_data
)
sampled_sub_epochs: dict[int, bool] = {}
for idx in range(1, len(sub_epoch_weight_list)):
if _sample_sub_epoch(sub_epoch_weight_list[idx - 1], sub_epoch_weight_list[idx], weight_to_check):
sampled_sub_epochs[idx - 1] = True
if len(sampled_sub_epochs) == WeightProofHandler.MAX_SAMPLES:
break
curr_sub_epoch_n = -1
for sub_epoch_segment in weight_proof.sub_epoch_segments:
if curr_sub_epoch_n < sub_epoch_segment.sub_epoch_n:
if sub_epoch_segment.sub_epoch_n in sampled_sub_epochs:
del sampled_sub_epochs[sub_epoch_segment.sub_epoch_n]
curr_sub_epoch_n = sub_epoch_segment.sub_epoch_n
if len(sampled_sub_epochs) > 0:
return False
return True
def get_fork_point(self, received_summaries: List[SubEpochSummary]) -> uint32:
# iterate through sub epoch summaries to find fork point
fork_point_index = 0
@ -652,6 +657,68 @@ def handle_finished_slots(end_of_slot: EndOfSubSlotBundle, icc_end_of_slot_info)
)
def handle_end_of_slot(
sub_slot: EndOfSubSlotBundle,
eos_vdf_iters: uint64,
):
assert sub_slot.infused_challenge_chain
assert sub_slot.proofs.infused_challenge_chain_slot_proof
if sub_slot.proofs.infused_challenge_chain_slot_proof.normalized_to_identity:
icc_info = sub_slot.infused_challenge_chain.infused_challenge_chain_end_of_slot_vdf
else:
icc_info = VDFInfo(
sub_slot.infused_challenge_chain.infused_challenge_chain_end_of_slot_vdf.challenge,
eos_vdf_iters,
sub_slot.infused_challenge_chain.infused_challenge_chain_end_of_slot_vdf.output,
)
if sub_slot.proofs.challenge_chain_slot_proof.normalized_to_identity:
cc_info = sub_slot.challenge_chain.challenge_chain_end_of_slot_vdf
else:
cc_info = VDFInfo(
sub_slot.challenge_chain.challenge_chain_end_of_slot_vdf.challenge,
eos_vdf_iters,
sub_slot.challenge_chain.challenge_chain_end_of_slot_vdf.output,
)
assert sub_slot.proofs.infused_challenge_chain_slot_proof is not None
return SubSlotData(
None,
None,
None,
None,
None,
None,
sub_slot.proofs.challenge_chain_slot_proof,
sub_slot.proofs.infused_challenge_chain_slot_proof,
cc_info,
icc_info,
None,
None,
None,
)
def compress_segments(full_segment_index, segments: List[SubEpochChallengeSegment]) -> List[SubEpochChallengeSegment]:
compressed_segments = []
compressed_segments.append(segments[0])
for idx, segment in enumerate(segments[1:]):
if idx != full_segment_index:
# remove all redundant values
segment = compress_segment(segment)
compressed_segments.append(segment)
return compressed_segments
def compress_segment(segment: SubEpochChallengeSegment) -> SubEpochChallengeSegment:
# find challenge slot
comp_seg = SubEpochChallengeSegment(segment.sub_epoch_n, [], segment.rc_slot_end_info)
for slot in segment.sub_slots:
comp_seg.sub_slots.append(slot)
if slot.is_challenge():
break
return segment
# wp validation methods
def _validate_sub_epoch_summaries(
constants: ConsensusConstants,
@ -670,7 +737,7 @@ def _validate_sub_epoch_summaries(
constants.DIFFICULTY_STARTING,
)
log.info(f"validating {len(summaries)} summaries")
log.info(f"validating {len(summaries)} sub epochs")
# validate weight
if not _validate_summaries_weight(constants, total, summaries, weight_proof):
@ -722,6 +789,8 @@ def _map_sub_epoch_summaries(
# add to dict
summaries.append(ses)
ses_hash = std_hash(ses)
# add last sub epoch weight
sub_epoch_weight_list.append(uint128(total_weight + curr_difficulty))
return summaries, total_weight, sub_epoch_weight_list
@ -738,8 +807,20 @@ def _validate_summaries_weight(constants: ConsensusConstants, sub_epoch_data_wei
return curr.reward_chain_block.weight == sub_epoch_data_weight
def _validate_segments(
def map_segments_by_sub_epoch(sub_epoch_segments) -> Dict[int, List[SubEpochChallengeSegment]]:
segments: Dict[int, List[SubEpochChallengeSegment]] = {}
curr_sub_epoch_n = -1
for idx, segment in enumerate(sub_epoch_segments):
if curr_sub_epoch_n < segment.sub_epoch_n:
curr_sub_epoch_n = segment.sub_epoch_n
segments[curr_sub_epoch_n] = []
segments[curr_sub_epoch_n].append(segment)
return segments
def _validate_sub_epoch_segments(
constants_dict: Dict,
rng: random.Random,
weight_proof_bytes: bytes,
summaries_bytes: List[bytes],
):
@ -748,38 +829,35 @@ def _validate_segments(
total_blocks, total_ip_iters = 0, 0
total_slot_iters, total_slots = 0, 0
total_ip_iters = 0
curr_sub_epoch_n = -1
prev_ses: Optional[SubEpochSummary] = None
first_sub_epoch_segment = True
sampled_sub_epochs = 0
for idx, segment in enumerate(weight_proof.sub_epoch_segments):
curr_difficulty, curr_ssi = _get_curr_diff_ssi(constants, segment.sub_epoch_n, summaries)
if curr_sub_epoch_n < segment.sub_epoch_n:
log.info(f"validate sub epoch {segment.sub_epoch_n}")
sampled_sub_epochs += 1
first_sub_epoch_segment = True
# recreate RewardChainSubSlot for next ses rc_hash
if segment.sub_epoch_n > 0:
rc_sub_slot = __get_rc_sub_slot(constants, segment, summaries, curr_ssi)
prev_ses = summaries[segment.sub_epoch_n - 1]
rc_sub_slot_hash = rc_sub_slot.get_hash()
if not summaries[segment.sub_epoch_n].reward_chain_hash == rc_sub_slot_hash:
log.error(f"failed reward_chain_hash validation sub_epoch {segment.sub_epoch_n}")
return False
log.debug(f"validate segment {idx}")
valid_segment, ip_iters, slot_iters, slots = _validate_segment_slots(
constants, segment, curr_ssi, curr_difficulty, prev_ses, first_sub_epoch_segment
)
first_sub_epoch_segment = False
prev_ses = None
if not valid_segment:
log.error(f"failed to validate sub_epoch {segment.sub_epoch_n} segment {idx} slots")
segments_by_sub_epoch = map_segments_by_sub_epoch(weight_proof.sub_epoch_segments)
curr_ssi = constants.SUB_SLOT_ITERS_STARTING
for sub_epoch_n, segments in segments_by_sub_epoch.items():
prev_ssi = curr_ssi
curr_difficulty, curr_ssi = _get_curr_diff_ssi(constants, sub_epoch_n, summaries)
log.debug(f"validate sub epoch {sub_epoch_n}")
# recreate RewardChainSubSlot for next ses rc_hash
sampled_seg_index = rng.choice(range(len(segments)))
log.debug(f"sub epoch {sub_epoch_n} has {len(segments)} segments sampled segment {sampled_seg_index}")
if sub_epoch_n > 0:
rc_sub_slot = __get_rc_sub_slot(constants, segments[0], summaries, curr_ssi)
prev_ses = summaries[sub_epoch_n - 1]
rc_sub_slot_hash = rc_sub_slot.get_hash()
if not summaries[sub_epoch_n].reward_chain_hash == rc_sub_slot_hash:
log.error(f"failed reward_chain_hash validation sub_epoch {sub_epoch_n}")
return False
total_blocks += 1
total_slot_iters += slot_iters
total_slots += slots
total_ip_iters += ip_iters
curr_sub_epoch_n = segment.sub_epoch_n
for idx, segment in enumerate(segments):
valid_segment, ip_iters, slot_iters, slots = _validate_segment(
constants, segment, curr_ssi, prev_ssi, curr_difficulty, prev_ses, idx == 0, sampled_seg_index == idx
)
if not valid_segment:
log.error(f"failed to validate sub_epoch {segment.sub_epoch_n} segment {idx} slots")
return False
prev_ses = None
total_blocks += 1
total_slot_iters += slot_iters
total_slots += slots
total_ip_iters += ip_iters
avg_ip_iters = total_ip_iters / total_blocks
avg_slot_iters = total_slot_iters / total_slots
if avg_slot_iters / avg_ip_iters < float(constants.WEIGHT_PROOF_THRESHOLD):
@ -788,19 +866,21 @@ def _validate_segments(
return True
def _validate_segment_slots(
def _validate_segment(
constants: ConsensusConstants,
segment: SubEpochChallengeSegment,
curr_ssi: uint64,
prev_ssi: uint64,
curr_difficulty: uint64,
ses: Optional[SubEpochSummary],
first_segment_in_se: bool,
validate_sub_slots=False, # todo almog remove after bluebox integration
sampled: bool,
) -> Tuple[bool, int, int, int]:
ip_iters, slot_iters, slots = 0, 0, 0
after_challenge = False
sub_slots_since_prev = 0
for idx, sub_slot_data in enumerate(segment.sub_slots):
if sub_slot_data.is_challenge():
if sub_slot_data.is_challenge() and sampled:
after_challenge = True
required_iters = __validate_pospace(constants, segment, idx, curr_difficulty, ses, first_segment_in_se)
if required_iters is None:
@ -812,12 +892,17 @@ def _validate_segment_slots(
if not _validate_challenge_block_vdfs(constants, idx, segment.sub_slots, curr_ssi):
log.error(f"failed to validate challenge slot {idx} vdfs")
return False, uint64(0), uint64(0), uint64(0)
elif validate_sub_slots and after_challenge:
elif after_challenge and sampled:
if not _validate_sub_slot_data(constants, idx, segment.sub_slots, curr_ssi):
log.error(f"failed to validate sub slot data {idx} vdfs")
return False, uint64(0), uint64(0), uint64(0)
slot_iters = slot_iters + curr_ssi # type: ignore
slots = slots + uint64(1) # type: ignore
if not sub_slot_data.is_end_of_slot():
sub_slots_since_prev = 0
else:
sub_slots_since_prev += 1
slot_iters = slot_iters + curr_ssi # type: ignore
slots = slots + uint64(1) # type: ignore
log.debug(f"slot iters {slot_iters} slots {slots}")
return True, ip_iters, slot_iters, slots
@ -880,7 +965,6 @@ def _validate_sub_slot_data(
if not sub_slot_data.icc_slot_end.is_valid(constants, input, sub_slot_data.icc_slot_end_info, None):
log.error(f"failed icc slot end validation {sub_slot_data.icc_slot_end_info} ")
return False
assert sub_slot_data.cc_slot_end_info is not None
assert sub_slot_data.cc_slot_end_info
assert sub_slot_data.cc_slot_end
input = ClassgroupElement.get_default_element()
@ -1305,47 +1389,6 @@ def _get_ses_idx(recent_reward_chain: List[HeaderBlock]) -> List[int]:
return idxs
def handle_end_of_slot(
sub_slot: EndOfSubSlotBundle,
eos_vdf_iters: uint64,
):
assert sub_slot.infused_challenge_chain
assert sub_slot.proofs.infused_challenge_chain_slot_proof
if sub_slot.proofs.infused_challenge_chain_slot_proof.normalized_to_identity:
icc_info = sub_slot.infused_challenge_chain.infused_challenge_chain_end_of_slot_vdf
else:
icc_info = VDFInfo(
sub_slot.infused_challenge_chain.infused_challenge_chain_end_of_slot_vdf.challenge,
eos_vdf_iters,
sub_slot.infused_challenge_chain.infused_challenge_chain_end_of_slot_vdf.output,
)
if sub_slot.proofs.challenge_chain_slot_proof.normalized_to_identity:
cc_info = sub_slot.challenge_chain.challenge_chain_end_of_slot_vdf
else:
cc_info = VDFInfo(
sub_slot.challenge_chain.challenge_chain_end_of_slot_vdf.challenge,
eos_vdf_iters,
sub_slot.challenge_chain.challenge_chain_end_of_slot_vdf.output,
)
assert sub_slot.proofs.infused_challenge_chain_slot_proof is not None
return SubSlotData(
None,
None,
None,
None,
None,
None,
sub_slot.proofs.challenge_chain_slot_proof,
sub_slot.proofs.infused_challenge_chain_slot_proof,
cc_info,
icc_info,
None,
None,
None,
)
def get_deficit(
constants: ConsensusConstants,
curr_deficit: uint8,
@ -1381,3 +1424,53 @@ def blue_boxed_end_of_slot(sub_slot: EndOfSubSlotBundle):
else:
return True
return False
def validate_sub_epoch_sampling(rng, sub_epoch_weight_list, weight_proof):
tip = weight_proof.recent_chain_data[-1]
weight_to_check = _get_weights_for_sampling(rng, tip.weight, weight_proof.recent_chain_data)
sampled_sub_epochs: dict[int, bool] = {}
for idx in range(1, len(sub_epoch_weight_list)):
if _sample_sub_epoch(sub_epoch_weight_list[idx - 1], sub_epoch_weight_list[idx], weight_to_check):
sampled_sub_epochs[idx - 1] = True
if len(sampled_sub_epochs) == WeightProofHandler.MAX_SAMPLES:
break
curr_sub_epoch_n = -1
for sub_epoch_segment in weight_proof.sub_epoch_segments:
if curr_sub_epoch_n < sub_epoch_segment.sub_epoch_n:
if sub_epoch_segment.sub_epoch_n in sampled_sub_epochs:
del sampled_sub_epochs[sub_epoch_segment.sub_epoch_n]
curr_sub_epoch_n = sub_epoch_segment.sub_epoch_n
if len(sampled_sub_epochs) > 0:
return False
return True
def validate_total_iters(
segment: SubEpochChallengeSegment,
sub_slot_data_idx,
expected_sub_slot_iters: uint64,
finished_sub_slots_since_prev: int,
prev_b: SubSlotData,
prev_sub_slot_data_iters,
genesis,
) -> bool:
sub_slot_data = segment.sub_slots[sub_slot_data_idx]
if genesis:
total_iters: uint128 = uint128(expected_sub_slot_iters * finished_sub_slots_since_prev)
elif segment.sub_slots[sub_slot_data_idx - 1].is_end_of_slot():
assert prev_b.total_iters
total_iters = prev_b.total_iters
# Add the rest of the slot of prev_b
assert prev_b.cc_ip_vdf_info
total_iters = uint128(total_iters + prev_sub_slot_data_iters - prev_b.cc_ip_vdf_info.number_of_iterations)
# Add other empty slots
total_iters = uint128(total_iters + (expected_sub_slot_iters * (finished_sub_slots_since_prev - 1)))
else:
# Slot iters is guaranteed to be the same for header_block and prev_b
# This takes the beginning of the slot, and adds ip_iters
assert prev_b.total_iters
assert prev_b.cc_ip_vdf_info
total_iters = uint128(prev_b.total_iters - prev_b.cc_ip_vdf_info.number_of_iterations)
total_iters = uint128(total_iters + sub_slot_data.cc_ip_vdf_info.number_of_iterations)
return total_iters == sub_slot_data.total_iters

View File

@ -1,13 +1,16 @@
# flake8: noqa: F811, F401
import asyncio
import sys
from typing import Dict, List, Optional, Tuple
from typing import Dict, Optional, List, Tuple
import aiosqlite
import pytest
from src.consensus.block_header_validation import validate_finished_header_block
from src.consensus.block_record import BlockRecord
from src.consensus.default_constants import DEFAULT_CONSTANTS
from src.consensus.difficulty_adjustment import get_next_sub_slot_iters_and_difficulty
from src.consensus.full_block_to_block_record import block_to_block_record
from src.full_node.block_store import BlockStore
from src.types.blockchain_format.sized_bytes import bytes32
@ -23,18 +26,19 @@ except ImportError:
from src.consensus.pot_iterations import calculate_iterations_quality
from src.full_node.weight_proof import ( # type: ignore
WeightProofHandler,
_map_sub_epoch_summaries,
_validate_segment_slots,
_validate_summaries_weight,
_validate_segment,
)
from src.types.full_block import FullBlock
from src.types.header_block import HeaderBlock
from src.util.ints import uint32, uint64
from tests.core.fixtures import (
default_400_blocks,
default_1000_blocks,
default_400_blocks,
default_10000_blocks,
default_10000_blocks_compact,
pre_genesis_empty_slots_1000_blocks,
@ -149,12 +153,7 @@ async def _test_map_summaries(blocks, header_cache, height_to_hash, sub_blocks,
class TestWeightProof:
@pytest.mark.asyncio
async def test_weight_proof_map_summaries_1(self, default_400_blocks):
header_cache, height_to_hash, sub_blocks, summaries = await load_blocks_dont_validate(default_400_blocks)
await _test_map_summaries(default_400_blocks, header_cache, height_to_hash, sub_blocks, summaries)
@pytest.mark.asyncio
async def test_weight_proof_map_summaries_2(self, default_1000_blocks):
async def test_weight_proof_map_summaries_1(self, default_1000_blocks):
header_cache, height_to_hash, sub_blocks, summaries = await load_blocks_dont_validate(default_1000_blocks)
await _test_map_summaries(default_1000_blocks, header_cache, height_to_hash, sub_blocks, summaries)
@ -211,6 +210,14 @@ class TestWeightProof:
header_cache, height_to_hash, sub_blocks, summaries = await load_blocks_dont_validate(blocks)
wpf = WeightProofHandler(test_constants, BlockCache(sub_blocks, header_cache, height_to_hash, summaries))
blockchain = BlockCache(sub_blocks, header_cache, height_to_hash, summaries)
header = header_cache[height_to_hash[1]]
prev_b = blockchain.block_record(header.prev_header_hash)
sub_slot_iters, difficulty = get_next_sub_slot_iters_and_difficulty(
test_constants, len(header.finished_sub_slots) > 0, prev_b, blockchain
)
validate_finished_header_block(test_constants, blockchain, header, False, difficulty, sub_slot_iters, False)
wp = await wpf.get_proof_of_weight(blocks[-1].header_hash)
assert wp is not None
wpf = WeightProofHandler(test_constants, BlockCache(sub_blocks, header_cache, height_to_hash, {}))