diff --git a/Makefile b/Makefile index c328f6da19..0a060801d2 100644 --- a/Makefile +++ b/Makefile @@ -69,6 +69,7 @@ endif ## install-standalone: Build and install the celestia-appd binary into the $GOPATH/bin directory. This target does not install the multiplexer. install-standalone: @echo "--> Installing celestia-appd" + @bash scripts/check_cpu_features.sh @go install $(BUILD_FLAGS_STANDALONE) ./cmd/celestia-appd .PHONY: install-standalone @@ -76,6 +77,7 @@ install-standalone: # TODO: Improve logic here and in goreleaser to make it future proof and less expensive. install: download-v3-binaries download-v4-binaries download-v5-binaries @echo "--> Installing celestia-appd with multiplexer support" + @bash scripts/check_cpu_features.sh @go install $(BUILD_FLAGS_MULTIPLEXER) ./cmd/celestia-appd .PHONY: install diff --git a/cmd/celestia-appd/cmd/cpu_features.go b/cmd/celestia-appd/cmd/cpu_features.go new file mode 100644 index 0000000000..ba02d49cb7 --- /dev/null +++ b/cmd/celestia-appd/cmd/cpu_features.go @@ -0,0 +1,85 @@ +package cmd + +import ( + "os" + "runtime" + "strings" + + "cosmossdk.io/log" + "github.com/spf13/cobra" +) + +const FlagCPUFeaturesCheck = "force-no-cpu-features" + +// checkCPUFeatures checks if CPU supports GFNI and SHA_NI extensions. +func checkCPUFeatures(command *cobra.Command, logger log.Logger) error { + const ( + warning = ` +CPU Performance Warning: Missing hardware acceleration features + +Your CPU does not support one or more of the following hardware acceleration features: +- GFNI (Galois Field New Instructions) +- SHA_NI (Secure Hash Algorithm New Instructions) + +These features significantly improve cryptographic performance for blockchain operations. + +Note: These features are not required for the 32MB/6s block configuration but will become +essential when the network transitions to 128MB/6s blocks. Validators should prepare by upgrading +their hardware to ensure optimal performance during future network upgrades. + +To check what features your CPU supports: +grep -o -E 'sha_ni|gfni' /proc/cpuinfo + +Modern Intel CPUs (10th gen+) and AMD CPUs (Zen 4+) typically support these features. +If you are running this node, consider upgrading to a CPU with these features. + +This node will continue to run, but may experience reduced performance for cryptographic operations. +If you need to bypass this check, use the --force-no-cpu-features flag. +` + ) + + isCPUFeaturesCheckDisabled, err := command.Flags().GetBool(FlagCPUFeaturesCheck) + if err != nil { + return err + } + if isCPUFeaturesCheckDisabled { + return nil + } + + // Only check on Linux where /proc/cpuinfo is available + if runtime.GOOS != "linux" { + // Skip check silently for non-Linux OSes (e.g., macOS, Windows, BSD) + return nil + } + + file, err := os.ReadFile("/proc/cpuinfo") + if err != nil { + logger.Warn(warning) + // TODO: enable when we want to start enforcing the new CPU features. + // return fmt.Errorf("failed to read file '/proc/cpuinfo' %w", err) + return nil + } + + cpuInfo := string(file) + hasGFNI := strings.Contains(cpuInfo, "gfni") + hasSHANI := strings.Contains(cpuInfo, "sha_ni") + + if !hasGFNI || !hasSHANI { + missingFeatures := []string{} + if !hasGFNI { + missingFeatures = append(missingFeatures, "GFNI") + } + if !hasSHANI { + missingFeatures = append(missingFeatures, "SHA_NI") + } + logger.Warn(warning, "missing_features", strings.Join(missingFeatures, ", ")) + } + + if !hasGFNI { + // TODO: enable when we want to start enforcing the new CPU features. + // return fmt.Errorf("missing GFNI") + return nil + } + + return nil +} diff --git a/cmd/celestia-appd/cmd/root.go b/cmd/celestia-appd/cmd/root.go index 7baea367ba..bb26715b53 100644 --- a/cmd/celestia-appd/cmd/root.go +++ b/cmd/celestia-appd/cmd/root.go @@ -136,7 +136,7 @@ func initRootCommand(rootCommand *cobra.Command, capp *app.App) { modifyRootCommand(rootCommand) // Add hooks run prior to the start command - if err := addPreStartHooks(rootCommand, checkBBR); err != nil { + if err := addPreStartHooks(rootCommand, checkBBR, checkCPUFeatures); err != nil { panic(fmt.Errorf("failed to add pre-start hooks: %w", err)) } } @@ -155,6 +155,7 @@ func addStartFlags(startCmd *cobra.Command) { startCmd.Flags().Duration(DelayedPrecommitTimeoutFlag, 0, "Override the DelayedPrecommitTimeout to control block time. Note: only for testing purposes.") startCmd.Flags().Bool(FlagForceNoBBR, false, "bypass the requirement to use bbr locally") + startCmd.Flags().Bool(FlagCPUFeaturesCheck, false, "bypass CPU feature checks") } // replaceLogger optionally replaces the logger with a file logger if the flag diff --git a/scripts/check_cpu_features.sh b/scripts/check_cpu_features.sh new file mode 100755 index 0000000000..72f49fb06e --- /dev/null +++ b/scripts/check_cpu_features.sh @@ -0,0 +1,73 @@ +#!/bin/bash + +# Script to check CPU features for celestia-app +# Checks for GFNI and SHA_NI CPU features that improve cryptographic performance + +check_cpu_features() { + local warning=" +CPU Performance Warning: Missing hardware acceleration features + +Your CPU does not support one or more of the following hardware acceleration features: +- GFNI (Galois Field New Instructions) +- SHA_NI (Secure Hash Algorithm New Instructions) + +These features significantly improve cryptographic performance for blockchain operations. + +Note: These features are not required for the 32MB/6s block configuration but will become +essential when the network transitions to 128MB/6s blocks. Validators should prepare by upgrading +their hardware to ensure optimal performance during future network upgrades. + +To check what features your CPU supports: +grep -o -E 'sha_ni|gfni' /proc/cpuinfo + +Modern Intel CPUs (10th gen+) and AMD CPUs (Zen 3+) typically support these features. +If you are running this node in production, consider upgrading to a CPU with these features. + +This node will continue to run, but may experience reduced performance for cryptographic operations. +" + + # Only check on Linux where /proc/cpuinfo is available + if [[ "$OSTYPE" != "linux-gnu"* ]]; then + # Skip check silently for non-Linux OSes (e.g., macOS, Windows, BSD) + return 0 + fi + + # Check if /proc/cpuinfo exists and is readable + if [[ ! -f /proc/cpuinfo ]] || [[ ! -r /proc/cpuinfo ]]; then + echo "Warning: Could not read /proc/cpuinfo to check CPU features" + return 0 + fi + + # Check for CPU features + local cpu_features + cpu_features=$(grep -o -E 'sha_ni|gfni' /proc/cpuinfo 2>/dev/null | sort -u) + + local has_gfni=false + local has_sha_ni=false + local missing_features=() + + if echo "$cpu_features" | grep -q "gfni"; then + has_gfni=true + else + missing_features+=("GFNI") + fi + + if echo "$cpu_features" | grep -q "sha_ni"; then + has_sha_ni=true + else + missing_features+=("SHA_NI") + fi + + # If any features are missing, show warning + if [[ ${#missing_features[@]} -gt 0 ]]; then + echo "$warning" + printf "Missing features: %s\n\n" "$(IFS=', '; echo "${missing_features[*]}")" + fi + + return 0 +} + +# Run the check if script is executed directly +if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then + check_cpu_features +fi