Merge commit 'd803bfe2b1fe7f5e219e50ac20d6801a0a58ac75' as 'vendor/ruvector'

This commit is contained in:
ruv
2026-02-28 14:39:40 -05:00
7854 changed files with 3522914 additions and 0 deletions

View File

@@ -0,0 +1,820 @@
#!/usr/bin/env node
/**
* Edge-Net Network Module
*
* Handles:
* - Bootstrap node discovery
* - Peer announcement protocol
* - QDAG contribution recording
* - Contribution verification
* - P2P message routing
*/
import { createHash, randomBytes } from 'crypto';
import { promises as fs } from 'fs';
import { homedir } from 'os';
import { join, dirname } from 'path';
import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
// Network configuration
const NETWORK_CONFIG = {
// Bootstrap nodes (DHT entry points)
bootstrapNodes: [
{ id: 'bootstrap-1', host: 'edge-net.ruvector.dev', port: 9000 },
{ id: 'bootstrap-2', host: 'edge-net-2.ruvector.dev', port: 9000 },
{ id: 'bootstrap-3', host: 'edge-net-3.ruvector.dev', port: 9000 },
],
// Local network simulation for offline/testing
localSimulation: true,
// Peer discovery interval (ms)
discoveryInterval: 30000,
// Heartbeat interval (ms)
heartbeatInterval: 10000,
// Max peers per node
maxPeers: 50,
// QDAG sync interval (ms)
qdagSyncInterval: 5000,
};
// Data directories
function getNetworkDir() {
return join(homedir(), '.ruvector', 'network');
}
function getPeersFile() {
return join(getNetworkDir(), 'peers.json');
}
function getQDAGFile() {
return join(getNetworkDir(), 'qdag.json');
}
// Ensure directories exist
async function ensureDirectories() {
await fs.mkdir(getNetworkDir(), { recursive: true });
}
/**
* Peer Discovery and Management
*/
export class PeerManager {
constructor(localIdentity) {
this.localIdentity = localIdentity;
this.peers = new Map();
this.bootstrapNodes = NETWORK_CONFIG.bootstrapNodes;
this.discoveryInterval = null;
this.heartbeatInterval = null;
}
async initialize() {
await ensureDirectories();
await this.loadPeers();
// Start discovery and heartbeat
if (!NETWORK_CONFIG.localSimulation) {
this.startDiscovery();
this.startHeartbeat();
}
return this;
}
async loadPeers() {
try {
const data = await fs.readFile(getPeersFile(), 'utf-8');
const peers = JSON.parse(data);
for (const peer of peers) {
this.peers.set(peer.piKey, peer);
}
console.log(` 📡 Loaded ${this.peers.size} known peers`);
} catch (err) {
// No peers file yet
console.log(' 📡 Starting fresh peer list');
}
}
async savePeers() {
const peers = Array.from(this.peers.values());
await fs.writeFile(getPeersFile(), JSON.stringify(peers, null, 2));
}
/**
* Announce this node to the network
*/
async announce() {
const announcement = {
type: 'announce',
piKey: this.localIdentity.piKey,
publicKey: this.localIdentity.publicKey,
siteId: this.localIdentity.siteId,
timestamp: Date.now(),
capabilities: ['compute', 'storage', 'verify'],
version: '0.1.1',
};
// Sign the announcement
announcement.signature = this.signMessage(JSON.stringify(announcement));
// In local simulation, just record ourselves
if (NETWORK_CONFIG.localSimulation) {
await this.registerPeer({
...announcement,
lastSeen: Date.now(),
verified: true,
});
return announcement;
}
// In production, broadcast to bootstrap nodes
for (const bootstrap of this.bootstrapNodes) {
try {
await this.sendToNode(bootstrap, announcement);
} catch (err) {
// Bootstrap node unreachable
}
}
return announcement;
}
/**
* Register a peer in the local peer table
*/
async registerPeer(peer) {
const existing = this.peers.get(peer.piKey);
if (existing) {
// Update last seen
existing.lastSeen = Date.now();
existing.verified = peer.verified || existing.verified;
} else {
// New peer
this.peers.set(peer.piKey, {
piKey: peer.piKey,
publicKey: peer.publicKey,
siteId: peer.siteId,
capabilities: peer.capabilities || [],
firstSeen: Date.now(),
lastSeen: Date.now(),
verified: peer.verified || false,
contributions: 0,
});
console.log(` 🆕 New peer: ${peer.siteId} (π:${peer.piKey.slice(0, 8)})`);
}
await this.savePeers();
}
/**
* Get active peers (seen in last 5 minutes)
*/
getActivePeers() {
const cutoff = Date.now() - 300000; // 5 minutes
return Array.from(this.peers.values()).filter(p => p.lastSeen > cutoff);
}
/**
* Get all known peers
*/
getAllPeers() {
return Array.from(this.peers.values());
}
/**
* Verify a peer's identity
*/
async verifyPeer(peer) {
// Request identity proof
const challenge = randomBytes(32).toString('hex');
const response = await this.requestProof(peer, challenge);
if (response && this.verifyProof(peer.publicKey, challenge, response)) {
peer.verified = true;
await this.savePeers();
return true;
}
return false;
}
/**
* Sign a message with local identity
*/
signMessage(message) {
// Simplified signing (in production uses Ed25519)
const hash = createHash('sha256')
.update(this.localIdentity.piKey)
.update(message)
.digest('hex');
return hash;
}
/**
* Verify a signature
*/
verifySignature(publicKey, message, signature) {
// Simplified verification
return signature && signature.length === 64;
}
startDiscovery() {
this.discoveryInterval = setInterval(async () => {
await this.discoverPeers();
}, NETWORK_CONFIG.discoveryInterval);
}
startHeartbeat() {
this.heartbeatInterval = setInterval(async () => {
await this.announce();
}, NETWORK_CONFIG.heartbeatInterval);
}
async discoverPeers() {
// Request peer lists from known peers
for (const peer of this.getActivePeers()) {
try {
const newPeers = await this.requestPeerList(peer);
for (const newPeer of newPeers) {
await this.registerPeer(newPeer);
}
} catch (err) {
// Peer unreachable
}
}
}
// Placeholder network methods (implemented in production with WebRTC/WebSocket)
async sendToNode(node, message) {
// In production: WebSocket/WebRTC connection
return { ok: true };
}
async requestProof(peer, challenge) {
// In production: Request signed proof
return this.signMessage(challenge);
}
verifyProof(publicKey, challenge, response) {
return response && response.length > 0;
}
async requestPeerList(peer) {
return [];
}
stop() {
if (this.discoveryInterval) clearInterval(this.discoveryInterval);
if (this.heartbeatInterval) clearInterval(this.heartbeatInterval);
}
}
/**
* QDAG (Quantum DAG) Contribution Ledger
*
* A directed acyclic graph that records all contributions
* with cryptographic verification and consensus
*/
export class QDAGLedger {
constructor(peerManager) {
this.peerManager = peerManager;
this.nodes = new Map(); // DAG nodes
this.tips = new Set(); // Current tips (unconfirmed)
this.confirmed = new Set(); // Confirmed nodes
this.pendingContributions = [];
this.syncInterval = null;
}
async initialize() {
await this.loadLedger();
if (!NETWORK_CONFIG.localSimulation) {
this.startSync();
}
return this;
}
async loadLedger() {
try {
const data = await fs.readFile(getQDAGFile(), 'utf-8');
const ledger = JSON.parse(data);
for (const node of ledger.nodes || []) {
this.nodes.set(node.id, node);
}
this.tips = new Set(ledger.tips || []);
this.confirmed = new Set(ledger.confirmed || []);
console.log(` 📊 Loaded QDAG: ${this.nodes.size} nodes, ${this.confirmed.size} confirmed`);
} catch (err) {
// Create genesis node
const genesis = this.createNode({
type: 'genesis',
timestamp: Date.now(),
message: 'Edge-Net QDAG Genesis',
}, []);
this.nodes.set(genesis.id, genesis);
this.tips.add(genesis.id);
this.confirmed.add(genesis.id);
await this.saveLedger();
console.log(' 📊 Created QDAG genesis block');
}
}
async saveLedger() {
const ledger = {
nodes: Array.from(this.nodes.values()),
tips: Array.from(this.tips),
confirmed: Array.from(this.confirmed),
savedAt: Date.now(),
};
await fs.writeFile(getQDAGFile(), JSON.stringify(ledger, null, 2));
}
/**
* Create a new QDAG node
*/
createNode(data, parents) {
const nodeData = {
...data,
parents: parents,
timestamp: Date.now(),
};
const id = createHash('sha256')
.update(JSON.stringify(nodeData))
.digest('hex')
.slice(0, 16);
return {
id,
...nodeData,
weight: 1,
confirmations: 0,
};
}
/**
* Record a contribution to the QDAG
*/
async recordContribution(contribution) {
// Select parent tips (2 parents for DAG structure)
const parents = this.selectTips(2);
// Create contribution node
const node = this.createNode({
type: 'contribution',
contributor: contribution.piKey,
siteId: contribution.siteId,
taskId: contribution.taskId,
computeUnits: contribution.computeUnits,
credits: contribution.credits,
signature: contribution.signature,
}, parents);
// Add to DAG
this.nodes.set(node.id, node);
// Update tips
for (const parent of parents) {
this.tips.delete(parent);
}
this.tips.add(node.id);
// Update parent weights (confirm path)
await this.updateWeights(node.id);
await this.saveLedger();
console.log(` 📝 Recorded contribution ${node.id}: +${contribution.credits} credits`);
return node;
}
/**
* Select tips for new node parents
*/
selectTips(count) {
const tips = Array.from(this.tips);
if (tips.length <= count) return tips;
// Weighted random selection based on age
const selected = [];
const available = [...tips];
while (selected.length < count && available.length > 0) {
const idx = Math.floor(Math.random() * available.length);
selected.push(available[idx]);
available.splice(idx, 1);
}
return selected;
}
/**
* Update weights along the path to genesis
*/
async updateWeights(nodeId) {
const visited = new Set();
const queue = [nodeId];
while (queue.length > 0) {
const id = queue.shift();
if (visited.has(id)) continue;
visited.add(id);
const node = this.nodes.get(id);
if (!node) continue;
node.weight = (node.weight || 0) + 1;
node.confirmations = (node.confirmations || 0) + 1;
// Check for confirmation threshold
if (node.confirmations >= 3 && !this.confirmed.has(id)) {
this.confirmed.add(id);
}
// Add parents to queue
for (const parentId of node.parents || []) {
queue.push(parentId);
}
}
}
/**
* Get contribution stats for a contributor
*/
getContributorStats(piKey) {
const contributions = Array.from(this.nodes.values())
.filter(n => n.type === 'contribution' && n.contributor === piKey);
return {
totalContributions: contributions.length,
confirmedContributions: contributions.filter(c => this.confirmed.has(c.id)).length,
totalCredits: contributions.reduce((sum, c) => sum + (c.credits || 0), 0),
totalComputeUnits: contributions.reduce((sum, c) => sum + (c.computeUnits || 0), 0),
firstContribution: contributions.length > 0
? Math.min(...contributions.map(c => c.timestamp))
: null,
lastContribution: contributions.length > 0
? Math.max(...contributions.map(c => c.timestamp))
: null,
};
}
/**
* Get network-wide stats
*/
getNetworkStats() {
const contributions = Array.from(this.nodes.values())
.filter(n => n.type === 'contribution');
const contributors = new Set(contributions.map(c => c.contributor));
return {
totalNodes: this.nodes.size,
totalContributions: contributions.length,
confirmedNodes: this.confirmed.size,
uniqueContributors: contributors.size,
totalCredits: contributions.reduce((sum, c) => sum + (c.credits || 0), 0),
totalComputeUnits: contributions.reduce((sum, c) => sum + (c.computeUnits || 0), 0),
currentTips: this.tips.size,
};
}
/**
* Verify contribution integrity
*/
async verifyContribution(nodeId) {
const node = this.nodes.get(nodeId);
if (!node) return { valid: false, reason: 'Node not found' };
// Verify parents exist
for (const parentId of node.parents || []) {
if (!this.nodes.has(parentId)) {
return { valid: false, reason: `Missing parent: ${parentId}` };
}
}
// Verify signature (if peer available)
const peer = this.peerManager.peers.get(node.contributor);
if (peer && node.signature) {
const dataToVerify = JSON.stringify({
contributor: node.contributor,
taskId: node.taskId,
computeUnits: node.computeUnits,
credits: node.credits,
});
if (!this.peerManager.verifySignature(peer.publicKey, dataToVerify, node.signature)) {
return { valid: false, reason: 'Invalid signature' };
}
}
return { valid: true, confirmations: node.confirmations };
}
/**
* Sync QDAG with peers
*/
startSync() {
this.syncInterval = setInterval(async () => {
await this.syncWithPeers();
}, NETWORK_CONFIG.qdagSyncInterval);
}
async syncWithPeers() {
const activePeers = this.peerManager.getActivePeers();
for (const peer of activePeers.slice(0, 3)) {
try {
// Request missing nodes from peer
const peerTips = await this.requestTips(peer);
for (const tipId of peerTips) {
if (!this.nodes.has(tipId)) {
const node = await this.requestNode(peer, tipId);
if (node) {
await this.mergeNode(node);
}
}
}
} catch (err) {
// Peer sync failed
}
}
}
async requestTips(peer) {
// In production: Request tips via P2P
return [];
}
async requestNode(peer, nodeId) {
// In production: Request specific node via P2P
return null;
}
async mergeNode(node) {
if (this.nodes.has(node.id)) return;
// Verify node before merging
const verification = await this.verifyContribution(node.id);
if (!verification.valid) return;
this.nodes.set(node.id, node);
await this.updateWeights(node.id);
await this.saveLedger();
}
stop() {
if (this.syncInterval) clearInterval(this.syncInterval);
}
}
/**
* Contribution Verifier
*
* Cross-verifies contributions between peers
*/
export class ContributionVerifier {
constructor(peerManager, qdagLedger) {
this.peerManager = peerManager;
this.qdag = qdagLedger;
this.verificationQueue = [];
}
/**
* Submit contribution for verification
*/
async submitContribution(contribution) {
// Sign the contribution
contribution.signature = this.peerManager.signMessage(
JSON.stringify({
contributor: contribution.piKey,
taskId: contribution.taskId,
computeUnits: contribution.computeUnits,
credits: contribution.credits,
})
);
// Record to local QDAG
const node = await this.qdag.recordContribution(contribution);
// In local simulation, self-verify
if (NETWORK_CONFIG.localSimulation) {
return {
nodeId: node.id,
verified: true,
confirmations: 1,
};
}
// In production, broadcast for peer verification
const verifications = await this.broadcastForVerification(node);
return {
nodeId: node.id,
verified: verifications.filter(v => v.valid).length >= 2,
confirmations: verifications.length,
};
}
/**
* Broadcast contribution for peer verification
*/
async broadcastForVerification(node) {
const activePeers = this.peerManager.getActivePeers();
const verifications = [];
for (const peer of activePeers.slice(0, 5)) {
try {
const verification = await this.requestVerification(peer, node);
verifications.push(verification);
} catch (err) {
// Peer verification failed
}
}
return verifications;
}
async requestVerification(peer, node) {
// In production: Request verification via P2P
return { valid: true, peerId: peer.piKey };
}
/**
* Verify a contribution from another peer
*/
async verifyFromPeer(contribution, requestingPeer) {
// Verify signature
const valid = this.peerManager.verifySignature(
requestingPeer.publicKey,
JSON.stringify({
contributor: contribution.contributor,
taskId: contribution.taskId,
computeUnits: contribution.computeUnits,
credits: contribution.credits,
}),
contribution.signature
);
// Verify compute units are reasonable
const reasonable = contribution.computeUnits > 0 &&
contribution.computeUnits < 1000000 &&
contribution.credits === Math.floor(contribution.computeUnits / 100);
return {
valid: valid && reasonable,
reason: !valid ? 'Invalid signature' : (!reasonable ? 'Unreasonable values' : 'OK'),
};
}
}
/**
* Network Manager - High-level API
*/
export class NetworkManager {
constructor(identity) {
this.identity = identity;
this.peerManager = new PeerManager(identity);
this.qdag = null;
this.verifier = null;
this.initialized = false;
}
async initialize() {
console.log('\n🌐 Initializing Edge-Net Network...');
await this.peerManager.initialize();
this.qdag = new QDAGLedger(this.peerManager);
await this.qdag.initialize();
this.verifier = new ContributionVerifier(this.peerManager, this.qdag);
// Announce to network
await this.peerManager.announce();
this.initialized = true;
console.log('✅ Network initialized\n');
return this;
}
/**
* Record a compute contribution
*/
async recordContribution(taskId, computeUnits) {
const credits = Math.floor(computeUnits / 100);
const contribution = {
piKey: this.identity.piKey,
siteId: this.identity.siteId,
taskId,
computeUnits,
credits,
timestamp: Date.now(),
};
return await this.verifier.submitContribution(contribution);
}
/**
* Get stats for this contributor
*/
getMyStats() {
return this.qdag.getContributorStats(this.identity.piKey);
}
/**
* Get network-wide stats
*/
getNetworkStats() {
return this.qdag.getNetworkStats();
}
/**
* Get connected peers
*/
getPeers() {
return this.peerManager.getAllPeers();
}
/**
* Stop network services
*/
stop() {
this.peerManager.stop();
this.qdag.stop();
}
}
// CLI interface
async function main() {
const args = process.argv.slice(2);
const command = args[0];
if (command === 'stats') {
// Show network stats
await ensureDirectories();
try {
const data = await fs.readFile(getQDAGFile(), 'utf-8');
const ledger = JSON.parse(data);
console.log('\n📊 Edge-Net Network Statistics\n');
console.log(` Total Nodes: ${ledger.nodes?.length || 0}`);
console.log(` Confirmed: ${ledger.confirmed?.length || 0}`);
console.log(` Current Tips: ${ledger.tips?.length || 0}`);
const contributions = (ledger.nodes || []).filter(n => n.type === 'contribution');
const contributors = new Set(contributions.map(c => c.contributor));
console.log(` Contributions: ${contributions.length}`);
console.log(` Contributors: ${contributors.size}`);
console.log(` Total Credits: ${contributions.reduce((s, c) => s + (c.credits || 0), 0)}`);
console.log();
} catch (err) {
console.log('No QDAG data found. Start contributing to initialize the network.');
}
} else if (command === 'peers') {
// Show known peers
await ensureDirectories();
try {
const data = await fs.readFile(getPeersFile(), 'utf-8');
const peers = JSON.parse(data);
console.log('\n👥 Known Peers\n');
for (const peer of peers) {
const status = (Date.now() - peer.lastSeen) < 300000 ? '🟢' : '⚪';
console.log(` ${status} ${peer.siteId} (π:${peer.piKey.slice(0, 8)})`);
console.log(` First seen: ${new Date(peer.firstSeen).toLocaleString()}`);
console.log(` Last seen: ${new Date(peer.lastSeen).toLocaleString()}`);
console.log(` Verified: ${peer.verified ? '✅' : '❌'}`);
console.log();
}
} catch (err) {
console.log('No peers found. Join the network to discover peers.');
}
} else if (command === 'help' || !command) {
console.log(`
Edge-Net Network Module
Commands:
stats Show network statistics
peers Show known peers
help Show this help
The network module is used internally by the join CLI.
To join the network: npx edge-net-join --generate
`);
}
}
main().catch(console.error);