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

Code before:
                log_coins=log_coins,
            )

            self._mempool_manager = MempoolManager(
                get_coin_records=self.coin_store.get_coin_records,
                get_unspent_lineage_info_for_puzzle_hash=self.coin_store.get_unspent_lineage_info_for_puzzle_hash,
                consensus_constants=self.constants,
                single_threaded=single_threaded,
            )

            # Transactions go into this queue from the server, and get sent to respond_transaction
            self._transaction_queue = TransactionQueue(1000, self.log)
            self._transaction_queue_task: asyncio.Task[None] = create_referenced_task(self._handle_transactions())

            self._init_weight_proof = create_referenced_task(self.initialize_weight_proof())

            if self.config.get("enable_profiler", False):
                create_referenced_task(profile_task(self.root_path, "node", self.log), known_unreferenced=True)

            self.profile_block_validation = self.config.get("profile_block_validation", False)
            if self.profile_block_validation:  # pragma: no cover
                # this is not covered by any unit tests as it's essentially test code
                # itself. It's exercised manually when investigating performance issues
                profile_dir = path_from_root(self.root_path, "block-validation-profile")
                profile_dir.mkdir(parents=True, exist_ok=True)

            if self.config.get("enable_memory_profiler", False):
                create_referenced_task(mem_profile_task(self.root_path, "node", self.log), known_unreferenced=True)

            time_taken = time.monotonic() - start_time
            peak: Optional[BlockRecord] = self.blockchain.get_peak()
            if peak is None:
                self.log.info(f"Initialized with empty blockchain time taken: {int(time_taken)}s")
                if await coin_store_seems_nonempty():
                    self.log.error(
                        "Inconsistent blockchain DB file! Could not find peak block but found some coins! "
                        "This is a fatal error. The blockchain database may be corrupt"
                    )
                    raise RuntimeError("corrupt blockchain DB")
            else:
                self.log.info(
                    f"Blockchain initialized to peak {peak.header_hash} height"
                    f" {peak.height}, "
                    f"time taken: {int(time_taken)}s"
                )
                async with self.blockchain.priority_mutex.acquire(priority=BlockchainMutexPriority.high):
                    pending_tx = await self.mempool_manager.new_peak(self.blockchain.get_tx_peak(), None)
                    assert len(pending_tx.items) == 0  # no pending transactions when starting up

                    full_peak: Optional[FullBlock] = await self.blockchain.get_full_peak()
                    assert full_peak is not None

Review comment (bug):
The `.num_unspent` API is badly named and ill-conceived since a count could take a very long time depending on the specifics of the storage mechanism, and is not actually needed for any genuine purpose, so requiring it in the protocol applies an unnecessary constraint. We use a local function that more or less provides the same functionality. It doesn't catch all the same failure cases, but the prior method is just a mild sanity check anyway.

Code after:
                single_threaded=single_threaded,
            )

            # Transactions go into this queue from the server, and get sent to respond_transaction
            self._transaction_queue = TransactionQueue(1000, self.log)
            self._transaction_queue_task: asyncio.Task[None] = create_referenced_task(self._handle_transactions())

            self._init_weight_proof = create_referenced_task(self.initialize_weight_proof())

            if self.config.get("enable_profiler", False):
                create_referenced_task(profile_task(self.root_path, "node", self.log), known_unreferenced=True)

            self.profile_block_validation = self.config.get("profile_block_validation", False)
            if self.profile_block_validation:  # pragma: no cover
                # this is not covered by any unit tests as it's essentially test code
                # itself. It's exercised manually when investigating performance issues
                profile_dir = path_from_root(self.root_path, "block-validation-profile")
                profile_dir.mkdir(parents=True, exist_ok=True)

            if self.config.get("enable_memory_profiler", False):
                create_referenced_task(mem_profile_task(self.root_path, "node", self.log), known_unreferenced=True)

            time_taken = time.monotonic() - start_time
            peak: Optional[BlockRecord] = self.blockchain.get_peak()
            if peak is None:
                self.log.info(f"Initialized with empty blockchain time taken: {int(time_taken)}s")
                if not await self.coin_store.is_empty():
                    self.log.error(
                        "Inconsistent blockchain DB file! Could not find peak block but found some coins! "
                        "This is a fatal error. The blockchain database may be corrupt"
                    )
                    raise RuntimeError("corrupt blockchain DB")
            else:
                self.log.info(
                    f"Blockchain initialized to peak {peak.header_hash} height"
                    f" {peak.height}, "
                    f"time taken: {int(time_taken)}s"
                )
                async with self.blockchain.priority_mutex.acquire(priority=BlockchainMutexPriority.high):
                    pending_tx = await self.mempool_manager.new_peak(self.blockchain.get_tx_peak(), None)
                    assert len(pending_tx.items) == 0  # no pending transactions when starting up

                    full_peak: Optional[FullBlock] = await self.blockchain.get_full_peak()
                    assert full_peak is not None
                    state_change_summary = StateChangeSummary(peak, uint32(max(peak.height - 1, 0)), [], [], [], [])
                    # Must be called under priority_mutex
                    ppp_result: PeakPostProcessingResult = await self.peak_post_processing(
                        full_peak, state_change_summary, None
                    )
                # Can be called outside of priority_mutex
                await self.peak_post_processing_2(full_peak, None, state_change_summary, ppp_result)