103 lines
4.7 KiB
Python
103 lines
4.7 KiB
Python
import logging
|
|
from typing import List, Union
|
|
|
|
from chia.consensus.block_record import BlockRecord
|
|
from chia.consensus.blockchain_interface import BlockchainInterface
|
|
from chia.consensus.constants import ConsensusConstants
|
|
from chia.types.blockchain_format.sized_bytes import bytes32
|
|
from chia.types.full_block import FullBlock
|
|
from chia.types.header_block import HeaderBlock
|
|
from chia.types.unfinished_block import UnfinishedBlock
|
|
from chia.types.unfinished_header_block import UnfinishedHeaderBlock
|
|
from chia.util.ints import uint64
|
|
|
|
log = logging.getLogger(__name__)
|
|
|
|
|
|
def final_eos_is_already_included(
|
|
header_block: Union[UnfinishedHeaderBlock, UnfinishedBlock, HeaderBlock, FullBlock],
|
|
blocks: BlockchainInterface,
|
|
sub_slot_iters: uint64,
|
|
) -> bool:
|
|
"""
|
|
Args:
|
|
header_block: An overflow block, with potentially missing information about the new sub slot
|
|
blocks: all blocks that have been included before header_block
|
|
sub_slot_iters: sub_slot_iters at the header_block
|
|
|
|
Returns: True iff the missing sub slot was already included in a previous block. Returns False if the sub
|
|
slot was not included yet, and therefore it is the responsibility of this block to include it
|
|
|
|
"""
|
|
if len(header_block.finished_sub_slots) > 0:
|
|
# We already have an included empty sub slot, which means the prev block is 2 sub slots behind.
|
|
return False
|
|
curr: BlockRecord = blocks.block_record(header_block.prev_header_hash)
|
|
|
|
# We also check if curr is close to header_block, which means it's in the same sub slot
|
|
seen_overflow_block = curr.overflow and (header_block.total_iters - curr.total_iters < sub_slot_iters // 2)
|
|
while not curr.first_in_sub_slot and not curr.height == 0:
|
|
if curr.overflow and header_block.total_iters - curr.total_iters < sub_slot_iters // 2:
|
|
seen_overflow_block = True
|
|
curr = blocks.block_record(curr.prev_hash)
|
|
|
|
if curr.first_in_sub_slot and seen_overflow_block:
|
|
# We have seen another overflow block in this slot (same as header_block), therefore there are no
|
|
# missing sub slots
|
|
return True
|
|
|
|
# We have not seen any overflow blocks, therefore header_block will have to include the missing sub slot in
|
|
# the future
|
|
return False
|
|
|
|
|
|
def get_block_challenge(
|
|
constants: ConsensusConstants,
|
|
header_block: Union[UnfinishedHeaderBlock, UnfinishedBlock, HeaderBlock, FullBlock],
|
|
blocks: BlockchainInterface,
|
|
genesis_block: bool,
|
|
overflow: bool,
|
|
skip_overflow_last_ss_validation: bool,
|
|
):
|
|
if len(header_block.finished_sub_slots) > 0:
|
|
if overflow:
|
|
# New sub-slot with overflow block
|
|
if skip_overflow_last_ss_validation:
|
|
# In this case, we are missing the final sub-slot bundle (it's not finished yet), however
|
|
# There is a whole empty slot before this block is infused
|
|
challenge: bytes32 = header_block.finished_sub_slots[-1].challenge_chain.get_hash()
|
|
else:
|
|
challenge = header_block.finished_sub_slots[
|
|
-1
|
|
].challenge_chain.challenge_chain_end_of_slot_vdf.challenge
|
|
else:
|
|
# No overflow, new slot with a new challenge
|
|
challenge = header_block.finished_sub_slots[-1].challenge_chain.get_hash()
|
|
else:
|
|
if genesis_block:
|
|
challenge = constants.GENESIS_CHALLENGE
|
|
else:
|
|
if overflow:
|
|
if skip_overflow_last_ss_validation:
|
|
# Overflow infusion without the new slot, so get the last challenge
|
|
challenges_to_look_for = 1
|
|
else:
|
|
# Overflow infusion, so get the second to last challenge. skip_overflow_last_ss_validation is False,
|
|
# Which means no sub slots are omitted
|
|
challenges_to_look_for = 2
|
|
else:
|
|
challenges_to_look_for = 1
|
|
reversed_challenge_hashes: List[bytes32] = []
|
|
curr: BlockRecord = blocks.block_record(header_block.prev_header_hash)
|
|
while len(reversed_challenge_hashes) < challenges_to_look_for:
|
|
if curr.first_in_sub_slot:
|
|
assert curr.finished_challenge_slot_hashes is not None
|
|
reversed_challenge_hashes += reversed(curr.finished_challenge_slot_hashes)
|
|
if curr.height == 0:
|
|
assert curr.finished_challenge_slot_hashes is not None
|
|
assert len(curr.finished_challenge_slot_hashes) > 0
|
|
break
|
|
curr = blocks.block_record(curr.prev_hash)
|
|
challenge = reversed_challenge_hashes[challenges_to_look_for - 1]
|
|
return challenge
|