Inside Bitcoin
Opening the selected file…
Inside Bitcoin
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
1#!/usr/bin/env python32# Copyright (c) 2018-present The Bitcoin Core developers3# Distributed under the MIT software license, see the accompanying4# file COPYING or http://www.opensource.org/licenses/mit-license.php.6import sys7import re9# Directories with header-based modules, where the assumption that .cpp files10# define functions and variables declared in corresponding .h files is11# incorrect.12HEADER_MODULE_PATHS = [13'interfaces/'14]16def module_name(path):17if any(path.startswith(dirpath) for dirpath in HEADER_MODULE_PATHS):18return path19if path.endswith(".h"):20return path[:-2]21if path.endswith(".c"):22return path[:-2]23if path.endswith(".cpp"):24return path[:-4]25return None27files = dict()28deps: dict[str, set[str]] = dict()30RE = re.compile("^#include <(.*)>")32# Iterate over files, and create list of modules33for arg in sys.argv[1:]:34module = module_name(arg)35if module is None:36print("Ignoring file %s (does not constitute module)\n" % arg)37else:38files[arg] = module39deps[module] = set()41# Iterate again, and build list of direct dependencies for each module42# TODO: implement support for multiple include directories43for arg in sorted(files.keys()):44module = files[arg]45with open(arg, 'r') as f:46for line in f:47match = RE.match(line)48if match:49include = match.group(1)50included_module = module_name(include)51if included_module is not None and included_module in deps and included_module != module:52deps[module].add(included_module)54# Loop to find the shortest (remaining) circular dependency55have_cycle: bool = False56while True:57shortest_cycle = None58for module in sorted(deps.keys()):59# Build the transitive closure of dependencies of module60closure: dict[str, list[str]] = dict()61for dep in deps[module]:62closure[dep] = []63while True:64old_size = len(closure)65old_closure_keys = sorted(closure.keys())66for src in old_closure_keys:67for dep in deps[src]:68if dep not in closure:69closure[dep] = closure[src] + [src]70if len(closure) == old_size:71break72# If module is in its own transitive closure, it's a circular dependency; check if it is the shortest73if module in closure and (shortest_cycle is None or len(closure[module]) + 1 < len(shortest_cycle)):74shortest_cycle = [module] + closure[module]75if shortest_cycle is None:76break77# We have the shortest circular dependency; report it78module = shortest_cycle[0]79print("Circular dependency: %s" % (" -> ".join(shortest_cycle + [module])))80# And then break the dependency to avoid repeating in other cycles81deps[shortest_cycle[-1]] = deps[shortest_cycle[-1]] - set([module])82have_cycle = True84sys.exit(1 if have_cycle else 0)
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.