- Fixed TransferDirection import error in ethereum.rs tests - Implemented math.tanh function for Flutter tensor operations - Added DocumentStore CRUD methods (find_by_id, update_by_id, delete_by_id) - Implemented database gateway handlers (get/update/delete document) - Applied cargo fix across all crates to resolve unused imports/variables - Reduced warnings from 320+ to 68 (remaining are architectural) Affected crates: synor-database, synor-bridge, synor-compute, synor-privacy, synor-verifier, synor-hosting, synor-economics
377 lines
10 KiB
Rust
377 lines
10 KiB
Rust
//! Device registry and management.
|
|
//!
|
|
//! Supports all device types:
|
|
//! - Data center servers
|
|
//! - Desktop workstations
|
|
//! - Laptops
|
|
//! - Mobile devices (iOS, Android)
|
|
//! - Browsers (WebGPU, WASM)
|
|
//! - IoT devices
|
|
|
|
use crate::error::ComputeError;
|
|
use crate::processor::{GenericProcessor, Processor, ProcessorId, ProcessorType};
|
|
use crate::{NodeId, ProcessorInfo};
|
|
use parking_lot::RwLock;
|
|
use serde::{Deserialize, Serialize};
|
|
use std::collections::HashMap;
|
|
use std::sync::Arc;
|
|
|
|
/// Unique device identifier.
|
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
|
pub struct DeviceId(pub [u8; 32]);
|
|
|
|
impl DeviceId {
|
|
/// Creates a new random device ID.
|
|
pub fn new() -> Self {
|
|
use rand::Rng;
|
|
let mut bytes = [0u8; 32];
|
|
rand::thread_rng().fill(&mut bytes);
|
|
DeviceId(bytes)
|
|
}
|
|
|
|
/// Creates from bytes.
|
|
pub fn from_bytes(bytes: [u8; 32]) -> Self {
|
|
DeviceId(bytes)
|
|
}
|
|
}
|
|
|
|
impl Default for DeviceId {
|
|
fn default() -> Self {
|
|
Self::new()
|
|
}
|
|
}
|
|
|
|
impl std::fmt::Display for DeviceId {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
write!(f, "dev_{}", hex::encode(&self.0[..8]))
|
|
}
|
|
}
|
|
|
|
/// Device type classification.
|
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
|
pub enum DeviceType {
|
|
/// Data center server.
|
|
DataCenter,
|
|
/// Desktop workstation.
|
|
Desktop,
|
|
/// Laptop.
|
|
Laptop,
|
|
/// Mobile phone.
|
|
Mobile,
|
|
/// Tablet.
|
|
Tablet,
|
|
/// IoT device.
|
|
IoT,
|
|
/// Browser (WebGPU/WASM).
|
|
Browser,
|
|
/// Edge server.
|
|
Edge,
|
|
}
|
|
|
|
impl DeviceType {
|
|
/// Returns typical reliability score (0-100).
|
|
pub fn reliability(&self) -> u32 {
|
|
match self {
|
|
DeviceType::DataCenter => 99,
|
|
DeviceType::Edge => 95,
|
|
DeviceType::Desktop => 80,
|
|
DeviceType::Laptop => 60,
|
|
DeviceType::Mobile => 40,
|
|
DeviceType::Tablet => 50,
|
|
DeviceType::IoT => 70,
|
|
DeviceType::Browser => 30,
|
|
}
|
|
}
|
|
|
|
/// Returns typical availability hours per day.
|
|
pub fn availability_hours(&self) -> f32 {
|
|
match self {
|
|
DeviceType::DataCenter => 24.0,
|
|
DeviceType::Edge => 24.0,
|
|
DeviceType::Desktop => 8.0,
|
|
DeviceType::Laptop => 6.0,
|
|
DeviceType::Mobile => 4.0,
|
|
DeviceType::Tablet => 4.0,
|
|
DeviceType::IoT => 24.0,
|
|
DeviceType::Browser => 2.0,
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Device capabilities.
|
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
|
pub struct DeviceCapabilities {
|
|
/// Device type.
|
|
pub device_type: DeviceType,
|
|
/// Available processors.
|
|
pub processors: Vec<ProcessorType>,
|
|
/// Total memory (GB).
|
|
pub memory_gb: f32,
|
|
/// Network bandwidth (Mbps).
|
|
pub bandwidth_mbps: f32,
|
|
/// Storage available (GB).
|
|
pub storage_gb: f32,
|
|
/// Battery powered.
|
|
pub battery_powered: bool,
|
|
/// Supports background execution.
|
|
pub background_execution: bool,
|
|
}
|
|
|
|
/// Device information.
|
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
|
pub struct DeviceInfo {
|
|
/// Device ID.
|
|
pub id: DeviceId,
|
|
/// Device type.
|
|
pub device_type: DeviceType,
|
|
/// Owner address.
|
|
pub owner: [u8; 32],
|
|
/// Capabilities.
|
|
pub capabilities: DeviceCapabilities,
|
|
/// Current status.
|
|
pub status: DeviceStatus,
|
|
/// Reputation score (0-100).
|
|
pub reputation: u32,
|
|
/// Total earnings (atomic SYNOR).
|
|
pub earnings: u64,
|
|
/// Geographic region.
|
|
pub region: String,
|
|
}
|
|
|
|
/// Device status.
|
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
|
pub enum DeviceStatus {
|
|
/// Online and available.
|
|
Online,
|
|
/// Online but busy.
|
|
Busy,
|
|
/// Idle but available.
|
|
Idle,
|
|
/// On battery (reduced capacity).
|
|
OnBattery,
|
|
/// Offline.
|
|
Offline,
|
|
/// Maintenance.
|
|
Maintenance,
|
|
}
|
|
|
|
/// Device registry managing all devices and processors.
|
|
pub struct DeviceRegistry {
|
|
/// Registered devices.
|
|
devices: RwLock<HashMap<DeviceId, DeviceInfo>>,
|
|
/// Node to device mapping.
|
|
node_devices: RwLock<HashMap<NodeId, Vec<DeviceId>>>,
|
|
/// All processors (across all nodes).
|
|
processors: RwLock<HashMap<ProcessorId, Arc<dyn Processor>>>,
|
|
/// Processor to node mapping.
|
|
processor_nodes: RwLock<HashMap<ProcessorId, NodeId>>,
|
|
/// Next processor ID.
|
|
next_processor_id: std::sync::atomic::AtomicU64,
|
|
}
|
|
|
|
impl DeviceRegistry {
|
|
/// Creates a new device registry.
|
|
pub fn new() -> Self {
|
|
Self {
|
|
devices: RwLock::new(HashMap::new()),
|
|
node_devices: RwLock::new(HashMap::new()),
|
|
processors: RwLock::new(HashMap::new()),
|
|
processor_nodes: RwLock::new(HashMap::new()),
|
|
next_processor_id: std::sync::atomic::AtomicU64::new(0),
|
|
}
|
|
}
|
|
|
|
/// Registers a device.
|
|
pub fn register_device(&self, device: DeviceInfo) -> Result<DeviceId, ComputeError> {
|
|
let id = device.id;
|
|
self.devices.write().insert(id, device);
|
|
Ok(id)
|
|
}
|
|
|
|
/// Unregisters a device.
|
|
pub fn unregister_device(&self, device_id: DeviceId) -> Result<(), ComputeError> {
|
|
self.devices.write().remove(&device_id);
|
|
Ok(())
|
|
}
|
|
|
|
/// Gets a device by ID.
|
|
pub fn get_device(&self, device_id: DeviceId) -> Option<DeviceInfo> {
|
|
self.devices.read().get(&device_id).cloned()
|
|
}
|
|
|
|
/// Registers a processor for a node.
|
|
pub fn register_processor(
|
|
&self,
|
|
node_id: NodeId,
|
|
info: ProcessorInfo,
|
|
) -> Result<(), ComputeError> {
|
|
let processor_id = info.id;
|
|
|
|
// Create a generic processor from the info
|
|
let processor: Arc<dyn Processor> = Arc::new(GenericProcessor::new(
|
|
processor_id,
|
|
info.processor_type,
|
|
info.capabilities,
|
|
));
|
|
|
|
self.processors.write().insert(processor_id, processor);
|
|
self.processor_nodes.write().insert(processor_id, node_id);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Unregisters all processors for a node.
|
|
pub fn unregister_node(&self, node_id: NodeId) -> Result<(), ComputeError> {
|
|
let mut processors = self.processors.write();
|
|
let mut processor_nodes = self.processor_nodes.write();
|
|
|
|
// Find and remove all processors for this node
|
|
let to_remove: Vec<_> = processor_nodes
|
|
.iter()
|
|
.filter(|(_, n)| **n == node_id)
|
|
.map(|(p, _)| *p)
|
|
.collect();
|
|
|
|
for proc_id in to_remove {
|
|
processors.remove(&proc_id);
|
|
processor_nodes.remove(&proc_id);
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Gets a processor by ID.
|
|
pub fn get_processor(&self, processor_id: ProcessorId) -> Result<Arc<dyn Processor>, ComputeError> {
|
|
self.processors
|
|
.read()
|
|
.get(&processor_id)
|
|
.cloned()
|
|
.ok_or(ComputeError::ProcessorNotFound(processor_id))
|
|
}
|
|
|
|
/// Gets all processors.
|
|
pub fn all_processors(&self) -> Vec<Arc<dyn Processor>> {
|
|
self.processors.read().values().cloned().collect()
|
|
}
|
|
|
|
/// Gets processors of a specific type.
|
|
pub fn processors_by_type(&self, proc_type: ProcessorType) -> Vec<Arc<dyn Processor>> {
|
|
self.processors
|
|
.read()
|
|
.values()
|
|
.filter(|p| p.processor_type() == proc_type)
|
|
.cloned()
|
|
.collect()
|
|
}
|
|
|
|
/// Gets the next processor ID.
|
|
pub fn next_processor_id(&self) -> ProcessorId {
|
|
ProcessorId(self.next_processor_id.fetch_add(1, std::sync::atomic::Ordering::SeqCst))
|
|
}
|
|
|
|
/// Gets total number of devices.
|
|
pub fn device_count(&self) -> usize {
|
|
self.devices.read().len()
|
|
}
|
|
|
|
/// Gets total number of processors.
|
|
pub fn processor_count(&self) -> usize {
|
|
self.processors.read().len()
|
|
}
|
|
|
|
/// Gets devices by type.
|
|
pub fn devices_by_type(&self, device_type: DeviceType) -> Vec<DeviceInfo> {
|
|
self.devices
|
|
.read()
|
|
.values()
|
|
.filter(|d| d.device_type == device_type)
|
|
.cloned()
|
|
.collect()
|
|
}
|
|
|
|
/// Gets online devices.
|
|
pub fn online_devices(&self) -> Vec<DeviceInfo> {
|
|
self.devices
|
|
.read()
|
|
.values()
|
|
.filter(|d| d.status == DeviceStatus::Online || d.status == DeviceStatus::Idle)
|
|
.cloned()
|
|
.collect()
|
|
}
|
|
|
|
/// Updates device status.
|
|
pub fn update_device_status(
|
|
&self,
|
|
device_id: DeviceId,
|
|
status: DeviceStatus,
|
|
) -> Result<(), ComputeError> {
|
|
if let Some(device) = self.devices.write().get_mut(&device_id) {
|
|
device.status = status;
|
|
Ok(())
|
|
} else {
|
|
Err(ComputeError::Internal(format!("Device not found: {}", device_id)))
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Default for DeviceRegistry {
|
|
fn default() -> Self {
|
|
Self::new()
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
use crate::processor::{CpuVariant, AvxSupport};
|
|
|
|
#[test]
|
|
fn test_device_id() {
|
|
let id1 = DeviceId::new();
|
|
let id2 = DeviceId::new();
|
|
assert_ne!(id1.0, id2.0);
|
|
}
|
|
|
|
#[test]
|
|
fn test_device_registry() {
|
|
let registry = DeviceRegistry::new();
|
|
|
|
let device = DeviceInfo {
|
|
id: DeviceId::new(),
|
|
device_type: DeviceType::Desktop,
|
|
owner: [1u8; 32],
|
|
capabilities: DeviceCapabilities {
|
|
device_type: DeviceType::Desktop,
|
|
processors: vec![ProcessorType::Cpu(CpuVariant::X86_64 {
|
|
avx: AvxSupport::Avx512,
|
|
})],
|
|
memory_gb: 64.0,
|
|
bandwidth_mbps: 1000.0,
|
|
storage_gb: 1000.0,
|
|
battery_powered: false,
|
|
background_execution: true,
|
|
},
|
|
status: DeviceStatus::Online,
|
|
reputation: 100,
|
|
earnings: 0,
|
|
region: "us-east".to_string(),
|
|
};
|
|
|
|
let device_id = device.id;
|
|
registry.register_device(device).unwrap();
|
|
|
|
assert_eq!(registry.device_count(), 1);
|
|
assert!(registry.get_device(device_id).is_some());
|
|
|
|
registry.unregister_device(device_id).unwrap();
|
|
assert_eq!(registry.device_count(), 0);
|
|
}
|
|
|
|
#[test]
|
|
fn test_device_type_properties() {
|
|
assert_eq!(DeviceType::DataCenter.reliability(), 99);
|
|
assert_eq!(DeviceType::Mobile.reliability(), 40);
|
|
assert_eq!(DeviceType::DataCenter.availability_hours(), 24.0);
|
|
assert_eq!(DeviceType::Browser.availability_hours(), 2.0);
|
|
}
|
|
}
|