montana/Русский/Совет/Google/подбор_лотереи_08.01.2026_16:00.md

11 KiB
Raw Permalink Blame History

Security Audit: Lottery Grinding & Bootstrap DoS

Модель: Gemini 3 Pro Компания: Google Дата: 08.01.2026 16:30 UTC


1. Понимание архитектуры

Montana ACP (Atemporal Coordinate Presence) — это сеть, где консенсус достигается не через PoW/PoS, а через "накопление присутствия" (время). Узлы подписывают временные слоты (таймслайсы), доказывая своё существование. Победитель раунда (каждые 10 минут, τ₂) выбирается через детерминированную лотерею.

Ключевые механизмы защиты:

  1. Детерминированная лотерея: Должна зависеть только от предыдущего состояния сети (хеш прошлого слайса), чтобы исключить манипуляции (grinding) в текущем раунде.
  2. Adaptive Cooldown: Защита от Sybil через временнУю стоимость входа (1-180 дней).
  3. Adaptive Subnet Limiter: Защита от сетевых атак (Erebus/DoS) через двухуровневые лимиты подсетей.

Я изучил архитектуру и обнаружил критическую уязвимость в реализации консенсуса.


2. Изученные файлы

Файл LOC Ключевые компоненты
montana/src/consensus.rs 271 Логика лотереи, расчет seed, проверка победителя
montana/src/net/rate_limit.rs 1183 Реализация лимитеров, AdaptiveSubnetLimiter
montana/src/net/protocol.rs 1653 Основной сетевой протокол, обработка сообщений
montana/src/net/bootstrap.rs 1254 Логика начальной загрузки и верификации
montana/src/cooldown.rs 262 Реализация адаптивного кулдауна

3. Attack Surface

Я определил следующие векторы атак:

  1. Манипуляция лотереей (Grinding): Возможность влиять на выбор победителя через изменение содержимого блока.
  2. Блокировка запуска (Bootstrap DoS): Манипуляция медианой сети для принудительного отказа в обслуживании новым узлам.

4. Найденные уязвимости

[CRITICAL] Lottery Grinding (Манипуляция лотереей)

Файл: montana/src/consensus.rs:23

Уязвимый код:

pub fn compute_lottery_seed(prev_hash: &Hash, tau2_index: u64, presence_root: &Hash) -> Hash {
    let mut data = Vec::with_capacity(72);
    data.extend_from_slice(prev_hash);
    data.extend_from_slice(&tau2_index.to_le_bytes());
    data.extend_from_slice(presence_root); // <--- КРИТИЧЕСКАЯ ОШИБКА
    sha3(&data)
}

Описание: В документации (layer_1.md) явно указано, что seed = SHA3-256(prev_slice_hash ‖ τ₂_index). Это гарантирует, что победитель определен до формирования блока. Однако в коде в расчет seed включен presence_root текущего блока. Поскольку presence_root зависит от набора подписей, включенных в блок, а блок формирует сам победитель, это создает циклическую зависимость, которую атакующий может эксплуатировать.

Вектор атаки:

  1. Атакующий (даже с минимальным весом) собирает подписи присутствия (presence signatures) от других узлов.
  2. Вместо публикации всех подписей, атакующий перебирает различные подмножества подписей.
  3. Для каждого подмножества вычисляется новый presence_root.
  4. Новый presence_root дает новый seed лотереи.
  5. Новый seed меняет победителя (функция find_winner).
  6. Атакующий повторяет перебор (Grinding), пока не найдет такой presence_root, при котором seed делает его победителем.
  7. Атакующий публикует валидный блок, где он — законный победитель.

Импакт: Атакующий с минимальным весом может выигрывать лотерею практически в каждом раунде, просто перебирая комбинации подписей. Это полностью ломает модель консенсуса, основанную на времени/весе, и превращает её в PoW-гонку (где "работа" — это хеширование комбинаций подписей). Захват сети возможен с одним слабым узлом.

Сложность: Низкая. Требуется только CPU для хеширования.

PoC сценарий:

// Псевдокод атаки
let signatures = collect_mempool_signatures();
let my_pubkey = my_keypair.public;

for subset in signatures.powerset() {
    let root = compute_merkle_root(subset);
    let seed = compute_lottery_seed(prev_hash, index, root);
    let (winner, _) = find_winner(seed, all_participants);
    
    if winner == my_pubkey {
        publish_block(subset); // PROFIT!
        break;
    }
}

[MEDIUM] Bootstrap DoS via Consensus Manipulation

Файл: montana/src/net/bootstrap.rs:326 (verify_hardcoded_consensus)

Описание: При запуске узел опрашивает 100 пиров (из которых ~20 hardcoded). Он вычисляет медиану высоты цепи по всем ответам. Затем он требует, чтобы каждый hardcoded узел соответствовал этой медиане (с допуском 1%). Если hardcoded узлы отклоняются (потому что медиана смещена атакой), загрузка прерывается с ошибкой CRITICAL.

Вектор атаки: Атакующий окружает новый узел своими пирами (Eclipse) и сообщает ложную высоту (например, сильно большую или малую). Медиана по всем 100 пирам смещается в сторону атакующего. Честные hardcoded узлы (которые сообщают реальную высоту) оказываются "несогласными" с медианой. Узел считает, что hardcoded узлы скомпрометированы, и аварийно останавливается.

Импакт: Полный отказ в обслуживании (DoS) для новых узлов. Они не могут присоединиться к сети.

Сложность: Средняя (требуется контроль входящих соединений жертвы).


5. Атаки, которые НЕ работают

  1. Erebus / Subnet Flood: Код GlobalSubnetLimiter в rate_limit.rs корректно реализует двухуровневую защиту (Fast/Slow tiers) и правильно интегрирован в protocol.rs (вызовы subnet_limiter.check()). Это защищает от атак с использованием множества IP из одной подсети.
  2. Sybil (регистрация): AdaptiveCooldown реализован корректно в cooldown.rs. Спам регистрациями действительно приведет к увеличению кулдауна до 180 дней.
  3. Fake Hardcoded Nodes: HardcodedNode аутентификация через ML-DSA-65 реализована и работает. Подделать hardcoded узел без приватного ключа нельзя.
  4. Inventory Exhaustion: BoundedInvSet использует FIFO удаление старых элементов, что защищает память даже при флуде уникальными инвентарными хешами.

6. Рекомендации

  1. Исправить Lottery Grinding (СРОЧНО): Исключить presence_root из расчета seed в consensus.rs. Seed должен зависеть только от prev_hash и index.

    // Было:
    // data.extend_from_slice(presence_root);
    // Стало:
    // (удалить эту строку)
    

    Это сделает лотерею честной: победитель определяется до того, как он сможет манипулировать содержимым блока.

  2. Улучшить логику Bootstrap: Вместо аварийной остановки при несогласии hardcoded узлов с медианой сети, следует использовать "Trusted Core" подход:

    1. Собрать ответы от всех hardcoded узлов.
    2. Вычислить медиану ТОЛЬКО среди hardcoded узлов (hardcoded_median).
    3. Проверить консенсус внутри hardcoded группы (сколько узлов в пределах ±1% от hardcoded_median).
    4. Если большинство (>50%) hardcoded узлов согласны → считать hardcoded_median истинной.
    5. P2P узлы проверять относительно этой доверенной медианы (warning при расхождении, но не блокировка).
    6. Hardcoded узлы, которые не согласны с hardcoded_median (меньшинство), игнорируются, но не вызывают падения. Это сделает bootstrap устойчивым к Eclipse-атакам, так как атакующий не может подделать подписи hardcoded узлов.

7. Вердикт

[x] CRITICAL — есть уязвимости, позволяющие уничтожить сеть (Lottery Grinding позволяет захватить контроль над блокчейном). [ ] HIGH [ ] MEDIUM [ ] LOW [ ] SECURE