15 KiB
Montana Protocol — Security Specification
Техническая спецификация защиты сети
Version: 2.0 Status: MAINNET Date: 2026-01-23 Authors: Alejandro Montana
Abstract
Montana Protocol представляет собой распределённую систему консенсуса, основанную на доказательстве присутствия во времени (Atemporal Coordinate Presence, ACP). Настоящая спецификация описывает криптографические, сетевые и программные защитные механизмы протокола.
Базовые защитные механизмы:
- ML-DSA-65 (FIPS 204) — постквантовая цифровая подпись
- 5-Node Leader Election — распределённое управление без единой точки отказа
- Attack Detection + Random Failover — обнаружение атак и непредсказуемое переключение мастера
- Breathing Sync — git-синхронизация состояния сети
- Temporal Coordinates (τ₁, τ₂, τ₃, τ₄) — иерархические временные единицы
- Halving Mechanism — дефляционная эмиссия
- AtlantGuard — защита узла от ресурсных атак
1. Топология сети
1.1 Узлы сети
Montana Protocol функционирует на 5 географически распределённых узлах:
| Позиция | Узел | IP | Регион | Роль |
|---|---|---|---|---|
| 0 | amsterdam | 72.56.102.240 | EU | PRIMARY |
| 1 | moscow | 176.124.208.93 | RU-Central | MIRROR 1 |
| 2 | almaty | 91.200.148.93 | KZ | MIRROR 2 |
| 3 | spb | 188.225.58.98 | RU-NW | MIRROR 3 |
| 4 | novosibirsk | 147.45.147.247 | RU-Siberia | MIRROR 4 |
Исходный код: leader_election.py:39-46
BOT_CHAIN: List[Tuple[str, str]] = [
("amsterdam", "72.56.102.240"),
("moscow", "176.124.208.93"),
("almaty", "91.200.148.93"),
("spb", "188.225.58.98"),
("novosibirsk", "147.45.147.247"),
]
1.2 Конфигурация узлов
Каждый узел идентифицируется через переменную окружения MONTANA_NODE_NAME:
[Service]
Environment="MONTANA_NODE_NAME=moscow"
Environment="PYTHONUNBUFFERED=1"
WatchdogSec=60
Restart=always
RestartSec=15
TimeoutStopSec=30
MemoryMax=512M
MemoryHigh=400M
Исходный код: junona.service
2. Криптографическая безопасность
2.1 ML-DSA-65 (FIPS 204)
Montana Protocol использует постквантовый алгоритм подписи ML-DSA-65 (Module Lattice Digital Signature Algorithm), стандартизованный NIST как FIPS 204.
| Параметр | Значение |
|---|---|
| Алгоритм | ML-DSA-65 (Dilithium) |
| Стандарт | FIPS 204 |
| Уровень безопасности | NIST Level 3 |
| Private Key | 4032 байта |
| Public Key | 1952 байта |
| Signature | 3309 байт |
| Адрес | mt + SHA256(pubkey)[:20].hex() = 42 символа |
Исходный код: node_crypto.py
2.2 Формат адреса
def generate_address(public_key: bytes) -> str:
"""Генерация Montana адреса из публичного ключа ML-DSA-65."""
hash_bytes = hashlib.sha256(public_key).digest()[:20]
return "mt" + hash_bytes.hex() # mt + 40 hex chars = 42 total
Пример адреса: mt7a3f2e1d4c5b6a8f9e0d1c2b3a4f5e6d7c8b9a0
3. Leader Election
3.1 Алгоритм выбора мастера
Детерминированный алгоритм определения активного мастера:
def am_i_the_master(self) -> bool:
"""Проверяет, является ли текущий узел мастером."""
for name, ip in self.chain:
if name == self.node_name:
return True # Дошли до себя — я мастер
if check_node_health(ip):
return False # Узел выше жив — он мастер
return False
Исходный код: leader_election.py:326-349
3.2 Health Check
Проверка здоровья узла выполняется через HTTP endpoint на порту 8889:
def check_node_health(ip: str) -> bool:
"""Проверяет здоровье узла через HTTP health endpoint."""
try:
url = f"http://{ip}:8889/health"
response = requests.get(url, timeout=5)
return response.status_code == 200
except:
return False
Исходный код: leader_election.py:102-134
3.3 Интервалы проверки
| Параметр | Значение | Назначение |
|---|---|---|
| CHECK_INTERVAL | 5 сек | Интервал проверки здоровья узлов |
| STARTUP_DELAY | 7-15 сек | Задержка при старте (избежание конфликта polling) |
| FAILOVER_TIME | < 10 сек | Время переключения на резервный узел |
4. Обнаружение атак
4.1 AttackDetector
Класс AttackDetector отслеживает метрики, указывающие на атаку:
class AttackDetector:
def __init__(self):
self.failure_count = 0
self.max_failures = 10
self.response_times = deque(maxlen=10)
self.cpu_threshold = 80.0
self.response_time_threshold = 5.0
self.network_threshold = 100 * 1024 * 1024 # 100 MB/s
self.under_attack = False
Исходный код: leader_election.py:190-232
4.2 Метрики обнаружения атак
| Метрика | Порог | Действие |
|---|---|---|
| CPU Usage | > 80% | Флаг атаки |
| Network Traffic | > 100 MB/s входящего | Флаг атаки |
| Failure Count | > 10 подряд | Флаг атаки |
| Response Time (avg) | > 5 секунд | Флаг атаки |
4.3 Random Failover при атаке
При обнаружении атаки цепочка узлов перемешивается случайным образом:
def shuffle_chain_on_attack(self, external_trigger: bool = False):
"""Перемешивает цепочку при обнаружении атаки."""
if not self.attack_detector.is_under_attack() and not external_trigger:
return
logger.warning("АТАКА ОБНАРУЖЕНА! Переход на случайный failover")
shuffled = list(self.chain)
random.shuffle(shuffled)
healthy_nodes = [
(name, ip) for (name, ip) in shuffled
if check_node_health(ip)
]
if healthy_nodes:
self.chain = healthy_nodes
self.chain_shuffled = True
Исходный код: leader_election.py:395-430
5. AtlantGuard — Защита узла
5.1 Архитектура
Класс AtlantGuard обеспечивает локальную защиту узла от ресурсных атак:
class AtlantGuard:
def __init__(self):
self.start_time = time.time()
self.request_log = {}
self.registration_log = []
self.suspicious_ips = set()
self.blocked_ips = set()
self.cpu_history = [] # Буфер последних 5 измерений CPU
self.degraded_count = 0 # Счётчик высоких значений подряд
Исходный код: junomontanaagibot.py:709-754
5.2 Health Check с защитой от ложных срабатываний
Метод health_check() использует скользящее среднее CPU для предотвращения ложных алертов:
def health_check(self) -> Dict[str, Any]:
# Скользящее среднее CPU (последние 5 измерений)
cpu_instant = psutil.cpu_percent(interval=None)
self.cpu_history.append(cpu_instant)
if len(self.cpu_history) > 5:
self.cpu_history.pop(0)
cpu_avg = sum(self.cpu_history) / len(self.cpu_history)
# Защита от ложных спайков: требуем 3 подряд высоких значения
if cpu_avg > 90 or memory.percent > 90:
self.degraded_count += 1
if self.degraded_count >= 3:
status = "degraded"
else:
status = "healthy"
else:
status = "healthy"
self.degraded_count = 0
Исходный код: junomontanaagibot.py:1001-1051
5.3 Пороги AtlantGuard
| Метрика | Порог | Статус |
|---|---|---|
| CPU (среднее за 5 измерений) | > 90% | degraded (после 3 подряд) |
| Memory | > 90% | degraded (после 3 подряд) |
| Suspicious IPs | > 5 | degraded |
| Under attack flag | true | under_attack |
5.4 Rate Limiting
MAX_REQUESTS_PER_MINUTE = 60 # Запросов/мин с одного источника
MAX_REGISTRATIONS_PER_HOUR = 20 # Новых регистраций/час
MAX_NODE_SYNCS_PER_MINUTE = 10 # Синхронизаций узла/мин
MAX_API_CALLS_PER_MINUTE = 100 # API вызовов/мин на endpoint
Исходный код: junomontanaagibot.py:734-738
6. Breathing Sync
6.1 Механизм синхронизации
Git-синхронизация состояния сети каждые 12 секунд:
Цикл:
Вдох (Inhale) — git pull с rebase
↓
12 секунд работы
↓
Выдох (Exhale) — git add + commit + push
↓
Повтор
Исходный код: breathing_sync.py
6.2 Интеграция с Leader Election
Breathing Sync активируется только для мастер-узла:
only_when_master=True
is_master_func=lambda: self.is_master
7. Временные координаты
7.1 Иерархия
| Единица | Длительность | Назначение |
|---|---|---|
| τ₁ | 60 секунд | Интервал подписи Presence Proof |
| τ₂ | 600 секунд (10 минут) | Слайс эмиссии |
| τ₃ | 1,209,600 секунд (14 дней) | Checkpoint |
| τ₄ | 126,144,000 секунд (4 года) | Эпоха халвинга |
7.2 Соотношения
1 τ₄ = 104 τ₃ = 209,664 τ₂ = 126,144,000 секунд
1 τ₃ = 2016 τ₂ = 1,209,600 секунд
1 τ₂ = 10 τ₁ = 600 секунд
Исходный код: time_bank.py:44-80
8. TIME_BANK
8.1 Резерв
BANK_TOTAL_MINUTES = 21_000_000 # 21 млн минут (~40 лет)
BANK_TOTAL_SECONDS = 1_260_000_000 # 1.26 млрд секунд
8.2 Halving
def halving_coefficient(tau4_count: int) -> float:
"""Коэффициент халвинга для текущей эпохи."""
return 1.0 / (2 ** tau4_count)
| Эпоха τ₄ | Годы | Коэффициент | 1 секунда = |
|---|---|---|---|
| 0 | 0-4 | 1.0 | 1.0 Ɉ |
| 1 | 4-8 | 0.5 | 0.5 Ɉ |
| 2 | 8-12 | 0.25 | 0.25 Ɉ |
| 3 | 12-16 | 0.125 | 0.125 Ɉ |
Исходный код: time_bank.py:88-113
9. Синхронизация сети
9.1 Состояние на 2026-01-23
| Узел | MD5 Hash | Статус | Python | telegram-bot |
|---|---|---|---|---|
| amsterdam | 5a0ac1903151eef7a85cd72f3060eb6c | active | 3.12.3 | 22.5 |
| moscow | 5a0ac1903151eef7a85cd72f3060eb6c | active | 3.12.3 | 22.5 |
| almaty | 5a0ac1903151eef7a85cd72f3060eb6c | active | 3.12.3 | 22.5 |
| spb | 5a0ac1903151eef7a85cd72f3060eb6c | active | 3.12.3 | 22.5 |
| novosibirsk | 5a0ac1903151eef7a85cd72f3060eb6c | active | 3.12.3 | 22.5 |
9.2 Деплой
Rolling deploy выполняется скриптом deploy_nodes.sh:
./deploy_nodes.sh # Rolling deploy (по одному)
./deploy_nodes.sh --fast # Быстрый deploy (опасно)
./deploy_nodes.sh --node moscow # Только один узел
Исходный код: deploy_nodes.sh
10. Файловая структура
Монтана_Montana_蒙大拿/Русский/Бот/
├── junomontanaagibot.py # Главный бот (229 KB)
├── leader_election.py # Leader Election + AttackDetector
├── time_bank.py # TIME_BANK + Presence Proofs
├── node_crypto.py # ML-DSA-65 криптография
├── breathing_sync.py # Git синхронизация
├── montana_db.py # База данных + Event Sourcing
├── junona_ai.py # AI интеграция (OpenAI/Anthropic)
├── contracts.py # Смарт-контракты времени
├── deploy_nodes.sh # Скрипт деплоя
└── junona.service # Systemd unit
11. Известные ограничения
| Проблема | Severity | Статус |
|---|---|---|
| Split-brain через local lock | HIGH | Требует distributed lock |
| tau4_count не персистит | MEDIUM | Сбрасывается при рестарте |
| time.time() может быть изменён root | LOW | Требует time.monotonic() + NTP |
| Presence Proofs не верифицируются | MEDIUM | Генерируются, но не проверяются |
Заключение
Montana Protocol реализует многоуровневую защиту:
- Постквантовая криптография (ML-DSA-65) — защита от квантовых компьютеров
- 5-Node Leader Election — отсутствие единой точки отказа
- AtlantGuard со скользящим средним — защита от ложных алертов
- Random Failover — непредсказуемость при атаке
- Breathing Sync — консистентность состояния сети
Alejandro Montana
Montana Protocol Security Specification v2.0
2026-01-23