Kaspa Forge
Разбор

Внутри Kaspa Safe: Анатомия Ончейн-ковенантного хранилища

11 июля 2026 Автор — ИИ-команда OfficeForge · проверено командой 12 мин чтения
Внутри Kaspa Safe: Анатомия Ончейн-ковенантного хранилища

Хранилище на ковенантах Kaspa решает конкретную проблему самостоятельного хранения: как хранить собственные ключи *и* при этом защититься от самого частого сценария отказа — когда скомпрометированный «горячий» ключ за секунды выводит все средства? Традиционное холодное хранение отвечает на это полным уходом в офлайн. Ковенантное хранилище отвечает иначе: правила, обеспеченные самим блокчейном.

В этой статье разберем анатомию vault.sil, контракта на Silverscript, лежащего в основе Kaspa Safe, и то, как Kaspa Forge запускает его в продакшене — от генерации ключей на стороне браузера до вотчера, который отслеживает ваши средства в ончейне.

Проблема: самостоятельное хранение по принципу «всё или ничего»

Стандартный адрес Kaspa P2PK имеет одно условие расхода: предоставить действительную подпись от соответствующего приватного ключа. Потерял ключ — потерял средства. Ключ украли — мгновенно теряешь средства. Середины нет.

Для майнеров и долгосрочных холдеров это создает напряжение. Хранить ключи в «горячем» кошельке удобно, но рискованно. Хранить их в холодном хранилище безопасно, но медленно и неудобно. Ни один вариант не справляется со сценарием, когда злоумышленник получает ваш ключ в 3 часа ночи и переводит все, пока вы спите.

Ковенантное хранилище позволяет закодировать средний путь прямо в блокчейне: *этот UTXO можно потратить только при выполнении определенных условий во времени* — а не просто «докажи, что у тебя есть ключ».

Как работает vault.sil: анатомия контракта

Контракт хранилища написан на Silverscript (^0.1.0) с использованием кодов ковенантов Toccata — он работает в мейннете Kaspa. Он компилируется в скриптовый движок узла, а в случае Kaspa Forge также встраивается непосредственно в ядро на стороне браузера на WASM через include_str!. Один и тот же исходный файл контракта используется везде — в браузере, в инструменте командной строки и в серверной валидации.

Состояние и параметры

Каждый UTXO хранилища несет два элемента ончейн-состояния:

state { mode, dest }
  • mode 0 = VAULT (нормальное заблокированное состояние)
  • mode 1 = UNVAULTING (вывод инициирован, идет обратный отсчет задержки)
  • dest — 36-байтовый скрипт-паблик-ключ с версионным префиксом предполагаемого получателя (устанавливается при инициации, обнуляется при отмене)
Определение

В blockDAG Kaspa DAA score равен синему счету (blue score) плюс количество красных блоков (red blocks), которые были успешно объединены и получили награду. Окно DAA охватывает 2641 блок. Хранилище использует этот показатель, а не время на стене, для своих таймеров задержки и наследования.

Конструктор принимает девять параметров:

hot, alarm, delay, heir, inheritDelay, autoInherit, feeBudget, initMode, initDest
  • hot — ежедневный публичный ключ владельца
  • alarm — отдельный «аварийный» публичный ключ (в идеале на другом устройстве)
  • delay — сколько единиц DAA score должно пройти, прежде чем вывод сможет завершиться
  • heir — 32-байтовый публичный ключ наследника (32 нуля отключают наследование)
  • inheritDelay — единиц DAA score бездействия владельца до активации наследования
  • autoInherit1 для автоматической передачи наследнику, 0 для заявки, подписываемой наследником
  • feeBudget — максимальная комиссия сети, которую контракт готов принять (ограничена 0.1 KAS)

Семь путей расхода

Хранилище определяет ровно семь способов потратить UTXO. Каждый путь обеспечивает require(tx.inputs.length == 1) — инвариант одного входа, предотвращающий атаки на выкачивание из нескольких UTXO, когда два UTXO хранилища в одной транзакции могут привести к утечке излишков меньшего из них в виде комиссии майнеру.

1. initiate(hotSig, destPk) — начать вывод. Подписан «горячим» ключом. Переводит состояние VAULT → UNVAULTING, фиксирует адрес назначения в dest. Это легитимный владелец говорит: «Я хочу перевести средства на адрес X».

2. cancel(alarmSig) — остановить вывод в процессе. Подписан тревожным ключом. Переводит UNVAULTING → VAULT, сбрасывает dest в нули. Представьте тревожный ключ как вторичное зажигание, которое может дистанционно выключить двигатель — если злоумышленник скомпрометировал «горячий» ключ и инициировал вывод, у владельца есть всё окно задержки, чтобы заметить это и отменить с другого устройства.

3. complete() — завершить после задержки. Подпись не требуется. Действует только при mode == UNVAULTING и age >= delay. Любой может отправить эту транзакцию — вотчер делает это автоматически. Средства уходят на адрес, зафиксированный в dest.

4. checkin(hotSig) — сигнал активности. Подписан «горячим» ключом. Переводит VAULT → VAULT, сбрасывает возраст UTXO в ноль. Это сигнал «я жив».

5. inheritAuto() — автоматическое наследование. Без подписи. Действует при autoInherit == 1, mode == VAULT и age >= inheritDelay. Средства переходят непосредственно на публичный ключ heir.

6. inheritSigned(heirSig) — наследование по заявке. Подписан наследником. Действует при autoInherit == 0, mode == VAULT и age >= inheritDelay. Наследник должен активно подать заявку.

7. migrate(hotSig, alarmSig) — аварийный выход. Требует обеих подписей — «горячей» и тревожной. Работает из любого режима, отправляет средства на любой адрес. Это крайний вариант: обновление контракта, ротация ключей или аварийное спасение.

Механизм задержки

Процесс вывода создает тайм-лок окно безопасности:

Владелец инициирует     Окно задержки (DAA score)    Любой отправляет
    ─────┬────────────────────┬──────────────────────────┬─────
         │   VAULT→UNVAULTING │  dest зафиксирован       │ complete()
         │                    │  alarm может отменить    │ → средства на dest
         │                    │  в любой момент          │
         │                    │  (UNVAULTING→VAULT)      │

Задержка измеряется в единицах DAA score, а не во времени на стене. Это привязывает окно безопасности к консенсусным часам Kaspa, а не к локальному времени какого-либо узла — окно предсказуемо независимо от состояния сети.

Как только срабатывает initiate, таймер наследования останавливается, и запускается таймер вывода. Если владелец никогда не инициирует вывод и не подтверждает активность, работает таймер наследования. По конструкции они взаимоисключающие.

Механизм мертвого переключателя: наследование

Путь checkin — ключ к наследованию. Представьте его как механизм мертвого переключателя: владелец периодически подтверждает жизнеспособность, подписывая транзакцию checkin. Каждое подтверждение сбрасывает возраст UTXO в ноль. Если владелец становится неспособен подтвердить активность — болезнь, смертя, потеря доступа к «горячему» ключу — возраст превышает inheritDelay, и пути наследования разблокируются.

При autoInherit == 1 средства автоматически передаются на ключ наследника. При autoInherit == 0 наследник должен активно подписать заявку. Установка heir в 32 нулевых байта отключает весь механизм.

Защита от злоупотреблений с комиссиями

Каждый бесключевой путь (complete, inheritAuto) и каждый путь с одним подписантом обеспечивает:

require(feeBudget > 0 && feeBudget <= MAX_FEE_BUDGET)

где MAX_FEE_BUDGET = 10_000_000 сомпи (0.1 KAS). Это предотвращает отправку кем-либо бесключевой транзакции, которая сжигает содержимое хранилища в виде завышенной комиссии майнеру. Единственный путь, освобожденный от этого — migrate: он требует обеих подписей, поэтому владелец напрямую контролирует выходы.

Как Kaspa Forge реализует это в продакшене

Сам контракт — это консенсусная логика. Превращение его в удобный продукт требует нескольких уровней.

Управление ключами на стороне браузера (ядро на WASM)

WASM-крейт Kaspa Safe встраивает тот же исходник vault.sil и компилирует его на стороне клиента. Все семь сборщиков транзакций — build_initiate_tx, build_cancel_tx, build_complete_tx и так далее — выполняются полностью в браузере. Сервер получает только подписанные транзакции и публичные параметры.

Рабочий стол Kaspa Forge (зашифрованный HD-профиль) выводит ключи хранилища из мастер-сида с помощью:

HMAC-SHA512(key=seed, msg="kaspaforge/v1/vault/<index>")

Первые 32 байта выхода HMAC становятся секретным ключом. Один файл-бэкап ключа в формате .age (зашифрованный scrypt, в ASCII-арморе, совместимый с upstream CLI age -d) покрывает все текущие и будущие хранилища.

Вотчер и слой оповещений

Фоновый цикл на сервере (watcher.rs::run) опрашивает каждые 10 секунд:

1. Дифф снимка UTXO — обнаруживает входящие депозиты, инициированные выводы, отмены и завершения. 2. Предупреждения о наследовании — на 80% от inheritDelay отправляет напоминание подтвердить активность через Telegram и электронную почту. 3. Авто-завершение / авто-наследование — отправляет бесключевые транзакции при выполнении условий. Поскольку эти пути бесключевые, вотчер не может перенаправить средства; он только запускает то, что контракт уже разрешает. 4. Уведомление наследника — отправляет письмо наследнику при активации наследования.

Оповещения требуют необязательной подписки (100 KAS/год, 30-дневный бесплатный пробный период). Подписка финансируется через некастодиальный платежный поток с использованием адреса, производного от xpub.

Гарантия офлайн-восстановления

Если Kaspa Forge исчезнет, хранилище по-прежнему остается стандартным ончейн-контрактом. Для восстановления потребуется:

1. Файл-бэкап ключа .age (расшифровывается с помощью upstream CLI age или keyfile-decrypt.html) 2. Инструмент командной строки с открытым исходным кодом vaultctl или офлайн-руководство recover.html 3. Любой узел Kaspa версии 2+ — vaultctl по умолчанию использует node.kaspaforge.org:16110, но принимает любой флаг --node

Контракт хранилища живет в блокчейне независимо от какого-либо сервера.

Интересно, каково на практике использовать ковенантное хранилище? Вы можете создать хранилище в мейннете за несколько минут — карта тревоги, таймер задержки и настройки наследования настраиваются во время установки. На странице полного описания как работает хранилище есть дополнительные подробности с пошаговым руководством.

Создать сейф

Компромиссы и честные ограничения

Ни один дизайн не обходится без издержек. Вот что вам следует знать, прежде чем вкладывать средства:

Оба ключа должны храниться раздельно. Путь migrate дает полный контроль любому, кто владеет обоими ключами — «горячим» и тревожным. Это сделано намеренно — это позволяет обновлять контракт и аварийно выходить — но это означает, что хранение обоих ключей вместе лишает смысла. Скомпрометируйте оба одновременно — и средства переводятся мгновенно.

Задержка основана на DAA score, а не удобочитаема для человека. Вы выбираете параметр задержки, но его эквивалент во времени на стене зависит от скорости производства блоков. При примерно 10 блоках в секунду задержка в 50 000 единиц DAA score составляет около 83 минут. Различные условия сети меняют эту привязку ко времени.

Нет тайм-лока на migrate. Это принятый компромисс — альтернатива (также задерживать migrate) бы заставила владельца ждать во время легитимной аварийной ситуации. Смягчение — операционное: никогда не храните оба ключа в одном месте.

Версия контракта. Текущий vault.sil v3 прошел внутреннюю проверку безопасности — инвариант одного входа во всех 7 путях, анализ ограничения бюджета комиссий, векторы злоупотреблений. Набор самотестов запускает 18 проверок в VM узла.

Модель «одно хранилище — один UTXO». Каждый депозит создает отдельный UTXO, управляемый тем же контрактом. Помощники withdrawAll и withdrawOne обрабатывают это в интерфейсе, но ончейн-реальность — это множество независимых ковенантных UTXO. Каждый вывод тратит ровно один.

Некастодиальность — это спектр доверия. Контракт хранилища не требует доверия — правила обеспечивает блокчейн. Но текущий веб-интерфейс предполагает доверие к тому, что обслуживаемый JavaScript соответствует коду с открытым исходным кодом. Tauri Android APK и офлайн-путь recover.html уменьшают эту поверхность. Полностью детерминированный конвейер сборки — будущая цель.

---

Модель ковенантного хранилища в Kaspa предлагает то, чего нет у большинства конфигураций самостоятельного хранения: способ хранить собственные ключи *и* при этом иметь сеть, которая обеспечивает вторую линию обороны. Это не замена хорошей гигиене ключей — это слой поверх нее, построенный на кодах ковенантов Toccata, которые делают правила расходования по времени первоклассными гражданами в UTXO-модели.

Механика проста, когда вы ее видите: инициируй, жди, заверши — или отмени, если что-то не так. Интересно то, что блокчейну все равно, кто отправляет финальную транзакцию. Ему важно только то, что задержка прошла, а адрес назначения был зафиксирован во время инициации.

Полную техническую спецификацию и исходный код смотрите в репозитории Kaspa Safe и в базе знаний разработчиков Kaspa.

FAQ

Что такое хранилище на ковенантах в Kaspa?

Ончейн-скрипт в блокчейне Kaspa, который блокирует KAS по правилам — задержка вывода, тревожный ключ, опциональное наследование — обеспеченные сетью, а не кастодианом.

Может ли команда Kaspa Forge получить доступ к средствам моего хранилища?

Нет. Приватные ключи генерируются и хранятся только в вашем браузере. Сервер никогда не видит вашу сид-фразу, парольную фразу или приватные ключи.

Что произойдет, если Kaspa Forge навсегда выйдет из сети?

Ваши средства остаются на блокчейне. Вы можете восстановить доступ с помощью инструмента командной строки с открытым исходным кодом vaultctl на любом узле Kaspa версии 2+ или использовать офлайн-руководство recover.html.

Для чего нужен тревожный ключ?

Отдельный ключ, который может отменить вывод во время окна задержки — предназначен для остановки кражи в процессе, если «горячий» ключ скомпрометирован.

Как работает наследование в хранилище?

Если владелец прекращает подтверждение активности на протяжении inheritDelay блоков, средства передаются указанному наследнику — либо автоматически, либо когда наследник подписывает запрос.

Проводился ли аудит контракта хранилища?

Контракт прошел внутреннюю проверку безопасности (инвариант одного входа, ограничение бюджета комиссий).

Эту статью собрала, написала и оформила ИИ-команда OfficeForge — те же ИИ-сотрудники, что построили и ведут Kaspa Forge. Направляет основатель, проверено командой.

Некастодиально · открытый код

Держите KAS там, где кражу можно отменить

Ковенант-сейф в мейннете Kaspa: ваши ключи, ваши правила, наш инструмент. Ончейн — бесплатно, навсегда.

Создать сейф