# Montana Protocol — P2P Network Specification # Техническая спецификация пиринговой сети **Version:** 2.0 **Status:** MAINNET **Date:** 2026-01-23 **Authors:** Alejandro Montana --- ## Abstract Настоящий документ описывает архитектуру пиринговой сети Montana Protocol. Сеть обеспечивает распространение подписей присутствия, выбор активного мастера и защиту от изоляции узлов. --- ## 1. Архитектура сети ### 1.1 Топология Montana Protocol использует фиксированную топологию из 5 узлов: ``` ┌─────────────┐ │ amsterdam │ ← PRIMARY (позиция 0) │ 72.56.102.240│ └──────┬──────┘ │ ┌─────────────────┼─────────────────┐ │ │ │ ┌────▼────┐ ┌────▼────┐ ┌─────▼────┐ │ moscow │ │ almaty │ │ spb │ │176.124..│ │91.200...│ │188.225...│ └────┬────┘ └────┬────┘ └────┬─────┘ │ │ │ └────────────────┼────────────────┘ │ ┌──────▼──────┐ │ novosibirsk │ │147.45.147...│ └─────────────┘ ``` ### 1.2 Типы узлов | Тип | Описание | Реализация | |-----|----------|------------| | **Full Node** | Полный узел сети с Telegram polling | junomontanaagibot.py | | **Health Server** | HTTP endpoint для проверки здоровья | leader_election.py:8889 | ### 1.3 Порты | Порт | Протокол | Назначение | |------|----------|------------| | 22 | SSH | Администрирование | | 8889 | HTTP | Health check endpoint | | 443 | HTTPS | Fallback проверка | --- ## 2. Leader Election Protocol ### 2.1 Алгоритм выбора мастера Детерминированный выбор мастера на основе позиции в цепочке: ```python # leader_election.py:326-349 BOT_CHAIN = [ ("amsterdam", "72.56.102.240"), # позиция 0 ("moscow", "176.124.208.93"), # позиция 1 ("almaty", "91.200.148.93"), # позиция 2 ("spb", "188.225.58.98"), # позиция 3 ("novosibirsk", "147.45.147.247"), # позиция 4 ] def am_i_the_master(): for name, ip in BOT_CHAIN: if name == my_node_name: return True # Я первый живой — я мастер if check_node_health(ip): return False # Узел выше меня жив return False ``` ### 2.2 Health Check Protocol HTTP запрос к `/health` endpoint: ```python # leader_election.py:102-134 def check_node_health(ip: str) -> bool: try: url = f"http://{ip}:8889/health" response = requests.get(url, timeout=5) return response.status_code == 200 except: return False ``` **Response format:** ```json { "status": "healthy", "node": "moscow", "uptime": 3600, "is_master": false } ``` ### 2.3 Failover Timing | Событие | Время | |---------|-------| | Health check interval | 5 секунд | | Request timeout | 5 секунд | | Max failover time | < 10 секунд | | Startup delay | 7-15 секунд (рандом) | --- ## 3. Message Types ### 3.1 Telegram Polling Только мастер-узел выполняет polling Telegram API: ```python # junomontanaagibot.py async def start_polling(): if not am_i_the_master(): return # Standby режим await application.run_polling( drop_pending_updates=True, allowed_updates=Update.ALL_TYPES ) ``` ### 3.2 Presence Proof Подпись присутствия (ML-DSA-65): ```python # time_bank.py:271-327 message = f"MONTANA_PRESENCE_V1:{timestamp}:{prev_hash}:{pubkey}:{t2_index}" signature = ML_DSA_65.sign(private_key, message.encode()) proof_hash = SHA256(message || signature) ``` | Поле | Размер | Описание | |------|--------|----------| | version | 20 B | "MONTANA_PRESENCE_V1" | | timestamp | 8 B | Unix timestamp | | prev_hash | 64 B | SHA256 предыдущего proof | | pubkey | 1952 B | ML-DSA-65 public key | | t2_index | 8 B | Номер τ₂ слайса | | signature | 3309 B | ML-DSA-65 подпись | --- ## 4. Защита от Eclipse ### 4.1 Стратегия Eclipse-атака — изоляция узла от честной сети. Защита обеспечивается: 1. **Фиксированная топология** — узлы знают друг друга заранее 2. **Множественные проверки** — ping + TCP fallback 3. **Географическое распределение** — 5 регионов ### 4.2 Multi-method Health Check ```python # leader_election.py:102-134 def check_node_health(ip: str) -> bool: # 1. HTTP health endpoint try: response = requests.get(f"http://{ip}:8889/health", timeout=5) if response.status_code == 200: return True except: pass # 2. Fallback: TCP port check (SSH) try: sock = socket.create_connection((ip, 22), timeout=5) sock.close() return True except: pass # 3. Fallback: TCP port check (HTTPS) try: sock = socket.create_connection((ip, 443), timeout=5) sock.close() return True except: pass return False ``` --- ## 5. Защита от атак ### 5.1 Random Failover При обнаружении атаки цепочка перемешивается: ```python # leader_election.py:395-430 def shuffle_chain_on_attack(): if not attack_detector.is_under_attack(): return shuffled = list(BOT_CHAIN) random.shuffle(shuffled) healthy_nodes = [ (name, ip) for name, ip in shuffled if check_node_health(ip) ] BOT_CHAIN = healthy_nodes # Новый порядок ``` **Пример:** ``` Нормальный режим: amsterdam → moscow → almaty → spb → novosibirsk После атаки: spb → novosibirsk → almaty → moscow (amsterdam исключён как атакованный) ``` ### 5.2 Attack Detection Metrics ```python # leader_election.py:190-232 class AttackDetector: cpu_threshold = 80.0 # % network_threshold = 100 MB/s # входящий трафик max_failures = 10 # подряд response_time_threshold = 5.0 # секунд ``` --- ## 6. Синхронизация состояния ### 6.1 Breathing Sync Git-синхронизация каждые 12 секунд: ``` ┌─────────┐ ┌─────────┐ ┌─────────┐ │ Inhale │────▶│ Work │────▶│ Exhale │ │git pull │ │ 12 sec │ │git push │ └─────────┘ └─────────┘ └─────────┘ ▲ │ └───────────────────────────────┘ ``` **Исходный код:** [breathing_sync.py](../Бот/breathing_sync.py) ### 6.2 Синхронизируемые данные | Данные | Путь | Формат | |--------|------|--------| | База данных | data/montana.db | SQLite | | События | data/events.jsonl | JSON Lines | | Конфигурация | *.py | Python | --- ## 7. Сетевые метрики ### 7.1 Health Status ```python # junomontanaagibot.py:997-1051 def health_check() -> Dict: return { "status": "healthy" | "degraded" | "under_attack", "uptime": int, "metrics": { "cpu_percent": float, # скользящее среднее "memory_percent": float, "disk_percent": float, "active_connections": int, "blocked_ips": int, "suspicious_ips": int } } ``` ### 7.2 Пороги статусов | Статус | Условие | |--------|---------| | healthy | cpu < 90% AND mem < 90% AND suspicious < 5 | | degraded | (cpu > 90% OR mem > 90%) × 3 подряд | | under_attack | attack_detector.under_attack = True | --- ## 8. Деплой и обновление ### 8.1 Rolling Deploy ```bash # deploy_nodes.sh ./deploy_nodes.sh # По одному узлу, 20 сек между ними ./deploy_nodes.sh --fast # Все сразу (downtime!) ./deploy_nodes.sh --node X # Только узел X ``` ### 8.2 Порядок деплоя 1. Обновить amsterdam (PRIMARY) 2. Ждать 20 секунд (failover time) 3. Обновить moscow 4. Ждать 20 секунд 5. ... остальные узлы ### 8.3 Верификация ```bash # Проверка хэшей на всех узлах for ip in 72.56.102.240 176.124.208.93 ...; do ssh root@$ip "md5sum /root/bot/junomontanaagibot.py" done ``` **Ожидаемый результат:** все хэши идентичны. --- ## 9. Диагностика ### 9.1 Проверка статуса узла ```bash ssh root@IP "systemctl status junona" ssh root@IP "journalctl -u junona -n 50 --no-pager" ssh root@IP "curl localhost:8889/health" ``` ### 9.2 Проверка leader election ```bash ssh root@IP "journalctl -u junona | grep -i 'master\|standby'" ``` ### 9.3 Проверка синхронизации ```bash for ip in 72.56.102.240 176.124.208.93 91.200.148.93 188.225.58.98 147.45.147.247; do echo "=== $ip ===" ssh root@$ip "md5sum /root/bot/junomontanaagibot.py | cut -d' ' -f1" done ``` --- ## 10. Ограничения | Ограничение | Описание | Mitigation | |-------------|----------|------------| | Фиксированная топология | Нельзя добавить узел динамически | Требует деплой | | Single Telegram Token | Один токен на всю сеть | Leader Election | | Git-based sync | Не подходит для high-frequency данных | Event Sourcing | --- ## Заключение P2P сеть Montana Protocol обеспечивает: 1. **Отказоустойчивость** — 5 узлов, автоматический failover 2. **Безопасность** — ML-DSA-65, Random Failover при атаке 3. **Консистентность** — Breathing Sync через Git 4. **Мониторинг** — Health endpoints, AtlantGuard Сеть функционирует в MAINNET режиме с января 2026. --- ``` Alejandro Montana Montana Protocol P2P Specification v2.0 2026-01-23 ```