Ковенант Kaspa блокирует средства за скриптом — набором правил, зафиксированных при развёртывании, которые точно определяют, как можно потратить UTXO. Некоторые из этих правил требуют подписи определённым ключом. Другие, называемые безключевыми путями, могут быть отправлены кем угодно: после истечения задержки, по завершении таймера наследования, после закрытия окна спора.
Такая открытость — это преимущество. И одновременно вектор атаки.
Когда срабатывает безключевой путь, человек, формирующий и отправляющий транзакцию, контролирует нечто опасное: какая часть стоимости UTXO уходит в сеть в виде комиссии. Без защитного барьера злоумышленник может создать транзакцию, которая формально соблюдает правила выходов ковенанта — правильный адрес назначения, правильное минимальное значение, — но при этом установить абсурдно высокую сетевую комиссию, сжигая остаток. Бенефициар ковенанта получает свою долю; остальное испаряется в вознаграждения майнерам.
Именно от этого класса атак защищает параметр feeBudget.
feeBudget — параметр конструктора, внедряемый в ковенант Kaspa при развёртывании. Он ограничивает максимальную стоимость, которую ковенант готов потерять при любой одной безключевой транзакции сверх обязательного выхода. Ограничивает как сетевые комиссии, так и любой остаток, направляемый на дополнительные выходы.
Как feeBudget попадает в скрипт
Оба основных ковенанта платформы Kaspa Forge принимают feeBudget в качестве аргумента конструктора. В контракте хранилища (vault.sil, развёрнутом в основной сети Kaspa Toccata) это 9-й параметр. В контракте эскроу (escrow.sil) — 11-й. Компилятор Silverscript встраивает это значение непосредственно в развёрнутый байткод — как только ковенант существует в блокчейне, бюджет становится неизменяемым.
Внутри скрипта большинство путей расходования выполняют проверку по следующей схеме:
require(feeBudget > 0 && feeBudget <= 10_000_000)
Константа 10_000_000 сомпи равна 0,1 KAS. Это потолок на уровне всей платформы, заданный как MAX_FEE_BUDGET. Ни один безключевой путь ни в одном ковенанте Kaspa Forge не может сжечь более 0,1 KAS сверх обязательного выхода — станет ли эта сумма сетевой комиссией или утечёт в дополнительный выход транзакции.
Почему «остаток» важен наряду с комиссиями
Пути ковенанта v3 проверяют обязательный выход — они убеждаются, что outputs[0] платит на правильный адрес назначения не менее определённой минимальной суммы. Но в настоящее время они не проверяют tx.outputs.length. Это означает, что автор транзакции может добавить второй выход, направив до feeBudget остаточной стоимости на свой адрес, а не выплачивая её в качестве сетевой комиссии.
Лимит грифинга по-прежнему действует — общие потери ограничены feeBudget независимо от того, куда уходит остаток. Но это задокументированное ограничение v3: ограничение действует на общие потери, а не конкретно на размер комиссии. Официальные конструкторы транзакций Kaspa Forge всегда формируют единственный канонический выход, поэтому на практике остаток всегда является сетевой комиссией. Более строгая проверка количества выходов запланирована для ревизии контракта v4.
Общая картина платформы: 16 из 17
В обоих основных ковенантах Kaspa Forge задействовано в общей сложности 17 путей расходования:
| Ковенант | Пути | feeBudget соблюдается | Исключение |
|---|---|---|---|
| vault.sil (Kaspa Safe) | 7 | 6 из 7 | migrate — без лимита |
| escrow.sil (Kaspa Escrow) | 10 | все 10 | — |
| Итого | 17 | 16 | 1 исключение |
Единственное исключение — migrate — намеренное.
Почему migrate не подчиняется лимиту
migrate(hotSig, alarmSig) требует подписания транзакции обоими ключами — горячим и тревожным. При двойной авторизации владелец получает неограниченный контроль: путь может перенаправить средства на любой адрес, в любом соотношении, с любой комиссией. Лимит грифинга здесь не дал бы ничего — если оба ключа скомпрометированы, злоумышленник уже обладает полной властью, и потолок комиссии в 0,1 KAS не спасёт хранилище.
Что migrate взамен обеспечивает — это обновляемость. Владелец хранилища может перевести средства из ковенанта v3 в ковенант v4 за одну транзакцию, ротировать горячий ключ или выполнить экстренный выход — всё с помощью тех же двух подписей, которые в обычном режиме защищают хранилище. Именно так Kaspa Safe будет внедрять более строгие проверки количества выходов, не требуя от пользователей закрывать и пересоздавать хранилища.
Многоуровневая защита: feeBudget не один
Лимит комиссии — один из уровней в стеке инвариантов, усиливающих друг друга. Вот как уровни работают вместе:
Уровень 1 — Инвариант единственного входа. Каждый из 17 путей начинается с require(tx.inputs.length == 1). Это предотвращает смежную атаку: слияние двух UTXO ковенанта с одного P2SH-адреса в одной транзакции, при котором излишек от меньшего UTXO утекает в комиссии или побочные выходы. Правило единственного входа делает каждое расходование UTXO полностью независимым — без перекрёстного загрязнения.
Уровень 2 — Лимит feeBudget. Ограничивает максимальные экономические потери на одно безключевое расходование до 0,1 KAS. Основная тема этой статьи.
Уровень 3 — Вычислительные бюджеты. Каждый путь расходования работает под отдельным лимитом сложности скрипта — количеством проверок подписей и операций интроспекции, которые должен выполнить верификатор:
vault normal paths: COMPUTE_BUDGET = 20 (single checkSig + introspection)
vault migrate: MIGRATE_BUDGET = 30 (two checkSig, measured min ~20, with headroom)
escrow mutual: ESCROW_BUDGET = 40 (up to 3 checkSig + 3-output introspection)
На высокопроизводительной цепочке Kaspa, работающей со скоростью 10 блоков в секунду, майнеры оценивают тысячи транзакций в секунду. Неограниченная сложность скрипта стала бы вектором отказа в обслуживании. Вычислительные бюджеты это предотвращают.
Уровень 4 — Сохранение стоимости. Путь арбитража контракта эскроу обеспечивает явное ограничение: out0 + out1 >= in - feeBudget. Это гарантирует, что два выхода (доля покупателя + доля продавца) учитывают полный вход ковенанта за вычетом допустимого бюджета. Никакая стоимость не «теряется» на фантомных выходах.
Вместе:
| Защита | Предотвращает |
|---|---|
| Единственный вход | Перекрёстный перелив стоимости между UTXO |
| Лимит feeBudget | Избыточная комиссия или остаток при одном расходовании |
| Вычислительный бюджет | Отказ в обслуживании через сложность скрипта |
| Сохранение стоимости | Манипуляция выходами на путях с несколькими выходами |
| Разделение ключей | Одностороннее списание при компрометации одного ключа |
Ни одного уровня недостаточно. Стек работает только потому, что каждый инвариант закрывает брешь, которую оставляют другие.
Проверка в блокчейне и вне его
Скрипт в блокчейне обеспечивает верхнюю границу: feeBudget <= 10_000_000 (0,1 KAS). Но внерейновые конструкторы Kaspa Forge — WASM-ядро, работающее в браузере пользователя — применяют более узкий диапазон: [1 000 000 — 10 000 000] сомпи (0,01–0,1 KAS).
Нижняя граница — это чисто внерейновая политика. В блокчейне скрипт требует лишь feeBudget > 0. Стороннее развёртывание может создать ковенант с feeBudget в 1 сомпи — технически допустимо, но практически бесполезно, ведь ни один майнер не примет транзакцию с комиссией ниже минимума ретрансляции.
Такое разделение намеренно. Контракт — это публичный, проверяемый артефакт: каждый может прочитать байткод и верифицировать инвариант. Конструкторы Kaspa Forge добавляют ограничения удобства поверх, не ограничивая то, что другие могут построить на тех же ковенантах Toccata. Механика комиссий за транзакции Kaspa — при которой узлы устанавливают минимумы ретрансляции независимо от майнинговой политики — делает эту нижнюю границу практической необходимостью, а не гарантией на уровне протокола.
Как это выглядит в работающем хранилище
Когда вы создаёте хранилище через Kaspa Safe, feeBudget по умолчанию устанавливается в пределах поддерживаемого диапазона. Каждый безключевой путь в этом хранилище — complete() после задержки вывода, inheritAuto() по истечении таймера наследования — соблюдает этот лимит. Если наблюдатель Kaspa Safe, любой сторонний инструмент или случайный наблюдатель отправит одну из этих транзакций, максимальные потери на комиссии и остаток составят не более 0,1 KAS, независимо от того, сколько KAS хранится в хранилище.
Тот же лимит действует на каждую сделку Kaspa Escrow. Путь autoRelease() (оптимистичное освобождение после окна спора, который наблюдатель отправляет автоматически) и пути timeoutToBuyer()/timeoutToSeller() (защита при недоступности арбитра, единственные пути эскроу без сервисной комиссии) — все они несут ограничение feeBudget. Пути тайм-аута существуют именно для сценария, когда сам сервис исчезает — и их лимит feeBudget гарантирует, что даже враждебный отправитель не сможет воспользоваться этим моментом уязвимости.
Внерейновой барьер на практике
WASM-ядро Kaspa Forge (kaspa-safe-core) отклоняет значения feeBudget за пределами поддерживаемого диапазона ещё до подписания или отправки транзакции. Это означает:
feeBudget < 1_000_000: отклоняется на этапе сборки (создал бы неотправляемый безключевой путь).feeBudget > 10_000_000: отклоняется на этапе сборки (нарушил бы блокчейн-лимит).feeBudget в диапазоне [1_000_000, 10_000_000]: принимается; безключевой путь одновременно допустим и исполняем.
Хранилище или эскроу, созданные через Kaspa Forge, всегда будут в этом диапазоне. Хранилище, созданное другими средствами — напрямую с использованием байткода открытого контракта — технически может иметь любое положительное значение feeBudget, но всё равно будет подчиняться блокчейн-потолку в 0,1 KAS.
Компромиссы и известные ограничения
Недостаток v3 по количеству выходов. Как отмечалось выше, пути v3 проверяют стоимость выходов, но не их количество. Ограничение в 0,1 KAS соблюдается, но в его пределах остаток может уйти на дополнительный выход, а не майнерам. Для Kaspa Forge это косметическая проблема (наши конструкторы формируют канонические транзакции), но для сторонних интеграторов — реальная. v4 её закроет.
feeBudget — не оракул комиссий. Лимит не устанавливает фактическую сетевую комиссию — он лишь ограничивает, сколько ковенант готов потерять. Фактическая комиссия определяется конструктором транзакций на основе текущего состояния сети. Kaspa Forge запрашивает у узла эндпоинт fee-estimate и формирует транзакции с подходящими комиссиями, значительно ниже бюджета.
Лимит пыли в 100 сомпи. Протокол Kaspa устанавливает минимальную стоимость выхода (предел пыли). Лимит feeBudget с этим не взаимодействует — обязательный выход по определению уже превышает предел пыли (выходы хранилищ идут на адреса P2PK/P2SH, выходы эскроу имеют минимум 1 KAS согласно ограничению разделения). Но стоит отметить, что feeBudget не защищает от граничных случаев с пределом пыли; это отдельно обрабатывается проверками стоимости выходов в каждом пути.
Взаимный путь эскроу имеет самый высокий вычислительный бюджет — 40, по сравнению с 20–30 для путей хранилища. Это отражает его сложность: до трёх проверок подписей (покупатель + продаватель + проверка комиссионного выхода) и интроспекция трёх выходов. Лимит feeBudget действует идентично; только вычислительный бюджет больше.
Что это значит для ваших средств
Если вы храните KAS в хранилище Kaspa Safe или используете Kaspa Escrow для P2P-сделки, лимит feeBudget — одна из нескольких невидимых гарантий, защищающих ваши средства в промежутке между моментом, когда безключевой путь становится действительным, и моментом, когда транзакция попадает в блокчейн. Вы никогда не увидите его в интерфейсе — он встроен в байткод контракта при развёртывании и обеспечивается каждым узлом, валидирующим транзакцию.
Лимит в 0,1 KAS намеренно щедрый: он покрывает реалистичные сетевые комиссии как при нормальных, так и при перегруженных условиях, не оставляя пространства для значительного экономического ущерба. На высокопроизводительной цепочке Kaspa, где комиссия за UTXO невелика, а блоки приходят каждую секунду, 0,1 KAS обеспечивает комфортный запас, сохраняя поверхность грифинга пренебрежимо малой.
Ковенант-хранилище Kaspa Safe использует защиту на основе feeBudget, описанную здесь, наряду с обеспечением единственного входа и вычислительными бюджетами — всё прозрачно в контракте с открытым исходным кодом. Операции в блокчейне бесплатны навсегда; необязательная тревожная служба Telegram стоит 100 KAS/год с 30-дневным бесплатным пробным периодом. Создать хранилище →
---
*В этой статье рассматривается механизм feeBudget, реализованный в vault.sil v3 и escrow.sil в основной сети Kaspa Toccata. Байткод контрактов и исходный код конструкторов опубликованы на github.com/Kaspaforge/kaspaforge. Подробнее о системе ковенантов читайте в статье как работают ковенанты Kaspa.*
FAQ
Что такое feeBudget в ковенанте Kaspa?
Параметр конструктора, встроенный в развёрнутый скрипт при создании. Он представляет собой максимальную стоимость, которую ковенант готов потерять при любой одной безключевой транзакции сверх обязательного выхода — ограничивая как сетевые комиссии, так и любой остаток, направленный на дополнительные выходы.
Почему путь migrate хранилища освобождён от лимита feeBudget?
migrate требует одновременно горячий и тревожный ключ. При наличии обеих подписей владелец обладает полными полномочиями; лимит грифинга ограничил бы гибкость обновлений, не добавляя существенной безопасности.
Может ли злоумышленник обнулить моё хранилище Kaspa Safe через завышенные комиссии?
Нет — не более чем на лимит feeBudget, который составляет до 0,1 KAS (10 000 000 сомпи). Безключевые пути, такие как complete() и inheritAuto(), обеспечивают это ограничение непосредственно в скрипте в блокчейне.
Защищает ли feeBudget также сделки Kaspa Escrow?
Да. Все 10 путей расходования эскроу соблюдают feeBudget, включая оптимистичный путь autoRelease и пути тайм-аута, срабатывающие, когда арбитр недоступен.
В чём разница между feeBudget и вычислительным бюджетом?
feeBudget ограничивает экономические потери — максимальную стоимость, которая может покинуть ковенант в виде комиссий или остатка. Вычислительный бюджет ограничивает сложность выполнения скрипта — количество проверок подписей и операций интроспекции, допустимых при верификации.
Что произойдёт, если установить feeBudget слишком низко?
Скрипт в блокчейне требует только feeBudget > 0, поэтому микробюджет технически допустим. Но это делает безключевые пути неотправляемыми: майнеры отклоняют транзакции, комиссия которых ниже минимума ретрансляции. Конструкторы Kaspa Forge устанавливают минимум в 0,01 KAS, чтобы этого избежать.
Держите KAS там, где кражу можно отменить
Ковенант-сейф в мейннете Kaspa: ваши ключи, ваши правила, наш инструмент. Ончейн — бесплатно, навсегда.
Создать сейф
