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.5#6# Be aware that bitcoind and bitcoin-qt differ in terms of localization: Qt7# opts in to POSIX localization by running setlocale(LC_ALL, "") on startup,8# whereas no such call is made in bitcoind.9#10# Qt runs setlocale(LC_ALL, "") on initialization. This installs the locale11# specified by the user's LC_ALL (or LC_*) environment variable as the new12# C locale.13#14# In contrast, bitcoind does not opt in to localization -- no call to15# setlocale(LC_ALL, "") is made and the environment variables LC_* are16# thus ignored.17#18# This results in situations where bitcoind is guaranteed to be running19# with the classic locale ("C") whereas the locale of bitcoin-qt will vary20# depending on the user's environment variables.21#22# An example: Assuming the environment variable LC_ALL=de_DE then the23# call std::to_string(1.23) will return "1.230000" in bitcoind but24# "1,230000" in bitcoin-qt.25#26# From the Qt documentation:27# "On Unix/Linux Qt is configured to use the system locale settings by default.28# This can cause a conflict when using POSIX functions, for instance, when29# converting between data types such as floats and strings, since the notation30# may differ between locales. To get around this problem, call the POSIX function31# setlocale(LC_NUMERIC,"C") right after initializing QApplication, QGuiApplication32# or QCoreApplication to reset the locale that is used for number formatting to33# "C"-locale."34#35# See https://doc.qt.io/qt-5/qcoreapplication.html#locale-settings and36# https://stackoverflow.com/a/34878283 for more details.38import re39import sys41from subprocess import check_output, CalledProcessError43from lint_ignore_dirs import SHARED_EXCLUDED_SUBTREES46KNOWN_VIOLATIONS = [47"src/dbwrapper.cpp:.*vsnprintf",48"src/span.h:.*printf",49"src/test/fuzz/locale.cpp:.*setlocale",50"src/test/util_tests.cpp:.*strtoll",51"src/util/syserror.cpp:.*strerror", # Outside this function use `SysErrorString`52]54REGEXP_EXTERNAL_DEPENDENCIES_EXCLUSIONS = [55"src/tinyformat.h",56] + SHARED_EXCLUDED_SUBTREES58LOCALE_DEPENDENT_FUNCTIONS = [59"alphasort", # LC_COLLATE (via strcoll)60"asctime", # LC_TIME (directly)61"asprintf", # (via vasprintf)62"atof", # LC_NUMERIC (via strtod)63"atoi", # LC_NUMERIC (via strtol)64"atol", # LC_NUMERIC (via strtol)65"atoll", # (via strtoll)66"atoq",67"btowc", # LC_CTYPE (directly)68"ctime", # (via asctime or localtime)69"dprintf", # (via vdprintf)70"fgetwc",71"fgetws",72"fold_case", # boost::locale::fold_case73"fprintf", # (via vfprintf)74"fputwc",75"fputws",76"fscanf", # (via __vfscanf)77"fwprintf", # (via __vfwprintf)78"getdate", # via __getdate_r => isspace // __localtime_r79"getwc",80"getwchar",81"is_digit", # boost::algorithm::is_digit82"is_space", # boost::algorithm::is_space83"isalnum", # LC_CTYPE84"isalpha", # LC_CTYPE85"isblank", # LC_CTYPE86"iscntrl", # LC_CTYPE87"isctype", # LC_CTYPE88"isdigit", # LC_CTYPE89"isgraph", # LC_CTYPE90"islower", # LC_CTYPE91"isprint", # LC_CTYPE92"ispunct", # LC_CTYPE93"isspace", # LC_CTYPE94"isupper", # LC_CTYPE95"iswalnum", # LC_CTYPE96"iswalpha", # LC_CTYPE97"iswblank", # LC_CTYPE98"iswcntrl", # LC_CTYPE99"iswctype", # LC_CTYPE100"iswdigit", # LC_CTYPE101"iswgraph", # LC_CTYPE102"iswlower", # LC_CTYPE103"iswprint", # LC_CTYPE104"iswpunct", # LC_CTYPE105"iswspace", # LC_CTYPE106"iswupper", # LC_CTYPE107"iswxdigit", # LC_CTYPE108"isxdigit", # LC_CTYPE109"localeconv", # LC_NUMERIC + LC_MONETARY110"mblen", # LC_CTYPE111"mbrlen",112"mbrtowc",113"mbsinit",114"mbsnrtowcs",115"mbsrtowcs",116"mbstowcs", # LC_CTYPE117"mbtowc", # LC_CTYPE118"mktime",119"normalize", # boost::locale::normalize120"printf", # LC_NUMERIC121"putwc",122"putwchar",123"scanf", # LC_NUMERIC124"setlocale",125"snprintf",126"sprintf",127"sscanf",128"std::locale::global",129"std::to_string",130"stod",131"stof",132"stoi",133"stol",134"stold",135"stoll",136"stoul",137"stoull",138"strcasecmp",139"strcasestr",140"strcoll", # LC_COLLATE141"strerror",142"strfmon",143"strftime", # LC_TIME144"strncasecmp",145"strptime",146"strtod", # LC_NUMERIC147"strtof",148"strtoimax",149"strtol", # LC_NUMERIC150"strtold",151"strtoll",152"strtoq",153"strtoul", # LC_NUMERIC154"strtoull",155"strtoumax",156"strtouq",157"strxfrm", # LC_COLLATE158"swprintf",159"to_lower", # boost::locale::to_lower160"to_title", # boost::locale::to_title161"to_upper", # boost::locale::to_upper162"tolower", # LC_CTYPE163"toupper", # LC_CTYPE164"towctrans",165"towlower", # LC_CTYPE166"towupper", # LC_CTYPE167"trim", # boost::algorithm::trim168"trim_left", # boost::algorithm::trim_left169"trim_right", # boost::algorithm::trim_right170"ungetwc",171"vasprintf",172"vdprintf",173"versionsort",174"vfprintf",175"vfscanf",176"vfwprintf",177"vprintf",178"vscanf",179"vsnprintf",180"vsprintf",181"vsscanf",182"vswprintf",183"vwprintf",184"wcrtomb",185"wcscasecmp",186"wcscoll", # LC_COLLATE187"wcsftime", # LC_TIME188"wcsncasecmp",189"wcsnrtombs",190"wcsrtombs",191"wcstod", # LC_NUMERIC192"wcstof",193"wcstoimax",194"wcstol", # LC_NUMERIC195"wcstold",196"wcstoll",197"wcstombs", # LC_CTYPE198"wcstoul", # LC_NUMERIC199"wcstoull",200"wcstoumax",201"wcswidth",202"wcsxfrm", # LC_COLLATE203"wctob",204"wctomb", # LC_CTYPE205"wctrans",206"wctype",207"wcwidth",208"wprintf"209]212def find_locale_dependent_function_uses():213regexp_locale_dependent_functions = "|".join(LOCALE_DEPENDENT_FUNCTIONS)214exclude_args = [":(exclude)" + excl for excl in REGEXP_EXTERNAL_DEPENDENCIES_EXCLUSIONS]215git_grep_command = ["git", "grep", "--extended-regexp", "[^a-zA-Z0-9_\\`'\"<>](" + regexp_locale_dependent_functions + ")(_r|_s)?\\(", "--", "*.cpp", "*.h"] + exclude_args216git_grep_output = list()218try:219git_grep_output = check_output(git_grep_command, text=True).splitlines()220except CalledProcessError as e:221if e.returncode > 1:222raise e224return git_grep_output227def main():228exit_code = 0230regexp_ignore_known_violations = "|".join(KNOWN_VIOLATIONS)231git_grep_output = find_locale_dependent_function_uses()233for locale_dependent_function in LOCALE_DEPENDENT_FUNCTIONS:234matches = [line for line in git_grep_output235if re.search("[^a-zA-Z0-9_\\`'\"<>]" + locale_dependent_function + "(_r|_s)?\\(", line)236and not re.search("\\.(c|cpp|h):\\s*//.*" + locale_dependent_function, line)237and not re.search(regexp_ignore_known_violations, line)]238if matches:239print(f"The locale dependent function {locale_dependent_function}(...) appears to be used:")240for match in matches:241print(match)242print("")243exit_code = 1245if exit_code == 1:246print("Unnecessary locale dependence can cause bugs that are very tricky to isolate and fix. Please avoid using locale-dependent functions if possible.\n")247print(f"Advice not applicable in this specific case? Add an exception by updating the ignore list in {sys.argv[0]}")249sys.exit(exit_code)
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.