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

Code before:
            self,
            (fork_info.peak_height, fork_info.peak_hash),
            (block.height - 1, block.prev_header_hash),
            self.constants,
        )
        # the ForkInfo object is expected to be valid, just having its peak
        # behind the current block
        assert peak_hash == fork_info.peak_hash
        assert len(chain) == block.height - fork_info.peak_height - 1

        for height in range(fork_info.peak_height + 1, block.height):
            fork_block: Optional[FullBlock] = await self.block_store.get_full_block(chain[uint32(height)])
            assert fork_block is not None
            await self.run_single_block(fork_block, fork_info)

    async def run_single_block(self, block: FullBlock, fork_info: ForkInfo) -> None:
        assert fork_info.peak_height == block.height - 1
        assert block.height == 0 or fork_info.peak_hash == block.prev_header_hash

        conds = None
        if block.transactions_generator is not None:
            block_generator: Optional[BlockGenerator] = await get_block_generator(self.lookup_block_generators, block)
            assert block_generator is not None
            assert block.transactions_info is not None
            assert block.foliage_transaction_block is not None
            flags = get_flags_for_height_and_constants(block.height, self.constants)
            err, conds = run_block_generator2(
                program=bytes(block.transactions_generator),
                block_refs=block_generator.generator_refs,
                max_cost=min(self.constants.MAX_BLOCK_COST_CLVM, block.transactions_info.cost),
                flags=flags,
                signature=block.transactions_info.aggregated_signature,
                bls_cache=None,
                constants=self.constants,
            )
            assert err is None
            assert conds is not None

        fork_info.include_spends(conds, block, block.header_hash)

    async def add_block(
        self,
        block: FullBlock,
        pre_validation_result: PreValidationResult,
        sub_slot_iters: uint64,
        fork_info: ForkInfo,
        prev_ses_block: Optional[BlockRecord] = None,
        block_record: Optional[BlockRecord] = None,
    ) -> tuple[AddBlockResult, Optional[Err], Optional[StateChangeSummary]]:
        """
        This method must be called under the blockchain lock

Review comment (security):
is there a good reason to change this? `run_block_generator2()` is slower, since it accepts *untrusted* blocks, whereas `additions_and_removals()` only run *trusted* blocks. i.e. we have already validated them

Code after:
            (block.height - 1, block.prev_header_hash),
            self.constants,
        )
        # the ForkInfo object is expected to be valid, just having its peak
        # behind the current block
        assert peak_hash == fork_info.peak_hash
        assert len(chain) == block.height - fork_info.peak_height - 1

        for height in range(fork_info.peak_height + 1, block.height):
            fork_block: Optional[FullBlock] = await self.block_store.get_full_block(chain[uint32(height)])
            assert fork_block is not None
            await self.run_single_block(fork_block, fork_info)

    async def run_single_block(self, block: FullBlock, fork_info: ForkInfo) -> None:
        assert fork_info.peak_height == block.height - 1
        assert block.height == 0 or fork_info.peak_hash == block.prev_header_hash

        additions: list[tuple[Coin, Optional[bytes]]] = []
        removals: list[Coin] = []
        if block.transactions_generator is not None:
            block_generator: Optional[BlockGenerator] = await get_block_generator(self.lookup_block_generators, block)
            assert block_generator is not None
            assert block.transactions_info is not None
            assert block.foliage_transaction_block is not None
            flags = get_flags_for_height_and_constants(block.height, self.constants)
            additions, removals = additions_and_removals(
                bytes(block.transactions_generator),
                block_generator.generator_refs,
                flags,
                self.constants,
            )

        fork_info.include_block(additions, removals, block, block.header_hash)

    async def add_block(
        self,
        block: FullBlock,
        pre_validation_result: PreValidationResult,
        sub_slot_iters: uint64,
        fork_info: ForkInfo,
        prev_ses_block: Optional[BlockRecord] = None,
        block_record: Optional[BlockRecord] = None,
    ) -> tuple[AddBlockResult, Optional[Err], Optional[StateChangeSummary]]:
        """
        This method must be called under the blockchain lock
        Adds a new block into the blockchain, if it's valid and connected to the current
        blockchain, regardless of whether it is the child of a head, or another block.
        Returns a header if block is added to head. Returns an error if the block is
        invalid. Also returns the fork height, in the case of a new peak.

        Args: