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

Code before:
        blocks.reverse()
        return blocks

    async def autofarm_transaction(self, spend_name: bytes32) -> None:
        if self.auto_farm:
            self.log.info(f"Autofarm triggered by tx-id: {spend_name.hex()}")
            new_block = FarmNewBlockProtocol(self.bt.farmer_ph)
            await self.farm_new_transaction_block(new_block, force_wait_for_timestamp=True)

    async def update_autofarm_config(self, enable_autofarm: bool) -> bool:
        if enable_autofarm == self.auto_farm:
            return self.auto_farm
        else:
            self.auto_farm = enable_autofarm
            with lock_and_load_config(self.bt.root_path, "config.yaml") as config:
                if "simulator" in config:
                    config["simulator"]["auto_farm"] = self.auto_farm
                save_config(self.bt.root_path, "config.yaml", config)
            self.config = config
            if self.auto_farm is True and self.full_node.mempool_manager.mempool.total_mempool_cost() > 0:
                # if mempool is not empty and auto farm was just enabled, farm a block
                await self.farm_new_transaction_block(FarmNewBlockProtocol(self.bt.farmer_ph))
            return self.auto_farm

    async def get_all_coins(self, request: GetAllCoinsProtocol) -> list[CoinRecord]:
        """
        Simulates fetching all coins by querying coins added at each block height.

        Args:
            request: An object containing the `include_spent_coins` flag.

        Returns:
            A combined list of CoinRecords (including spent coins if requested).
        """
        coin_records: list[CoinRecord] = []
        current_height = 0
        max_block_height = self.full_node.blockchain.get_peak_height()

        if max_block_height is None:
            return coin_records

        while current_height <= max_block_height:
            # Fetch coins added at the current block height
            records_at_height = await self.full_node.coin_store.get_coins_added_at_height(uint32(current_height))

            if not request.include_spent_coins:
                # Filter out spent coins if not requested
                records_at_height = [record for record in records_at_height if not record.spent]

            coin_records.extend(records_at_height)
            current_height += 1

Review comment (suggestion):
Having this method in `CoinStoreProtocol` is a bad idea. We use an equivalent algorithm, also a bad idea, but at least contained to the simulator, limiting its potential damage.

Code after:
        blocks.reverse()
        return blocks

    async def autofarm_transaction(self, spend_name: bytes32) -> None:
        if self.auto_farm:
            self.log.info(f"Autofarm triggered by tx-id: {spend_name.hex()}")
            new_block = FarmNewBlockProtocol(self.bt.farmer_ph)
            await self.farm_new_transaction_block(new_block, force_wait_for_timestamp=True)

    async def update_autofarm_config(self, enable_autofarm: bool) -> bool:
        if enable_autofarm == self.auto_farm:
            return self.auto_farm
        else:
            self.auto_farm = enable_autofarm
            with lock_and_load_config(self.bt.root_path, "config.yaml") as config:
                if "simulator" in config:
                    config["simulator"]["auto_farm"] = self.auto_farm
                save_config(self.bt.root_path, "config.yaml", config)
            self.config = config
            if self.auto_farm is True and self.full_node.mempool_manager.mempool.total_mempool_cost() > 0:
                # if mempool is not empty and auto farm was just enabled, farm a block
                await self.farm_new_transaction_block(FarmNewBlockProtocol(self.bt.farmer_ph))
            return self.auto_farm

    async def get_all_coins(self, request: GetAllCoinsProtocol) -> list[CoinRecord]:
        """
        Simulates fetching all coins by querying coins added at each block height.

        Args:
            request: An object containing the `include_spent_coins` flag.

        Returns:
            A combined list of CoinRecords (including spent coins if requested).
        """
        coin_records: list[CoinRecord] = []
        current_height = 0

        # `.get_peak_height` can return `None`. We use -1 in that case to exit early
        max_block_height = self.full_node.blockchain.get_peak_height() or -1

        while current_height <= max_block_height:
            # Fetch coins added at the current block height
            records_at_height = await self.full_node.coin_store.get_coins_added_at_height(uint32(current_height))

            if not request.include_spent_coins:
                # Filter out spent coins if not requested
                records_at_height = [record for record in records_at_height if not record.spent]

            coin_records.extend(records_at_height)
            current_height += 1