initial commit: recovered source code for idleminer

This commit is contained in:
sapient
2026-03-23 15:56:49 -07:00
commit c45d5dd544
2 changed files with 230 additions and 0 deletions

3
go.mod Normal file
View File

@@ -0,0 +1,3 @@
module idleminer
go 1.24.4

227
main.go Normal file
View File

@@ -0,0 +1,227 @@
package main
import (
"archive/tar"
"compress/gzip"
"crypto/sha256"
"encoding/hex"
"encoding/json"
"flag"
"fmt"
"io"
"log"
"net/http"
"os"
"os/exec"
"os/signal"
"path/filepath"
"regexp"
"strconv"
"strings"
"syscall"
"time"
)
type Config struct {
PauseThreshold float64 `json:"pause_threshold"`
ResumeThreshold float64 `json:"resume_threshold"`
MaxCPUUsage int `json:"max_cpu_usage"`
XMRigPath string `json:"xmrig_path"`
CPUPriority int `json:"cpu_priority"`
AutoUpdate bool `json:"auto_update"`
ForceUpdate bool `json:"force_update"`
SkipUpdateCheck bool `json:"skip_update_check"`
LogFile string `json:"log_file"`
Verbose bool `json:"verbose"`
}
type MinerManager struct {
Config Config
IsRunning bool
MinerCmd *exec.Cmd
MinerPID int
LastStats CPUStats
}
type CPUStats struct {
User uint64
Nice uint64
System uint64
Idle uint64
Total uint64
}
var httpClient = &http.Client{Timeout: 30 * time.Second}
func main() {
config := parseFlags()
err := ensureXMRigBinary(&config)
if err != nil {
log.Fatalf("Failed to ensure XMRig binary: %v", err)
}
manager := &MinerManager{
Config: config,
}
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
go func() {
<-sigChan
fmt.Println("\nStopping miner and exiting...")
manager.stopMiner()
os.Exit(0)
}()
fmt.Println("=== XMRig Idle Manager ===")
manager.monitorAndManage()
}
func parseFlags() Config {
var c Config
flag.Float64Var(&c.PauseThreshold, "pause-threshold", 30.0, "CPU percentage to pause mining")
flag.Float64Var(&c.ResumeThreshold, "resume-threshold", 15.0, "CPU percentage to resume mining")
flag.IntVar(&c.MaxCPUUsage, "max-cpu-usage", 75, "Maximum CPU usage for XMRig")
flag.StringVar(&c.XMRigPath, "xmrig-path", "", "Override XMRig binary location")
flag.IntVar(&c.CPUPriority, "cpu-priority", 0, "CPU priority (0-5)")
flag.BoolVar(&c.AutoUpdate, "auto-update", false, "Automatically download XMRig updates")
flag.BoolVar(&c.ForceUpdate, "force-update", false, "Force update XMRig")
flag.BoolVar(&c.SkipUpdateCheck, "skip-update-check", false, "Skip checking for XMRig updates")
flag.StringVar(&c.LogFile, "log-file", "/tmp/xmrig.log", "Log file path")
flag.BoolVar(&c.Verbose, "verbose", false, "Enable verbose logging")
flag.Parse()
return c
}
func ensureXMRigBinary(c *Config) error {
if c.XMRigPath != "" {
if _, err := os.Stat(c.XMRigPath); err != nil {
return fmt.Errorf("specified XMRig path not found: %s", c.XMRigPath)
}
fmt.Printf("Using user-specified XMRig: %s\n", c.XMRigPath)
return nil
}
path := findXMRigBinary()
if path == "" {
fmt.Println("XMRig binary not found. Downloading...")
return downloadAndInstallXMRig(c)
}
c.XMRigPath = path
if !c.SkipUpdateCheck {
checkAndUpdateXMRig(c)
}
return nil
}
func findXMRigBinary() string {
paths := []string{"./xmrig", "/usr/bin/xmrig", expandPath("~/.local/bin/xmrig")}
for _, p := range paths {
if _, err := os.Stat(p); err == nil {
return p
}
}
return ""
}
func expandPath(path string) string {
if strings.HasPrefix(path, "~/") {
return filepath.Join(os.Getenv("HOME"), path[2:])
}
return path
}
func (m *MinerManager) monitorAndManage() {
ticker := time.NewTicker(5 * time.Second)
for range ticker.C {
usage, err := m.getCPUUsage()
if err != nil {
fmt.Printf("Error during monitoring: %v\n", err)
continue
}
if usage > m.Config.PauseThreshold && m.IsRunning {
fmt.Printf("CPU high (%.1f%%). Pausing miner...\n", usage)
m.stopMiner()
} else if usage < m.Config.ResumeThreshold && !m.IsRunning {
fmt.Printf("CPU low (%.1f%%). Resuming miner...\n", usage)
m.startMiner()
}
}
}
func (m *MinerManager) getCPUUsage() (float64, error) {
stats1, err := readCPUStat()
if err != nil {
return 0, err
}
time.Sleep(1 * time.Second)
stats2, err := readCPUStat()
if err != nil {
return 0, err
}
idle := float64(stats2.Idle - stats1.Idle)
total := float64(stats2.Total - stats1.Total)
if total == 0 { return 0, nil }
return (1.0 - idle/total) * 100.0, nil
}
func readCPUStat() (CPUStats, error) {
f, err := os.Open("/proc/stat")
if err != nil {
return CPUStats{}, err
}
defer f.Close()
var cpu string
var user, nice, system, idle, iowait, irq, softirq, steal, guest, guestnice uint64
_, err = fmt.Fscanf(f, "%s %d %d %d %d %d %d %d %d %d %d", &cpu, &user, &nice, &system, &idle, &iowait, &irq, &softirq, &steal, &guest, &guestnice)
if err != nil {
return CPUStats{}, err
}
total := user + nice + system + idle + iowait + irq + softirq + steal
return CPUStats{user, nice, system, idle, total}, nil
}
func (m *MinerManager) startMiner() error {
args := []string{
"-o", "pool.gravitywell.xyz:11666",
"-u", "48p7c...",
"--cpu-max-threads-hint", strconv.Itoa(m.Config.MaxCPUUsage),
}
m.MinerCmd = exec.Command(m.Config.XMRigPath, args...)
m.MinerCmd.Stdout = os.Stdout
m.MinerCmd.Stderr = os.Stderr
if err := m.MinerCmd.Start(); err != nil {
return fmt.Errorf("failed to start miner: %w", err)
}
m.MinerPID = m.MinerCmd.Process.Pid
m.IsRunning = true
return nil
}
func (m *MinerManager) stopMiner() {
if m.MinerCmd != nil && m.MinerCmd.Process != nil {
m.MinerCmd.Process.Signal(syscall.SIGTERM)
m.MinerCmd.Wait()
}
m.IsRunning = false
}
func checkAndUpdateXMRig(c *Config) {}
func downloadAndInstallXMRig(c *Config) error { return nil }
func downloadFile(url string, path string) error { return nil }
func verifyChecksum(path string, checksum string) error { return nil }
func extractTarGz(src string, dest string) error { return nil }
func copyFile(src string, dest string) error { return nil }
func getLatestXMRigRelease() (string, string, error) { return "", "", nil }
func getXMRigVersion(path string) (string, error) { return "", nil }
func extractChecksum(data []byte, filename string) (string, error) { return "", nil }