Files
wifi-densepose/vendor/ruvector/examples/edge-net/pkg/multi-contributor-test.js

501 lines
16 KiB
JavaScript

#!/usr/bin/env node
/**
* Multi-Contributor Edge-Net Test with Persistence
*
* Tests:
* 1. Multiple contributors with persistent identities
* 2. State persistence (patterns, ledger, coherence)
* 3. Cross-contributor verification
* 4. Session restore from persisted data
*/
import { readFileSync, writeFileSync, existsSync, mkdirSync, readdirSync } from 'fs';
import { fileURLToPath } from 'url';
import { dirname, join } from 'path';
import { webcrypto } from 'crypto';
import { performance } from 'perf_hooks';
import { homedir } from 'os';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
// Setup polyfills
async function setupPolyfills() {
if (typeof globalThis.crypto === 'undefined') {
globalThis.crypto = webcrypto;
}
if (typeof globalThis.performance === 'undefined') {
globalThis.performance = performance;
}
const createStorage = () => {
const store = new Map();
return {
getItem: (key) => store.get(key) || null,
setItem: (key, value) => store.set(key, String(value)),
removeItem: (key) => store.delete(key),
clear: () => store.clear(),
get length() { return store.size; },
key: (i) => [...store.keys()][i] || null,
};
};
let cpuCount = 4;
try {
const os = await import('os');
cpuCount = os.cpus().length;
} catch {}
if (typeof globalThis.window === 'undefined') {
globalThis.window = {
crypto: globalThis.crypto,
performance: globalThis.performance,
localStorage: createStorage(),
sessionStorage: createStorage(),
navigator: {
userAgent: `Node.js/${process.version}`,
hardwareConcurrency: cpuCount,
},
location: { href: 'node://localhost', hostname: 'localhost' },
screen: { width: 1920, height: 1080, colorDepth: 24 },
};
}
if (typeof globalThis.document === 'undefined') {
globalThis.document = { createElement: () => ({}), body: {}, head: {} };
}
}
// Colors
const c = {
reset: '\x1b[0m',
bold: '\x1b[1m',
dim: '\x1b[2m',
cyan: '\x1b[36m',
green: '\x1b[32m',
yellow: '\x1b[33m',
red: '\x1b[31m',
magenta: '\x1b[35m',
};
function toHex(bytes) {
return Array.from(bytes).map(b => b.toString(16).padStart(2, '0')).join('');
}
// Storage directory
const STORAGE_DIR = join(homedir(), '.ruvector', 'edge-net-test');
function ensureStorageDir() {
if (!existsSync(STORAGE_DIR)) {
mkdirSync(STORAGE_DIR, { recursive: true });
}
return STORAGE_DIR;
}
// Contributor class with persistence
class PersistentContributor {
constructor(wasm, id, storageDir) {
this.wasm = wasm;
this.id = id;
this.storageDir = storageDir;
this.identityPath = join(storageDir, `contributor-${id}.identity`);
this.statePath = join(storageDir, `contributor-${id}.state`);
this.piKey = null;
this.coherence = null;
this.reasoning = null;
this.memory = null;
this.ledger = null;
this.patterns = [];
}
// Initialize or restore from persistence
async initialize() {
const password = `contributor-${this.id}-secret`;
// Try to restore identity
if (existsSync(this.identityPath)) {
console.log(` ${c.cyan}[${this.id}]${c.reset} Restoring identity from storage...`);
const backup = new Uint8Array(readFileSync(this.identityPath));
this.piKey = this.wasm.PiKey.restoreFromBackup(backup, password);
console.log(` ${c.green}${c.reset} Identity restored: ${this.piKey.getShortId()}`);
} else {
console.log(` ${c.cyan}[${this.id}]${c.reset} Generating new identity...`);
this.piKey = new this.wasm.PiKey();
// Persist immediately
const backup = this.piKey.createEncryptedBackup(password);
writeFileSync(this.identityPath, Buffer.from(backup));
console.log(` ${c.green}${c.reset} New identity created: ${this.piKey.getShortId()}`);
}
// Initialize components
this.coherence = new this.wasm.CoherenceEngine();
this.reasoning = new this.wasm.ReasoningBank();
this.memory = new this.wasm.CollectiveMemory(this.getNodeId());
this.ledger = new this.wasm.QDAGLedger();
// Try to restore state
if (existsSync(this.statePath)) {
console.log(` ${c.cyan}[${this.id}]${c.reset} Restoring state...`);
const state = JSON.parse(readFileSync(this.statePath, 'utf-8'));
// Restore ledger state if available
if (state.ledger) {
const ledgerBytes = new Uint8Array(state.ledger);
const imported = this.ledger.importState(ledgerBytes);
console.log(` ${c.green}${c.reset} Ledger restored: ${imported} transactions`);
}
// Restore patterns
if (state.patterns) {
this.patterns = state.patterns;
state.patterns.forEach(p => this.reasoning.store(JSON.stringify(p)));
console.log(` ${c.green}${c.reset} Patterns restored: ${state.patterns.length}`);
}
}
return this;
}
getNodeId() {
return `node-${this.id}-${this.piKey.getShortId()}`;
}
getPublicKey() {
return this.piKey.getPublicKey();
}
// Sign data
sign(data) {
const bytes = typeof data === 'string' ? new TextEncoder().encode(data) : data;
return this.piKey.sign(bytes);
}
// Verify signature from another contributor
verify(data, signature, publicKey) {
const bytes = typeof data === 'string' ? new TextEncoder().encode(data) : data;
return this.piKey.verify(bytes, signature, publicKey);
}
// Store a pattern
storePattern(pattern) {
const id = this.reasoning.store(JSON.stringify(pattern));
this.patterns.push(pattern);
return id;
}
// Lookup patterns
lookupPatterns(query, k = 3) {
return JSON.parse(this.reasoning.lookup(JSON.stringify(query), k));
}
// Get coherence stats
getCoherenceStats() {
return JSON.parse(this.coherence.getStats());
}
// Get memory stats
getMemoryStats() {
return JSON.parse(this.memory.getStats());
}
// Persist state
persist() {
const state = {
timestamp: Date.now(),
nodeId: this.getNodeId(),
patterns: this.patterns,
ledger: Array.from(this.ledger.exportState()),
stats: {
coherence: this.getCoherenceStats(),
memory: this.getMemoryStats(),
patternCount: this.reasoning.count(),
txCount: this.ledger.transactionCount()
}
};
writeFileSync(this.statePath, JSON.stringify(state, null, 2));
return state;
}
// Cleanup WASM resources
cleanup() {
if (this.piKey) this.piKey.free();
if (this.coherence) this.coherence.free();
if (this.reasoning) this.reasoning.free();
if (this.memory) this.memory.free();
if (this.ledger) this.ledger.free();
}
}
// Network simulation
class EdgeNetwork {
constructor(wasm, storageDir) {
this.wasm = wasm;
this.storageDir = storageDir;
this.contributors = new Map();
this.sharedMessages = [];
}
async addContributor(id) {
const contributor = new PersistentContributor(this.wasm, id, this.storageDir);
await contributor.initialize();
this.contributors.set(id, contributor);
return contributor;
}
// Broadcast a signed message
broadcastMessage(senderId, message) {
const sender = this.contributors.get(senderId);
const signature = sender.sign(message);
this.sharedMessages.push({
from: senderId,
message,
signature: Array.from(signature),
publicKey: Array.from(sender.getPublicKey()),
timestamp: Date.now()
});
return signature;
}
// Verify all messages from network perspective
verifyAllMessages() {
const results = [];
for (const msg of this.sharedMessages) {
const signature = new Uint8Array(msg.signature);
const publicKey = new Uint8Array(msg.publicKey);
// Each contributor verifies
for (const [id, contributor] of this.contributors) {
if (id !== msg.from) {
const valid = contributor.verify(msg.message, signature, publicKey);
results.push({
message: msg.message.substring(0, 30) + '...',
from: msg.from,
verifiedBy: id,
valid
});
}
}
}
return results;
}
// Share patterns across network
sharePatterns() {
const allPatterns = [];
for (const [id, contributor] of this.contributors) {
contributor.patterns.forEach(p => {
allPatterns.push({ ...p, contributor: id });
});
}
return allPatterns;
}
// Persist all contributors
persistAll() {
const states = {};
for (const [id, contributor] of this.contributors) {
states[id] = contributor.persist();
}
// Save network state
const networkState = {
timestamp: Date.now(),
contributors: Array.from(this.contributors.keys()),
messages: this.sharedMessages,
totalPatterns: this.sharePatterns().length
};
writeFileSync(
join(this.storageDir, 'network-state.json'),
JSON.stringify(networkState, null, 2)
);
return { states, networkState };
}
cleanup() {
for (const [, contributor] of this.contributors) {
contributor.cleanup();
}
}
}
// Main test
async function runMultiContributorTest() {
console.log(`
${c.cyan}╔═══════════════════════════════════════════════════════════════╗${c.reset}
${c.cyan}${c.reset} ${c.bold}Multi-Contributor Edge-Net Test with Persistence${c.reset} ${c.cyan}${c.reset}
${c.cyan}╚═══════════════════════════════════════════════════════════════╝${c.reset}
`);
await setupPolyfills();
// Load WASM
const { createRequire } = await import('module');
const require = createRequire(import.meta.url);
console.log(`${c.dim}Loading WASM module...${c.reset}`);
const wasm = require('./node/ruvector_edge_net.cjs');
console.log(`${c.green}${c.reset} WASM module loaded\n`);
// Setup storage
const storageDir = ensureStorageDir();
console.log(`${c.cyan}Storage:${c.reset} ${storageDir}\n`);
// Check if this is a continuation
const networkStatePath = join(storageDir, 'network-state.json');
const isContinuation = existsSync(networkStatePath);
if (isContinuation) {
const prevState = JSON.parse(readFileSync(networkStatePath, 'utf-8'));
console.log(`${c.yellow}Continuing from previous session:${c.reset}`);
console.log(` Previous timestamp: ${new Date(prevState.timestamp).toISOString()}`);
console.log(` Contributors: ${prevState.contributors.join(', ')}`);
console.log(` Messages: ${prevState.messages.length}`);
console.log(` Patterns: ${prevState.totalPatterns}\n`);
} else {
console.log(`${c.green}Starting fresh network...${c.reset}\n`);
}
// Create network
const network = new EdgeNetwork(wasm, storageDir);
try {
// ==== Phase 1: Initialize Contributors ====
console.log(`${c.bold}=== Phase 1: Initialize Contributors ===${c.reset}\n`);
const contributorIds = ['alice', 'bob', 'charlie'];
for (const id of contributorIds) {
await network.addContributor(id);
}
console.log(`\n${c.green}${c.reset} ${network.contributors.size} contributors initialized\n`);
// ==== Phase 2: Cross-Verification ====
console.log(`${c.bold}=== Phase 2: Cross-Verification ===${c.reset}\n`);
// Each contributor signs a message
for (const id of contributorIds) {
const message = `Hello from ${id} at ${Date.now()}`;
network.broadcastMessage(id, message);
console.log(` ${c.cyan}[${id}]${c.reset} Broadcast: "${message.substring(0, 40)}..."`);
}
// Verify all signatures
const verifications = network.verifyAllMessages();
const allValid = verifications.every(v => v.valid);
console.log(`\n ${c.bold}Verification Results:${c.reset}`);
verifications.forEach(v => {
console.log(` ${v.valid ? c.green + '✓' : c.red + '✗'}${c.reset} ${v.from}${v.verifiedBy}`);
});
console.log(`\n${allValid ? c.green + '✓' : c.red + '✗'}${c.reset} All ${verifications.length} verifications ${allValid ? 'passed' : 'FAILED'}\n`);
// ==== Phase 3: Pattern Storage ====
console.log(`${c.bold}=== Phase 3: Pattern Storage & Learning ===${c.reset}\n`);
// Each contributor stores some patterns
const patternData = {
alice: [
{ centroid: [1.0, 0.0, 0.0], confidence: 0.95, task: 'compute' },
{ centroid: [0.9, 0.1, 0.0], confidence: 0.88, task: 'inference' }
],
bob: [
{ centroid: [0.0, 1.0, 0.0], confidence: 0.92, task: 'training' },
{ centroid: [0.1, 0.9, 0.0], confidence: 0.85, task: 'validation' }
],
charlie: [
{ centroid: [0.0, 0.0, 1.0], confidence: 0.90, task: 'storage' },
{ centroid: [0.1, 0.1, 0.8], confidence: 0.87, task: 'retrieval' }
]
};
for (const [id, patterns] of Object.entries(patternData)) {
const contributor = network.contributors.get(id);
patterns.forEach(p => contributor.storePattern(p));
console.log(` ${c.cyan}[${id}]${c.reset} Stored ${patterns.length} patterns`);
}
// Lookup patterns
console.log(`\n ${c.bold}Pattern Lookups:${c.reset}`);
const alice = network.contributors.get('alice');
const similar = alice.lookupPatterns([0.95, 0.05, 0.0], 2);
console.log(` Alice searches for [0.95, 0.05, 0.0]: Found ${similar.length} similar patterns`);
similar.forEach((p, i) => {
console.log(` ${i + 1}. similarity=${p.similarity.toFixed(3)}, task=${p.pattern?.task || 'unknown'}`);
});
const totalPatterns = network.sharePatterns();
console.log(`\n${c.green}${c.reset} Total patterns in network: ${totalPatterns.length}\n`);
// ==== Phase 4: Coherence Check ====
console.log(`${c.bold}=== Phase 4: Coherence State ===${c.reset}\n`);
for (const [id, contributor] of network.contributors) {
const stats = contributor.getCoherenceStats();
console.log(` ${c.cyan}[${id}]${c.reset} Merkle: ${contributor.coherence.getMerkleRoot().substring(0, 16)}... | Events: ${stats.total_events || 0}`);
}
// ==== Phase 5: Persistence ====
console.log(`\n${c.bold}=== Phase 5: Persistence ===${c.reset}\n`);
const { states, networkState } = network.persistAll();
console.log(` ${c.green}${c.reset} Network state persisted`);
console.log(` Contributors: ${networkState.contributors.length}`);
console.log(` Messages: ${networkState.messages.length}`);
console.log(` Total patterns: ${networkState.totalPatterns}`);
for (const [id, state] of Object.entries(states)) {
console.log(`\n ${c.cyan}[${id}]${c.reset} State saved:`);
console.log(` Node ID: ${state.nodeId}`);
console.log(` Patterns: ${state.stats.patternCount}`);
console.log(` Ledger TX: ${state.stats.txCount}`);
}
// ==== Phase 6: Verify Persistence ====
console.log(`\n${c.bold}=== Phase 6: Verify Persistence Files ===${c.reset}\n`);
const files = readdirSync(storageDir);
console.log(` Files in ${storageDir}:`);
files.forEach(f => {
const path = join(storageDir, f);
const stat = existsSync(path) ? readFileSync(path).length : 0;
console.log(` ${c.dim}${c.reset} ${f} (${stat} bytes)`);
});
// ==== Summary ====
console.log(`
${c.cyan}╔═══════════════════════════════════════════════════════════════╗${c.reset}
${c.cyan}${c.reset} ${c.bold}${c.green}All Tests Passed!${c.reset} ${c.cyan}${c.reset}
${c.cyan}╚═══════════════════════════════════════════════════════════════╝${c.reset}
${c.bold}Summary:${c.reset}
${c.green}${c.reset} ${network.contributors.size} contributors initialized with persistent identities
${c.green}${c.reset} ${verifications.length} cross-verifications passed
${c.green}${c.reset} ${totalPatterns.length} patterns stored and searchable
${c.green}${c.reset} State persisted to ${storageDir}
${c.green}${c.reset} ${isContinuation ? 'Continued from' : 'Started'} session
${c.dim}Run again to test persistence restoration!${c.reset}
`);
} finally {
network.cleanup();
}
}
// Run
runMultiContributorTest().catch(err => {
console.error(`${c.red}Error: ${err.message}${c.reset}`);
console.error(err.stack);
process.exit(1);
});