uploader-bot/docs/NEW_ARCHITECTURE.md

18 KiB
Raw Blame History

MY Network v3.0 - Децентрализованная архитектура контента

🎯 Обзор

MY Network v3.0 представляет собой полностью децентрализованную платформу дистрибьюции контента, где каждая нода принимает независимые решения о принятии и хранении контента. Система исключает централизованное управление и кворумное принятие решений.

🏗️ Принципы децентрализации

1. Автономность нод

  • Независимое принятие решений: Каждая нода самостоятельно решает принимать контент или нет
  • Локальные правила: Настройки фильтрации и политики хранения на уровне ноды
  • Отсутствие консенсуса: Нет необходимости в голосовании или кворуме

2. Доступность без цензуры

  • Множественные источники: Контент может быть доступен на разных нодах
  • Отсутствие единой точки отказа: Недоступность одной ноды не влияет на сеть
  • Устойчивость к цензуре: Контент остается доступным пока есть хотя бы одна нода

3. Гибкая топология сети

  • Публичные ноды: С открытыми портами для входящих соединений
  • Приватные ноды: Только исходящие соединения, получение контента
  • Bootstrap ноды: Точки входа в сеть для новых участников

🔄 Архитектура синхронизации

Замена кворумной системы

class ContentAcceptanceManager:
    """Управление принятием контента без консенсуса"""
    
    def __init__(self, node_config: dict):
        self.node_config = node_config
        self.filters = ContentFilters(node_config)
    
    async def should_accept_content(self, content_metadata: dict) -> bool:
        """
        Решение о принятии контента (заглушка для будущего расширения)
        
        В текущей версии всегда возвращает True.
        В будущем здесь будут фильтры по:
        - Авторам (whitelist/blacklist)
        - Типам контента 
        - Размерам файлов
        - Тегам и категориям
        """
        # TODO: Добавить логику фильтрации
        return True
    
    async def process_content_announcement(self, peer_id: str, announcement: dict):
        """Обработка анонса нового контента от пира"""
        
        content_hash = announcement.get("content_hash")
        
        # Проверка - нужен ли нам этот контент
        if await self.should_accept_content(announcement):
            # Добавляем в очередь синхронизации
            await self.sync_manager.queue_content_sync(peer_id, content_hash)
        else:
            logger.info(f"Content {content_hash} rejected by local filters")

Протокол синхронизации P2P

class P2PSyncProtocol:
    """Децентрализованный протокол синхронизации"""
    
    async def announce_new_content(self, content: StoredContent):
        """Анонс нового контента всем подключенным пирам"""
        
        announcement = {
            "type": "content_announcement",
            "content_hash": content.hash,
            "file_size": content.file_size,
            "content_type": content.content_type,
            "encrypted": content.encrypted,
            "timestamp": datetime.utcnow().isoformat(),
            "author_id": content.author_id,
            "tags": content.tags
        }
        
        # Рассылаем анонс всем активным пирам
        for peer_id in self.active_peers:
            try:
                await self.send_to_peer(peer_id, announcement)
            except Exception as e:
                logger.warning(f"Failed to announce to peer {peer_id}: {e}")
    
    async def request_content_sync(self, peer_id: str, content_hash: str):
        """Запрос синхронизации конкретного контента"""
        
        request = {
            "type": "sync_request",
            "content_hash": content_hash,
            "requesting_node": self.node_id,
            "timestamp": datetime.utcnow().isoformat()
        }
        
        response = await self.send_request_to_peer(peer_id, request)
        
        if response.get("status") == "approved":
            await self._sync_content_from_peer(peer_id, content_hash)
        else:
            logger.info(f"Sync request for {content_hash} denied by {peer_id}")

🔐 Система шифрования и хэширования

Единые хэши encrypted_content

class ContentHashManager:
    """Управление хэшированием контента для децентрализованной сети"""
    
    @staticmethod
    def calculate_content_hash(content_data: bytes) -> str:
        """
        Вычисление единого хэша для encrypted_content
        
        Использует SHA-256 для обеспечения одинакового хэша
        на всех нодах для одного и того же контента
        """
        return hashlib.sha256(content_data).hexdigest()
    
    @staticmethod
    def encrypt_content_for_storage(content_data: bytes) -> tuple[bytes, str]:
        """
        Шифрование контента для хранения
        
        Returns:
            tuple: (encrypted_data, encryption_key)
        """
        # Генерируем уникальный ключ для этого контента
        encryption_key = secrets.token_hex(32)  # 256-bit key
        
        # Шифруем контент симметричным алгоритмом
        cipher = AES.new(
            key=bytes.fromhex(encryption_key),
            mode=AES.MODE_GCM
        )
        
        encrypted_data, auth_tag = cipher.encrypt_and_digest(content_data)
        
        # Добавляем nonce и auth_tag к зашифрованным данным
        final_encrypted = cipher.nonce + auth_tag + encrypted_data
        
        return final_encrypted, encryption_key
    
    @staticmethod
    def decrypt_content(encrypted_data: bytes, encryption_key: str) -> bytes:
        """Расшифровка контента"""
        
        # Извлекаем nonce, auth_tag и данные
        nonce = encrypted_data[:16]
        auth_tag = encrypted_data[16:32]
        ciphertext = encrypted_data[32:]
        
        # Расшифровываем
        cipher = AES.new(
            key=bytes.fromhex(encryption_key),
            mode=AES.MODE_GCM,
            nonce=nonce
        )
        
        return cipher.decrypt_and_verify(ciphertext, auth_tag)

Контроль доступа к контенту

class ContentAccessControl:
    """Система контроля доступа к контенту"""
    
    async def can_provide_content(self, requester_node: str, content_hash: str) -> bool:
        """
        Решение о предоставлении контента запрашивающей ноде
        
        В текущей версии разрешает доступ всем.
        В будущем здесь будут проверки:
        - Доверенность ноды
        - Коммерческая лицензия
        - Региональные ограничения
        """
        # TODO: Добавить логику контроля доступа
        return True
    
    async def generate_preview_id(self, content_hash: str) -> str:
        """
        Генерация ID для preview, не связанного с основным хэшем
        
        Preview ID намеренно не связан с encrypted_content хэшем
        для обеспечения безопасности
        """
        # Используем случайный UUID для preview
        preview_id = str(uuid4())
        
        # Сохраняем связь в локальной базе
        await self._store_preview_mapping(content_hash, preview_id)
        
        return preview_id
    
    async def get_content_by_preview_id(self, preview_id: str) -> Optional[bytes]:
        """Получение preview контента по preview_id"""
        
        content_hash = await self._get_content_hash_by_preview_id(preview_id)
        if not content_hash:
            return None
        
        # Загружаем preview версию (не основной контент!)
        preview_content = await StoredContent.get_preview_by_hash(content_hash)
        return preview_content.data if preview_content else None

🌐 Топология сети

Типы нод

class NodeTypes:
    """Типы нод в MY Network"""
    
    BOOTSTRAP = "bootstrap"      # Точки входа в сеть
    PUBLIC = "public"           # Открытые ноды с входящими соединениями
    PRIVATE = "private"         # Закрытые ноды, только исходящие соединения
    SEED = "seed"              # Ноды с большим объемом контента для новых участников

class NodeConfiguration:
    """Конфигурация ноды"""
    
    def __init__(self, config: dict):
        self.node_type = config.get("node_type", NodeTypes.PUBLIC)
        self.allow_incoming = config.get("allow_incoming", True)
        self.max_connections = config.get("max_connections", 50)
        self.bootstrap_nodes = config.get("bootstrap_nodes", [])
        
    def is_private_node(self) -> bool:
        """Проверка является ли нода приватной"""
        return self.node_type == NodeTypes.PRIVATE or not self.allow_incoming
    
    def can_accept_incoming_connections(self) -> bool:
        """Может ли нода принимать входящие соединения"""
        return self.allow_incoming and self.node_type != NodeTypes.PRIVATE

Обнаружение и подключение к нодам

class NetworkDiscovery:
    """Обнаружение нод в децентрализованной сети"""
    
    async def discover_network_nodes(self) -> List[NodeInfo]:
        """Обнаружение доступных нод в сети"""
        
        discovered_nodes = []
        
        # Получаем список нод от bootstrap серверов
        for bootstrap_node in self.config.bootstrap_nodes:
            try:
                nodes = await self._get_nodes_from_bootstrap(bootstrap_node)
                discovered_nodes.extend(nodes)
            except Exception as e:
                logger.warning(f"Failed to get nodes from bootstrap {bootstrap_node}: {e}")
        
        # Получаем список нод от подключенных пиров
        for peer_id in self.connected_peers:
            try:
                nodes = await self._get_nodes_from_peer(peer_id)
                discovered_nodes.extend(nodes)
            except Exception as e:
                logger.warning(f"Failed to get nodes from peer {peer_id}: {e}")
        
        # Убираем дубликаты и себя
        unique_nodes = self._deduplicate_nodes(discovered_nodes)
        return [node for node in unique_nodes if node.node_id != self.node_id]
    
    async def connect_to_network(self):
        """Подключение к сети MY Network"""
        
        if not self.config.bootstrap_nodes:
            logger.error("No bootstrap nodes configured")
            return
        
        connected_count = 0
        target_connections = min(10, len(self.config.bootstrap_nodes) * 2)
        
        # Подключаемся к bootstrap нодам
        for bootstrap_node in self.config.bootstrap_nodes:
            try:
                if await self._connect_to_node(bootstrap_node):
                    connected_count += 1
                    logger.info(f"Connected to bootstrap node: {bootstrap_node}")
            except Exception as e:
                logger.warning(f"Failed to connect to bootstrap {bootstrap_node}: {e}")
        
        # Если недостаточно соединений, ищем дополнительные ноды
        if connected_count < target_connections:
            additional_nodes = await self.discover_network_nodes()
            
            for node_info in additional_nodes:
                if connected_count >= target_connections:
                    break
                
                try:
                    if await self._connect_to_node(node_info):
                        connected_count += 1
                        logger.info(f"Connected to discovered node: {node_info.node_id}")
                except Exception as e:
                    logger.warning(f"Failed to connect to node {node_info.node_id}: {e}")
        
        logger.info(f"Network connection complete. Connected to {connected_count} nodes")

📊 Мониторинг децентрализованной сети

Статистика сети

class NetworkStatistics:
    """Сбор статистики децентрализованной сети"""
    
    async def collect_network_stats(self) -> dict:
        """Сбор статистики о состоянии сети"""
        
        return {
            "node_info": {
                "node_id": self.node_id,
                "node_type": self.config.node_type,
                "version": self.version,
                "uptime": self.get_uptime_seconds()
            },
            "connections": {
                "total_peers": len(self.connected_peers),
                "bootstrap_peers": len(self.bootstrap_connections),
                "incoming_connections": self.get_incoming_connection_count(),
                "outgoing_connections": self.get_outgoing_connection_count()
            },
            "content": {
                "total_items": await self.get_local_content_count(),
                "encrypted_items": await self.get_encrypted_content_count(),
                "public_items": await self.get_public_content_count(),
                "storage_used": await self.get_storage_usage_bytes()
            },
            "sync_activity": {
                "content_synced_24h": await self.get_sync_count_24h(),
                "pending_sync_items": self.sync_manager.get_pending_count(),
                "failed_sync_attempts": self.sync_manager.get_failed_count(),
                "last_sync_time": self.sync_manager.last_sync_time
            },
            "network_health": {
                "reachable_nodes": await self.count_reachable_nodes(),
                "network_latency_avg": await self.calculate_avg_network_latency(),
                "content_availability": await self.calculate_content_availability()
            }
        }

🔧 API для децентрализованной сети

Новые эндпоинты

# Управление нодой
GET  /api/v1/node/status           # Статус ноды и подключений
GET  /api/v1/node/peers            # Список подключенных пиров
POST /api/v1/node/connect          # Подключение к новому пиру
POST /api/v1/node/disconnect       # Отключение от пира

# Обнаружение сети
GET  /api/v1/network/discover      # Обнаружение доступных нод
GET  /api/v1/network/stats         # Статистика сети
GET  /api/v1/network/topology      # Топология подключений

# Синхронизация контента
GET  /api/v1/sync/status           # Статус синхронизации
POST /api/v1/sync/request          # Запрос синхронизации контента
GET  /api/v1/sync/pending          # Список ожидающей синхронизации
POST /api/v1/sync/cancel           # Отмена синхронизации

# Поиск контента в сети
GET  /api/v1/content/search        # Поиск контента по хэшу в сети
GET  /api/v1/content/{hash}/nodes  # Список нод с конкретным контентом
POST /api/v1/content/announce      # Анонс нового контента в сеть

# Управление доступом
POST /api/v1/access/request        # Запрос доступа к контенту
GET  /api/v1/access/policies       # Политики доступа к контенту
PUT  /api/v1/access/policies       # Обновление политик доступа

Эта архитектура обеспечивает полную децентрализацию при сохранении гибкости и безопасности системы.