Repository: Chia-Network/chia-blockchain
File: chia/consensus/blockchain.py (Python)

Code before:
            return []
        recent_rc: list[tuple[bytes32, uint128]] = []
        curr: Optional[BlockRecord] = peak
        while curr is not None and len(recent_rc) < 2 * self.constants.MAX_SUB_SLOT_BLOCKS:
            if curr != peak:
                recent_rc.append((curr.reward_infusion_new_challenge, curr.total_iters))
            if curr.first_in_sub_slot:
                assert curr.finished_reward_slot_hashes is not None
                sub_slot_total_iters = curr.ip_sub_slot_total_iters(self.constants)
                # Start from the most recent
                for rc in reversed(curr.finished_reward_slot_hashes):
                    if sub_slot_total_iters < curr.sub_slot_iters:
                        break
                    recent_rc.append((rc, sub_slot_total_iters))
                    sub_slot_total_iters = uint128(sub_slot_total_iters - curr.sub_slot_iters)
            curr = self.try_block_record(curr.prev_hash)
        return list(reversed(recent_rc))

    async def validate_unfinished_block_header(
        self, block: UnfinishedBlock, skip_overflow_ss_validation: bool = True
    ) -> tuple[Optional[uint64], Optional[Err]]:
        if len(block.transactions_generator_ref_list) > self.constants.MAX_GENERATOR_REF_LIST_SIZE:
            return None, Err.TOO_MANY_GENERATOR_REFS

        prev_tx_height = prev_tx_block(
            self.constants,
            self,
            block.prev_header_hash,
            block.reward_chain_block.signage_point_index,
            len(block.finished_sub_slots) > 0,
        )

        # With hard fork 2 we ban transactions_generator_ref_list.
        if prev_tx_height >= self.constants.HARD_FORK2_HEIGHT and block.transactions_generator_ref_list != []:
            return None, Err.TOO_MANY_GENERATOR_REFS

        if block.transactions_info is not None:
            if block.transactions_generator is not None:
                if std_hash(bytes(block.transactions_generator)) != block.transactions_info.generator_root:
                    return None, Err.INVALID_TRANSACTIONS_GENERATOR_HASH
            elif block.transactions_info.generator_root != bytes([0] * 32):
                return None, Err.INVALID_TRANSACTIONS_GENERATOR_HASH

            if (
                block.foliage_transaction_block is None
                or block.foliage_transaction_block.transactions_info_hash != block.transactions_info.get_hash()
            ):
                return None, Err.INVALID_TRANSACTIONS_INFO_HASH
        else:
            # make sure non-tx blocks don't have these fields
            if block.transactions_generator is not None:

Review comment (suggestion):
the case where `prev_b` is `None` isn't handled in the new version of this. Here it returns `Err.INVALID_PREV_BLOCK_HASH`, in your new version it throws (I think)

Code after:
            return []
        recent_rc: list[tuple[bytes32, uint128]] = []
        curr: Optional[BlockRecord] = peak
        while curr is not None and len(recent_rc) < 2 * self.constants.MAX_SUB_SLOT_BLOCKS:
            if curr != peak:
                recent_rc.append((curr.reward_infusion_new_challenge, curr.total_iters))
            if curr.first_in_sub_slot:
                assert curr.finished_reward_slot_hashes is not None
                sub_slot_total_iters = curr.ip_sub_slot_total_iters(self.constants)
                # Start from the most recent
                for rc in reversed(curr.finished_reward_slot_hashes):
                    if sub_slot_total_iters < curr.sub_slot_iters:
                        break
                    recent_rc.append((rc, sub_slot_total_iters))
                    sub_slot_total_iters = uint128(sub_slot_total_iters - curr.sub_slot_iters)
            curr = self.try_block_record(curr.prev_hash)
        return list(reversed(recent_rc))

    async def validate_unfinished_block_header(
        self, block: UnfinishedBlock, skip_overflow_ss_validation: bool = True
    ) -> tuple[Optional[uint64], Optional[Err]]:
        if len(block.transactions_generator_ref_list) > self.constants.MAX_GENERATOR_REF_LIST_SIZE:
            return None, Err.TOO_MANY_GENERATOR_REFS

        prev_b = self.try_block_record(block.prev_header_hash)
        if prev_b is None and block.prev_header_hash != self.constants.GENESIS_CHALLENGE:
            return None, Err.INVALID_PREV_BLOCK_HASH

        prev_tx_height = prev_tx_block(
            constants=self.constants,
            blocks=self,
            prev_b_hash=block.prev_header_hash,
            sp_index=block.reward_chain_block.signage_point_index,
            first_in_sub_slot=len(block.finished_sub_slots) > 0,
        )

        # With hard fork 2 we ban transactions_generator_ref_list.
        if prev_tx_height >= self.constants.HARD_FORK2_HEIGHT and block.transactions_generator_ref_list != []:
            return None, Err.TOO_MANY_GENERATOR_REFS

        if block.transactions_info is not None:
            if block.transactions_generator is not None:
                if std_hash(bytes(block.transactions_generator)) != block.transactions_info.generator_root:
                    return None, Err.INVALID_TRANSACTIONS_GENERATOR_HASH
            elif block.transactions_info.generator_root != bytes([0] * 32):
                return None, Err.INVALID_TRANSACTIONS_GENERATOR_HASH

            if (
                block.foliage_transaction_block is None
                or block.foliage_transaction_block.transactions_info_hash != block.transactions_info.get_hash()
            ):