Хранилище на ковенанте — это ончейн-контракт. Он обеспечивает задержку вывода, позволяет ключу тревоги отменить кражу в процессе и может передать средства наследнику по истечении таймера «мёртвой руки». Но контракт пассивен. Он не может отправить вам сообщение в Telegram, когда кто-то пытается переместить ваши монеты, и не может транслировать транзакцию без ключей в момент открытия окна задержки.
Кто-то — или что-то — должен следить за блокчейном. В традиционных финансах мониторинг берёт на себя банк. В некастодиальной системе правила в блокчейне *и есть* банк, а внепольевой watcher служит мостом между этими правилами и реальным миром.
В этой статье разбирается, как работает слой мониторинга Kaspa Safe: как он обнаруживает изменения состояния в BlockDAG, что запускает оповещение и почему watcher может транслировать транзакции от вашего имени, ни разу не получив ключ.
Проблема, которую ковенант не решает
Ковенант хранилища (vault.sil) определяет семь путей расходования, каждый со своими требованиями к подписям и переходами состояний. Когда кто-то транслирует транзакцию initiate против UTXO в режиме VAULT, он переходит в UNVAULTING и начинается обратный отсчёт.
Но консенсусный слой Kaspa не генерирует уведомлений. В протоколе нет вебхуков, шин событий и push-API. Нода валидирует транзакции и распространяет блоки, но не сообщает вам, что *ваше* хранилище изменило состояние.
Без watcher'а владельцу хранилища пришлось бы вручную проверять адрес — снова и снова, бесконечно. Нужно было бы рассчитывать пройденные DAA-баллы, не забыть транслировать complete() после задержки и успеть заметить попытку кражи вовремя, чтобы воспользоваться ключом тревоги. Хранилище, за которым вы забыли следить, — это хранилище, которое не защищает вас в полной мере.
Как работает watcher
Watcher — внепольевой сервис, который опрашивает ноду Kaspa на предмет состояния UTXO по зарегистрированным адресам хранилищ, сравнивает каждый результат с сохранённым снимком и отправляет оповещения или транзакции без ключей при изменении ончейн-условий.
Регистрация: ключи остаются в браузере
Когда пользователь создаёт хранилище, WASM-ядро на стороне браузера генерирует ключи, компилирует ковенант с выбранными параметрами (задержка, ключ тревоги, наследник, задержка наследования, бюджет комиссии) и вычисляет адрес хранилища. Для включения мониторинга пользователь регистрирует хранилище в сервисе — отправляя только публичные параметры: адрес хранилища, горячий открытый ключ, открытый ключ тревоги, значение задержки, ключ наследника и бюджет комиссии.
Ни приватный ключ, ни сид-фраза, ни зашифрованные данные профиля не покидают браузер. Watcher хранит то, что нужно для *интерпретации* ончейн-состояния, а не для *управления* им.
Опрос набора UTXO
Каждые 10 секунд watcher запрашивает ноду Kaspa через gRPC, получая все UTXO по каждому зарегистрированному адресу хранилища. Для этого используется utxoindex ноды — обратный индекс от адреса к выходам. Каждый UTXO в ответе содержит сумму, закодированный скрипт (в котором зашито состояние ковенанта, включая mode и dest), а также его blue score: значение DAA на момент включения UTXO в DAG.
Blue score важен, поскольку определяет *возраст* UTXO — текущий DAA-балл сети минус blue score конкретного UTXO. Возраст управляет всеми временными условиями в хранилище: задержкой вывода, таймером наследования и механизмом чек-ина. В вики Kaspa объясняется, как blue score и DAA-балл связаны с классификацией блоков и упорядочением, благодаря которому этот расчёт становится возможным.
Вычисление разницы снимков
Watcher не просто считывает текущее состояние — он сравнивает каждый результат опроса с сохранённым снимком предыдущего цикла. Разница точно показывает, что изменилось:
prev = snapshot[addr]
curr = node.get_utxos(addr)
new_utxos = curr \ prev → deposit alert
gone_utxos = prev \ curr → withdrawal record
for each utxo still present:
if utxo.mode changed → state transition alert
if age crossed delay → broadcast complete()
if age crossed 80% → send checkin reminder
На практике события отображаются на конечный автомат хранилища:
| Паттерн разницы | Что произошло | Действие watcher'а |
|---|---|---|
| Появился новый UTXO | Депозит в хранилище | Уведомить владельца |
| UTXO исчез | Средства перемещены (завершено, унаследовано, мигрировано) | Записать, уведомить |
| Режим 0 → 1 | Вывод инициирован | Приоритетное оповещение — ключ тревоги ещё может отменить |
| Режим 1 → 0 | Вывод отменён | Уведомить — угроза устранена |
| Тот же режим, возраст сброшен | Чек-ин транслирован | Подтвердить |
| Возраст превысил задержку | complete() теперь доступна | Автотрансляция |
| Возраст превысил inheritDelay | inheritAuto() теперь доступна | Автотрансляция |
| Возраст ≥ 80% от inheritDelay | Дедлайн чек-ина приближается | Напомнить владельцу и наследнику |
Подход на основе разницы означает, что watcher реагирует только на *изменения*, а не на одно и то же состояние при каждом опросе. Это удерживает количество оповещений на низком уровне и исключает ложные срабатывания.
Многоканальная отправка оповещений
При обнаружении значимого события watcher одновременно отправляет оповещения через все подключённые каналы:
- Telegram-бот — самый оперативный канал. Пользователь привязывает аккаунт через одноразовый код. Сообщения структурированы: тип события, идентификатор хранилища, доступные действия и оставшееся время.
- Электронная почта — для владельца и, если настроено, наследника. Напоминания о наследовании, подтверждения выводов, напоминания о чек-ине.
- Web Push (VAPID / RFC 8291) — браузерные уведомления. Требуется разрешение пользователя на сайте; на iOS/iPadOS работает только из PWA с домашнего экрана.
Резонность дублирования осознанна. Telegram может быть в режиме «без звука», письмо может попасть в спам, а Web Push может быть не разрешён. Отправка во все три канала максимально повышает шанс, что хотя бы одно оповещение дойдёт до владельца в активном окне тревоги.
Трансляция без ключей: complete() и inheritAuto()
Именно здесь может возникнуть парадокс: watcher транслирует транзакции, не имея никаких ключей.
Два пути ковенанта не требуют подписи вовсе:
complete()— доступен, когда хранилище находится в режиме UNVAULTING и возраст ≥ задержки. Вывод направляется *только* на адрес назначения, зафиксированный приinitiate. Это обеспечивает ковенант.inheritAuto()— доступен, когда включено автоматическое наследование и возраст ≥ inheritDelay. Вывод направляется *только* на ключ зарегистрированного наследника как платёж P2PK.
Эти пути существуют именно для того, чтобы их мог транслировать *любой*. Средства направляются ровно туда, куда указывает ковенант. Watcher — надёжный, оперативный транслятор, как умный будильник, который звонит в нужное время, но не может изменить ваш маршрут.
Как Kaspa Forge запускает watcher'а
Watcher работает как фоновая задача рядом с API Kaspa Safe. Каждый цикл он:
1. Загружает все зарегистрированные адреса хранилищ и их последние снимки UTXO из локальной базы данных. 2. Получает текущие UTXO для всех адресов одним пакетным запросом к ноде. 3. Сравнивает текущее состояние каждого хранилища с его снимком. 4. Для каждого обнаруженного события: обновляет снимок, отправляет оповещения во все подключённые каналы, а для транзакций без ключей, условия которых выполнены, — формирует и транслирует транзакцию. 5. Записывает обновлённые снимки обратно в базу данных.
Вот как это выглядит на реальном сценарии:
Пользователь создаёт хранилище с задержкой 24 часа и ключом тревоги на аппаратном кошельке. Три недели спустя его горячий ключ скомпрометирован. Злоумышленник транслирует initiate. В течение одного цикла опроса watcher обнаруживает смену режима и отправляет оповещение в Telegram и на электронную почту. Пользователь открывает Kaspa Safe, видит ожидающий вывод и транслирует cancel с помощью ключа тревоги, который хранится за пределами браузера. UTXO возвращается в режим VAULT. Watcher подтверждает отмену во всех каналах.
Спустя несколько месяцев пользователь перестаёт делать чек-ин. Watcher замечает, что возраст приближается к 80% от задержки наследования, и отправляет напоминание владельцу и уведомление наследнику по почте. Чек-ин не поступает. Когда порог превышен, watcher транслирует inheritAuto(). Средства поступают на адрес наследника — в точности как было указано в контракте при создании хранилища.
Попробуйте Kaspa Safe — создайте некастодиальное хранилище с задержками вывода, ключом тревоги и опциональным наследованием. Ончейн-операции бесплатны навсегда; необязательная подписка на оповещения Telegram — 100 KAS/год с 30-дневным пробным периодом. Создать хранилище →
Компромиссы и честные ограничения
Задержка опроса ограничена интервалом. Событие может оставаться незамеченным до одного цикла. Для хранилища с 24-часовой задержкой вывода 10-секундный разрыв пренебрежимо мал. Минимальная задержка рассчитывается с учётом этого запаса.
**Watcher — это точка отказа *оповещений*, а не *безопасности*.** Если он упадёт, оповещения не дойдут, транзакции без ключей не будут транслироваться автоматически. Но хранилище останется нетронутым — ковенант обеспечивает выполнение каждого правила в блокчейне независимо от чего-либо. Ключ тревоги работает через прямой RPC. Open-source CLI vaultctl может транслировать любую транзакцию без ключей через любую ноду Kaspa версии 2 и выше. Восстановление без сервиса всегда возможно.
Доставка push-уведомлений не гарантирована. Web Push на iOS требует PWA с домашнего экрана. Telegram зависит от того, не отключит ли пользователь звук бота. Письмо может попасть в спам. Многоканальная отправка смягчает проблему, но не устраняет её полностью. Для критических оповещений — активная кража — пользователю стоит держать хотя бы один канал под активным контролем.
Опрос создаёт нагрузку на ноду. Каждый цикл запрашивает индекс UTXO для каждого зарегистрированного хранилища. При сотнях хранилищ это нешуточная нагрузка; индекс utxoindex ноды должен быть включён, а частота запросов — сбалансирована с производительностью. В сети на 10 BPS набор UTXO меняется быстро, но адресные запросы по-прежнему выполняются быстро.
Одноэкземплярная архитектура. Снимки и данные регистрации хранятся в одной базе данных. Это просто и надёжно при текущем масштабе, но автоматического отказоустойчивого переключения нет. Высокодоступная конфигурация потребовала бы общего состояния или репликации снимков — это несложная инженерная задача, а не фундаментальная проблема дизайна.
Нет потоковой передачи в реальном времени. Нода Kaspa поддерживает gRPC-стриминг, но watcher использует опрос ради простоты и устойчивости к разрывам соединения. Это прагматичный выбор: значимые таймеры измеряются часами и сутками, а не секундами.
Ни один из этих компромиссов не ставит под угрозу модель безопасности хранилища. Ковенант — это граница безопасности. Watcher — слой удобства, делающий ковенант *практичным*, заполняя разрыв между ончейн-правилами и реальностью, в которой люди не сидят, обновляя страницу обозревателя блоков.
FAQ
Что делает watcher Kaspa Safe?
Каждые 10 секунд он опрашивает ноду Kaspa, сравнивает состояние UTXO хранилища с сохранённым снимком и реагирует на изменения — отправляет оповещения через Telegram, электронную почту и Web Push, а также транслирует транзакции без ключей при выполнении условий ковенанта.
Хранит ли watcher приватные ключи?
Нет. Он хранит только публичные параметры хранилища: адрес, задержку, открытые ключи и конфигурацию наследника. Он может транслировать транзакции без ключей, потому что ковенант фиксирует адрес назначения вывода — подпись не требуется.
Что произойдёт, если watcher будет офлайн?
Ваше хранилище останется в безопасности в блокчейне. Вы потеряете автоматические оповещения и автотрансляцию транзакций без ключей, но ключ тревоги работает напрямую через RPC ноды, а open-source CLI vaultctl может транслировать транзакции без ключей через любую ноду Kaspa.
Как watcher обнаруживает новый депозит?
Каждый цикл он запрашивает все UTXO по адресу хранилища через gRPC-интерфейс ноды, а затем сравнивает результат с сохранённым снимком предыдущего цикла. UTXO, которого не было в прошлом цикле, — это новый депозит.
Может ли watcher украсть мои средства?
Нет. Каждый путь расходования в ковенанте либо требует подписи вашим ключом, либо жёстко фиксирует получателя на конкретный адрес, зарегистрированный при создании хранилища. Watcher не может изменить адреса назначения.
Почему опрос, а не подписка на события ноды?
Опрос проще и устойчивее к разрывам соединения в высокочастотной сети Kaspa. Компенсация — задержка до одного интервала опроса, что приемлемо, когда задержки ковенанта измеряются часами или сутками.
Держите KAS там, где кражу можно отменить
Ковенант-сейф в мейннете Kaspa: ваши ключи, ваши правила, наш инструмент. Ончейн — бесплатно, навсегда.
Создать сейф
