From 04e211837296aa2317bc5118863c15e5d76aa752 Mon Sep 17 00:00:00 2001 From: fanquake Date: Mon, 16 Mar 2026 17:35:58 +0800 Subject: [PATCH 1/5] lint: remove excluded .cpp/.h files from whitespace check These have been fixed since #32482 and 5d25a82b9a5e54f74cc066599541bc1d3da70988. --- test/lint/test_runner/src/lint_text_format.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/test/lint/test_runner/src/lint_text_format.rs b/test/lint/test_runner/src/lint_text_format.rs index ca51e6db081..1f7d540d911 100644 --- a/test/lint/test_runner/src/lint_text_format.rs +++ b/test/lint/test_runner/src/lint_text_format.rs @@ -20,14 +20,11 @@ fn get_pathspecs_exclude_whitespace() -> Vec { // Temporary excludes, or existing violations "contrib/init/bitcoind.openrc", "contrib/macdeploy/macdeployqtplus", - "src/crypto/sha256_sse4.cpp", "src/qt/res/src/*.svg", "test/functional/test_framework/crypto/ellswift_decode_test_vectors.csv", "test/functional/test_framework/crypto/xswiftec_inv_test_vectors.csv", "contrib/qos/tc.sh", "contrib/verify-commits/gpg.sh", - "src/univalue/include/univalue_escapes.h", - "src/univalue/test/object.cpp", "test/lint/git-subtree-check.sh", ] .iter() From ee8c22eb6a4f04e51110156e092744318cb76700 Mon Sep 17 00:00:00 2001 From: fanquake Date: Mon, 16 Mar 2026 19:54:10 +0800 Subject: [PATCH 2/5] contrib: fix whitespace issues in scripts --- contrib/init/bitcoind.openrc | 2 +- contrib/macdeploy/macdeployqtplus | 74 +++++++++---------- contrib/qos/tc.sh | 10 +-- contrib/verify-commits/gpg.sh | 46 ++++++------ test/lint/test_runner/src/lint_text_format.rs | 4 - 5 files changed, 66 insertions(+), 70 deletions(-) diff --git a/contrib/init/bitcoind.openrc b/contrib/init/bitcoind.openrc index 013a1a60702..30e7be36fcf 100644 --- a/contrib/init/bitcoind.openrc +++ b/contrib/init/bitcoind.openrc @@ -1,6 +1,6 @@ #!/sbin/openrc-run -# backward compatibility for existing gentoo layout +# backward compatibility for existing gentoo layout # if [ -d "/var/lib/bitcoin/.bitcoin" ]; then BITCOIND_DEFAULT_DATADIR="/var/lib/bitcoin/.bitcoin" diff --git a/contrib/macdeploy/macdeployqtplus b/contrib/macdeploy/macdeployqtplus index bb693e73058..c8244af1532 100755 --- a/contrib/macdeploy/macdeployqtplus +++ b/contrib/macdeploy/macdeployqtplus @@ -42,13 +42,13 @@ class FrameworkInfo(object): self.sourceContentsDirectory = "" self.destinationResourcesDirectory = "" self.destinationVersionContentsDirectory = "" - + def __eq__(self, other): if self.__class__ == other.__class__: return self.__dict__ == other.__dict__ else: return False - + def __str__(self): return f""" Framework name: {self.frameworkName} Framework directory: {self.frameworkDirectory} @@ -62,51 +62,51 @@ class FrameworkInfo(object): Source file Path: {self.sourceFilePath} Deployed Directory (relative to bundle): {self.destinationDirectory} """ - + def isDylib(self): return self.frameworkName.endswith(".dylib") - + def isQtFramework(self): if self.isDylib(): return self.frameworkName.startswith("libQt") else: return self.frameworkName.startswith("Qt") - + reOLine = re.compile(r'^(.+) \(compatibility version [0-9.]+, current version [0-9.]+\)$') bundleFrameworkDirectory = "Contents/Frameworks" bundleBinaryDirectory = "Contents/MacOS" - + @classmethod def fromLibraryLine(cls, line: str) -> Optional['FrameworkInfo']: # Note: line must be trimmed if line == "": return None - + # Don't deploy system libraries if line.startswith("/System/Library/") or line.startswith("@executable_path") or line.startswith("/usr/lib/"): return None - + m = cls.reOLine.match(line) if m is None: raise RuntimeError(f"Line could not be parsed: {line}") - + path = m.group(1) - + info = cls() info.sourceFilePath = path info.installName = path - + if path.endswith(".dylib"): dirname, filename = os.path.split(path) info.frameworkName = filename info.frameworkDirectory = dirname info.frameworkPath = path - + info.binaryDirectory = dirname info.binaryName = filename info.binaryPath = path info.version = "-" - + info.installName = path info.deployedInstallName = f"@executable_path/../Frameworks/{info.binaryName}" info.sourceFilePath = path @@ -121,25 +121,25 @@ class FrameworkInfo(object): i += 1 if i == len(parts): raise RuntimeError(f"Could not find .framework or .dylib in line: {line}") - + info.frameworkName = parts[i] info.frameworkDirectory = "/".join(parts[:i]) info.frameworkPath = os.path.join(info.frameworkDirectory, info.frameworkName) - + info.binaryName = parts[i+3] info.binaryDirectory = "/".join(parts[i+1:i+3]) info.binaryPath = os.path.join(info.binaryDirectory, info.binaryName) info.version = parts[i+2] - + info.deployedInstallName = f"@executable_path/../Frameworks/{os.path.join(info.frameworkName, info.binaryPath)}" info.destinationDirectory = os.path.join(cls.bundleFrameworkDirectory, info.frameworkName, info.binaryDirectory) - + info.sourceResourcesDirectory = os.path.join(info.frameworkPath, "Resources") info.sourceContentsDirectory = os.path.join(info.frameworkPath, "Contents") info.sourceVersionContentsDirectory = os.path.join(info.frameworkPath, "Versions", info.version, "Contents") info.destinationResourcesDirectory = os.path.join(cls.bundleFrameworkDirectory, info.frameworkName, "Resources") info.destinationVersionContentsDirectory = os.path.join(cls.bundleFrameworkDirectory, info.frameworkName, "Versions", info.version, "Contents") - + return info class ApplicationBundleInfo(object): @@ -289,45 +289,45 @@ def copyFramework(framework: FrameworkInfo, path: str, verbose: int) -> Optional def deployFrameworks(frameworks: list[FrameworkInfo], bundlePath: str, binaryPath: str, strip: bool, verbose: int, deploymentInfo: Optional[DeploymentInfo] = None) -> DeploymentInfo: if deploymentInfo is None: deploymentInfo = DeploymentInfo() - + while len(frameworks) > 0: framework = frameworks.pop(0) deploymentInfo.deployedFrameworks.append(framework.frameworkName) - + print("Processing", framework.frameworkName, "...") - + # Get the Qt path from one of the Qt frameworks if deploymentInfo.qtPath is None and framework.isQtFramework(): deploymentInfo.detectQtPath(framework.frameworkDirectory) - + if framework.installName.startswith("@executable_path") or framework.installName.startswith(bundlePath): print(framework.frameworkName, "already deployed, skipping.") continue - + # install_name_tool the new id into the binary changeInstallName(framework.installName, framework.deployedInstallName, binaryPath, verbose) - + # Copy framework to app bundle. deployedBinaryPath = copyFramework(framework, bundlePath, verbose) # Skip the rest if already was deployed. if deployedBinaryPath is None: continue - + if strip: runStrip(deployedBinaryPath, verbose) - + # install_name_tool it a new id. changeIdentification(framework.deployedInstallName, deployedBinaryPath, verbose) # Check for framework dependencies dependencies = getFrameworks(deployedBinaryPath, verbose, rpath=framework.frameworkDirectory) - + for dependency in dependencies: changeInstallName(dependency.installName, dependency.deployedInstallName, deployedBinaryPath, verbose) - + # Deploy framework if necessary. if dependency.frameworkName not in deploymentInfo.deployedFrameworks and dependency not in frameworks: frameworks.append(dependency) - + return deploymentInfo def deployFrameworksForAppBundle(applicationBundle: ApplicationBundleInfo, strip: bool, verbose: int) -> DeploymentInfo: @@ -355,29 +355,29 @@ def deployPlugins(appBundleInfo: ApplicationBundleInfo, deploymentInfo: Deployme continue plugins.append((pluginDirectory, pluginName)) - + for pluginDirectory, pluginName in plugins: print("Processing plugin", os.path.join(pluginDirectory, pluginName), "...") - + sourcePath = os.path.join(deploymentInfo.pluginPath, pluginDirectory, pluginName) destinationDirectory = os.path.join(appBundleInfo.pluginPath, pluginDirectory) if not os.path.exists(destinationDirectory): os.makedirs(destinationDirectory) - + destinationPath = os.path.join(destinationDirectory, pluginName) shutil.copy2(sourcePath, destinationPath) if verbose: print("Copied:", sourcePath) print(" to:", destinationPath) - + if strip: runStrip(destinationPath, verbose) - + dependencies = getFrameworks(destinationPath, verbose) - + for dependency in dependencies: changeInstallName(dependency.installName, dependency.deployedInstallName, destinationPath, verbose) - + # Deploy framework if necessary. if dependency.frameworkName not in deploymentInfo.deployedFrameworks: deployFrameworks([dependency], appBundleInfo.path, destinationPath, strip, verbose, deploymentInfo) @@ -446,7 +446,7 @@ except RuntimeError as e: if config.plugins: print("+ Deploying plugins +") - + try: deployPlugins(applicationBundle, deploymentInfo, config.strip, verbose) except RuntimeError as e: diff --git a/contrib/qos/tc.sh b/contrib/qos/tc.sh index 2c48fc2a268..4e4237084e1 100755 --- a/contrib/qos/tc.sh +++ b/contrib/qos/tc.sh @@ -34,9 +34,9 @@ tc filter add dev ${IF} parent 1: protocol ip prio 1 handle 1 fw classid 1:10 tc filter add dev ${IF} parent 1: protocol ip prio 2 handle 2 fw classid 1:11 if [ -n "${LOCALNET_V6}" ] ; then - # v6 cannot have the same priority value as v4 - tc filter add dev ${IF} parent 1: protocol ipv6 prio 3 handle 1 fw classid 1:10 - tc filter add dev ${IF} parent 1: protocol ipv6 prio 4 handle 2 fw classid 1:11 + # v6 cannot have the same priority value as v4 + tc filter add dev ${IF} parent 1: protocol ipv6 prio 3 handle 1 fw classid 1:10 + tc filter add dev ${IF} parent 1: protocol ipv6 prio 4 handle 2 fw classid 1:11 fi #delete any existing rules @@ -57,6 +57,6 @@ iptables -t mangle -A OUTPUT -p tcp -m tcp --dport 8333 ! -d ${LOCALNET_V4} -j M iptables -t mangle -A OUTPUT -p tcp -m tcp --sport 8333 ! -d ${LOCALNET_V4} -j MARK --set-mark 0x2 if [ -n "${LOCALNET_V6}" ] ; then - ip6tables -t mangle -A OUTPUT -p tcp -m tcp --dport 8333 ! -d ${LOCALNET_V6} -j MARK --set-mark 0x4 - ip6tables -t mangle -A OUTPUT -p tcp -m tcp --sport 8333 ! -d ${LOCALNET_V6} -j MARK --set-mark 0x4 + ip6tables -t mangle -A OUTPUT -p tcp -m tcp --dport 8333 ! -d ${LOCALNET_V6} -j MARK --set-mark 0x4 + ip6tables -t mangle -A OUTPUT -p tcp -m tcp --sport 8333 ! -d ${LOCALNET_V6} -j MARK --set-mark 0x4 fi diff --git a/contrib/verify-commits/gpg.sh b/contrib/verify-commits/gpg.sh index 3579a70a699..bcb117f19a0 100755 --- a/contrib/verify-commits/gpg.sh +++ b/contrib/verify-commits/gpg.sh @@ -9,27 +9,27 @@ if [ "$BITCOIN_VERIFY_COMMITS_ALLOW_SHA1" = 1 ]; then printf '%s\n' "$INPUT" | gpg --trust-model always "$@" 2>/dev/null exit $? else - # Note how we've disabled SHA1 with the --weak-digest option, disabling - # signatures - including selfsigs - that use SHA1. While you might think that - # collision attacks shouldn't be an issue as they'd be an attack on yourself, - # in fact because what's being signed is a commit object that's - # semi-deterministically generated by untrusted input (the pull-req) in theory - # an attacker could construct a pull-req that results in a commit object that - # they've created a collision for. Not the most likely attack, but preventing - # it is pretty easy so we do so as a "belt-and-suspenders" measure. - for LINE in $(gpg --version); do - case "$LINE" in - "gpg (GnuPG) 1.4.1"*|"gpg (GnuPG) 2.0."*) - echo "Please upgrade to at least gpg 2.1.10 to check for weak signatures" > /dev/stderr - printf '%s\n' "$INPUT" | gpg --trust-model always "$@" 2>/dev/null - exit $? - ;; - # We assume if you're running 2.1+, you're probably running 2.1.10+ - # gpg will fail otherwise - # We assume if you're running 1.X, it is either 1.4.1X or 1.4.20+ - # gpg will fail otherwise - esac - done - printf '%s\n' "$INPUT" | gpg --trust-model always --weak-digest sha1 "$@" 2>/dev/null - exit $? + # Note how we've disabled SHA1 with the --weak-digest option, disabling + # signatures - including selfsigs - that use SHA1. While you might think that + # collision attacks shouldn't be an issue as they'd be an attack on yourself, + # in fact because what's being signed is a commit object that's + # semi-deterministically generated by untrusted input (the pull-req) in theory + # an attacker could construct a pull-req that results in a commit object that + # they've created a collision for. Not the most likely attack, but preventing + # it is pretty easy so we do so as a "belt-and-suspenders" measure. + for LINE in $(gpg --version); do + case "$LINE" in + "gpg (GnuPG) 1.4.1"*|"gpg (GnuPG) 2.0."*) + echo "Please upgrade to at least gpg 2.1.10 to check for weak signatures" > /dev/stderr + printf '%s\n' "$INPUT" | gpg --trust-model always "$@" 2>/dev/null + exit $? + ;; + # We assume if you're running 2.1+, you're probably running 2.1.10+ + # gpg will fail otherwise + # We assume if you're running 1.X, it is either 1.4.1X or 1.4.20+ + # gpg will fail otherwise + esac + done + printf '%s\n' "$INPUT" | gpg --trust-model always --weak-digest sha1 "$@" 2>/dev/null + exit $? fi diff --git a/test/lint/test_runner/src/lint_text_format.rs b/test/lint/test_runner/src/lint_text_format.rs index 1f7d540d911..120e9a71db1 100644 --- a/test/lint/test_runner/src/lint_text_format.rs +++ b/test/lint/test_runner/src/lint_text_format.rs @@ -18,13 +18,9 @@ fn get_pathspecs_exclude_whitespace() -> Vec { "contrib/windeploy/win-codesign.cert", "doc/README_windows.txt", // Temporary excludes, or existing violations - "contrib/init/bitcoind.openrc", - "contrib/macdeploy/macdeployqtplus", "src/qt/res/src/*.svg", "test/functional/test_framework/crypto/ellswift_decode_test_vectors.csv", "test/functional/test_framework/crypto/xswiftec_inv_test_vectors.csv", - "contrib/qos/tc.sh", - "contrib/verify-commits/gpg.sh", "test/lint/git-subtree-check.sh", ] .iter() From ecefc1292778f41dbaffe9615cb2d99d63d54d05 Mon Sep 17 00:00:00 2001 From: fanquake Date: Mon, 16 Mar 2026 20:00:22 +0800 Subject: [PATCH 3/5] lint: fix lint issue in lint script Replace the tabs with spaces. --- test/lint/git-subtree-check.sh | 54 +++++++++---------- test/lint/test_runner/src/lint_text_format.rs | 1 - 2 files changed, 27 insertions(+), 28 deletions(-) diff --git a/test/lint/git-subtree-check.sh b/test/lint/git-subtree-check.sh index 1eb83401f2c..534fadbad71 100755 --- a/test/lint/git-subtree-check.sh +++ b/test/lint/git-subtree-check.sh @@ -47,33 +47,33 @@ fi # Taken from git-subtree (Copyright (C) 2009 Avery Pennarun ) find_latest_squash() { - dir="$1" - sq= - main= - sub= - git log --grep="^git-subtree-dir: $dir/*\$" \ - --pretty=format:'START %H%n%s%n%n%b%nEND%n' "$COMMIT" | - while read a b _; do - case "$a" in - START) sq="$b" ;; - git-subtree-mainline:) main="$b" ;; - git-subtree-split:) sub="$b" ;; - END) - if [ -n "$sub" ]; then - if [ -n "$main" ]; then - # a rejoin commit? - # Pretend its sub was a squash. - sq="$sub" - fi - echo "$sq" "$sub" - break - fi - sq= - main= - sub= - ;; - esac - done + dir="$1" + sq= + main= + sub= + git log --grep="^git-subtree-dir: $dir/*\$" \ + --pretty=format:'START %H%n%s%n%n%b%nEND%n' "$COMMIT" | + while read a b _; do + case "$a" in + START) sq="$b" ;; + git-subtree-mainline:) main="$b" ;; + git-subtree-split:) sub="$b" ;; + END) + if [ -n "$sub" ]; then + if [ -n "$main" ]; then + # a rejoin commit? + # Pretend its sub was a squash. + sq="$sub" + fi + echo "$sq" "$sub" + break + fi + sq= + main= + sub= + ;; + esac + done } # find latest subtree update diff --git a/test/lint/test_runner/src/lint_text_format.rs b/test/lint/test_runner/src/lint_text_format.rs index 120e9a71db1..98e27d8ce10 100644 --- a/test/lint/test_runner/src/lint_text_format.rs +++ b/test/lint/test_runner/src/lint_text_format.rs @@ -21,7 +21,6 @@ fn get_pathspecs_exclude_whitespace() -> Vec { "src/qt/res/src/*.svg", "test/functional/test_framework/crypto/ellswift_decode_test_vectors.csv", "test/functional/test_framework/crypto/xswiftec_inv_test_vectors.csv", - "test/lint/git-subtree-check.sh", ] .iter() .map(|s| format!(":(exclude){s}")), From 8864917d8bcb856db530f4b6e84a80bd77ed5035 Mon Sep 17 00:00:00 2001 From: fanquake Date: Mon, 16 Mar 2026 19:43:47 +0800 Subject: [PATCH 4/5] lint: add missing ipc/test to grep_boost_fixture_test_suite --- test/lint/lint-tests.py | 1 + 1 file changed, 1 insertion(+) diff --git a/test/lint/lint-tests.py b/test/lint/lint-tests.py index 919912dc692..c7354bc4122 100755 --- a/test/lint/lint-tests.py +++ b/test/lint/lint-tests.py @@ -20,6 +20,7 @@ def grep_boost_fixture_test_suite(): "-E", r"^BOOST_FIXTURE_TEST_SUITE\(", "--", + "src/ipc/test/**.cpp", "src/test/**.cpp", "src/wallet/test/**.cpp", ] From f55c891a65ed76e593be4108939cf6998036646a Mon Sep 17 00:00:00 2001 From: fanquake Date: Mon, 16 Mar 2026 20:15:10 +0800 Subject: [PATCH 5/5] lint: more reuse of SHARED_EXCLUDED_SUBTREES --- test/lint/lint-include-guards.py | 1 - test/lint/lint-locale-dependence.py | 9 +++------ test/lint/lint_ignore_dirs.py | 1 + 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/test/lint/lint-include-guards.py b/test/lint/lint-include-guards.py index dbbf0325c4e..4518f458d51 100755 --- a/test/lint/lint-include-guards.py +++ b/test/lint/lint-include-guards.py @@ -19,7 +19,6 @@ HEADER_ID_PREFIX = 'BITCOIN_' HEADER_ID_SUFFIX = '_H' EXCLUDE_FILES_WITH_PREFIX = ['contrib/devtools/bitcoin-tidy', - 'src/crypto/ctaes', 'src/tinyformat.h', 'src/bench/nanobench.h', 'src/test/fuzz/FuzzedDataProvider.h'] + SHARED_EXCLUDED_SUBTREES diff --git a/test/lint/lint-locale-dependence.py b/test/lint/lint-locale-dependence.py index c6a64587091..4957c694dac 100755 --- a/test/lint/lint-locale-dependence.py +++ b/test/lint/lint-locale-dependence.py @@ -40,6 +40,8 @@ import sys from subprocess import check_output, CalledProcessError +from lint_ignore_dirs import SHARED_EXCLUDED_SUBTREES + KNOWN_VIOLATIONS = [ "src/dbwrapper.cpp:.*vsnprintf", @@ -50,13 +52,8 @@ KNOWN_VIOLATIONS = [ ] REGEXP_EXTERNAL_DEPENDENCIES_EXCLUSIONS = [ - "src/crypto/ctaes/", - "src/ipc/libmultiprocess/", - "src/leveldb/", - "src/secp256k1/", - "src/minisketch/", "src/tinyformat.h", -] +] + SHARED_EXCLUDED_SUBTREES LOCALE_DEPENDENT_FUNCTIONS = [ "alphasort", # LC_COLLATE (via strcoll) diff --git a/test/lint/lint_ignore_dirs.py b/test/lint/lint_ignore_dirs.py index 838f01b6664..60637832309 100644 --- a/test/lint/lint_ignore_dirs.py +++ b/test/lint/lint_ignore_dirs.py @@ -9,4 +9,5 @@ SHARED_EXCLUDED_SUBTREES = ["src/leveldb/", "src/secp256k1/", "src/minisketch/", "src/ipc/libmultiprocess/", + "src/crypto/ctaes/", ]