Когда вы нажимаете «Отправить» в некастодиальном кошельке Kaspa, запускается цепочка событий, структурно отличная от того, что происходит внутри кастодиальной биржи. Ни один сервер не хранит ваши ключи. Ни одна база данных не отслеживает ваш баланс. Ваш браузер является фабрикой транзакций: он находит ваши средства, формирует транзакцию, подписывает её ключом, который никогда не покидает устройство, и передаёт подписанный блок данных для ретрансляции в сеть.
В этой статье мы проследим этот путь от начала до конца — от обнаружения UTXO в браузере через блокчейн blockDAG Kaspa до подтверждения в цепочке — на примере архитектуры Kaspa Forge.
Проблема, которую создаёт самостоятельное хранение
В кастодиальной системе сервер сервиса формирует и подписывает транзакции от вашего имени. Он хранит ваши приватные ключи, выбирает UTXO, рассчитывает комиссии и отправляет результат. Просто для пользователя; рискованно для денег пользователя.
Некастодиальный кошелёк переворачивает модель доверия: всю работу выполняет ваш браузер. Сервер — это ретранслятор и источник данных: он сообщает вам, какие UTXO существуют, и пересылает вашу подписанную транзакцию нодe Kaspa, — но он никогда не видит ваш приватный ключ и никогда не формирует транзакцию за вас.
Это создаёт инженерную проблему. Браузер должен уметь компилировать скрипты ковенантов, формировать корректные транзакции, подписывать их с помощью secp256k1 и сериализовать в формат, принимаемый нодой. Kaspa Forge решает это с помощью единой кодовой базы на Rust, компилируемой в WebAssembly для браузера и в нативную библиотеку для сервера.
Шаг 1: Поиск того, что можно потратить — Обнаружение UTXO
Каждая транзакция Kaspa начинается с вопроса: *что мне принадлежит?*
Kaspa использует модель UTXO (Unspent Transaction Output), унаследованную от Bitcoin. Ваш баланс — не единое число в реестре, а набор дискретных «монет», каждая из которых заблокирована на конкретном адресе. Когда вы получаете 100 KAS, вы не получаете запись о балансе; вы получаете один или несколько UTXO, привязанных к вашему адресу. Когда вы тратите 30 KAS из UTXO номиналом 100 KAS, протокол уничтожает исходный UTXO и создаёт два новых: 30 KAS получателю и примерно 70 KAS вам обратно в качестве сдачи.
UTXO (Unspent Transaction Output): дискретный, неделимый блок монет Kaspa, заблокированный на адресе. Тратится целиком, сдача приходит в виде нового UTXO. Баланс вашего кошелька — это сумма всех ваших UTXO.
Кошелёк Desk в Kaspa Forge хранит мастер-сид, из которого выводятся несколько адресов (через производную HMAC-SHA512 с доменными разделителями). Когда кошелёк открывается, он запрашивает у ноды Kaspa UTXO по всем производным адресам:
// Псевдокод: обнаружение UTXO
addresses = [derive(seed, "wallet"), derive(seed, "walletOld"), ...]
utxos = node.getUtxosByAddresses(addresses)
balance = sum(utxo.amount for utxo in utxos)
UTXO-индекс ноды отвечает каждым непотраченным выходом на этих адресах. Для хранилищ с ковенантами каждый UTXO несёт дополнительные данные — хеш скрипта ковенанта — который определяет, *как* его можно потратить. Desk агрегирует UTXO с нескольких производных адресов и отображает единый баланс; при тратах построитель выбирает отдельные UTXO из этого набора.
Для мониторинга хранилищ сервис-наблюдатель (watcher) также отслеживает снимки UTXO, чтобы обнаруживать изменения и запускать оповещения: новые депозиты, инициированные выводы, завершённые переводы.
Шаг 2: Формирование транзакции в WASM
Здесь архитектура Kaspa Forge становится особенно интересной. Один и тот же Rust-крейт — kaspa-safe-core — компилируется как в WebAssembly (для браузера), так и в нативную библиотеку (для сервера). Логика построения транзакций написана один раз и проверена один раз.
Процесс сборки на стороне браузера проходит в несколько этапов:
Выбор UTXO. Кошелёк выбирает, какие UTXO потратить. Для простой отправки по P2PK он берёт минимальный набор, покрывающий сумму плюс комиссии. Для ковенантных операций выбор ограничен — пути хранилищ и эскроу навязывают инвариант одного входа:
require(tx.inputs.length == 1);
Каждый путь расходования ковенанта (initiate, cancel, complete, checkin, inherit, release, dispute и т.д.) потребляет ровно один UTXO на транзакцию. Причина — в безопасности: если UTXO ковенанта объединить с другими UTXO во входной транзакции с несколькими входами, стоимость из меньшего входа может утечь майнерам в виде избыточной комиссии — атака типа «выкачивание». Правило одного входа устраняет этот класс уязвимостей. Для обычных отправок из кошелька транзакции с несколькими входами допустимы — построитель агрегирует UTXO с производных адресов и прикрепляет по одной подписи на каждый вход.
Формирование выходов. Пbuilder рассчитывает:
- Выход назначения (адрес получателя + сумма)
- Выход сдачи (обратно отправителю, если применимо)
- Для ковенантов: feeBudget — максимальная сетевая комиссия, разрешённая скриптом в блокчейне, ограниченная 0,1 KAS. Это предотвращает сценарий, при котором наблюдатель или третья сторона транслирует ковенантную транзакцию без ключа с завышенной комиссией, обесценивая хранилище в пользу вознаграждений майнерам.
Встраивание скрипта. Для ковенантных транзакций построитель встраивает скомпилированный скрипт ковенанта в выход. Kaspa Forge использует Silverscript для определения правил расходования — исходный код хранилища (vault.sil) и эскроу (escrow.sil) компилируются на этапе сборки и включаются непосредственно в бинарный файл WASM с помощью include_str! Rust. Скрипты параметризованы: один и тот же шаблон порождает разные контракты в блокчейне в зависимости от горячего ключа, ключа тревоги, задержки, наследника и других параметров, выбранных при создании.
Сериализация — протокол txjson. Сформированная транзакция сериализуется в формат, совместимый с JSON, для передачи из браузера на сервер. Практическая ловушка: суммы Kaspa — это 64-битные целые числа (sompi), которые превышают безопасный диапазон целых чисел JavaScript (2^53 - 1). Протокол txjson кодирует все суммы как строки, чтобы предотвратить незаметную потерю точности. Любой построитель, который прогоняет суммы через JSON.parse без этой защиты, исказит значения.
Шаг 3: Подпись в браузере
Шаг подписания — это сердце некастодиальности. Приватный ключ существует только в памяти браузера — он выводится из зашифрованного профиля Desk, расшифровывается на мгновение паролем пользователя, используется для генерации подписи secp256k1, а затем удаляется.
Kaspa Forge навязывает шаблон UX под названием confirmPassword: когда вы инициируете вывод или подписываете транзакцию, кошелёк снова запрашивает ваш пароль и показывает контекст (сумму и получателя). Это предотвращает сценарий, при котором разблокированная сессия захватывается вредоносной вкладкой или расширением.
Для ковенантных путей, требующих нескольких подписей — как путь migrate хранилища, которому нужны и горячий ключ, и ключ тревоги, — браузер собирает обе подписи перед отправкой. Для пути mutual эскроу (покупатель + продавец согласны) каждая сторона подписывает независимо, и подписи объединяются.
Для путей без ключей — как complete() (вывод после истечения задержки) или autoRelease() (автоматическое освобождение эскроу после окончания окна спора) — подпись не требуется вообще. Любой может транслировать эти транзакции. В архитектуре Kaspa Forge сервис-наблюдатель отслеживает соответствующие условия и транслирует транзакции без ключей автоматически, но ковенант гарантирует, что средства всегда направляются по назначению, независимо от того, кто нажимает кнопку.
Шаг 4: Из браузера в ноду
Подписанная транзакция покидает браузер в виде HTTP POST на сервер Kaspa Forge. Сервер:
1. Проверяет транзакцию структурно — корректный формат, разумная комиссия, известные параметры ковенанта 2. Ретранслирует её нодe Kaspa через gRPC (submitTransaction) 3. Возвращает ID транзакции браузеру
Сервер никогда не хранит приватные ключи и никогда не изменяет транзакцию — он предоставляет транспортный уровень сети между браузером (который не умеет общаться по gRPC) и нодой (которая принимает gRPC или wRPC). Для ковенантных путей без ключей сервис-наблюдатель сервера формирует и отправляет транзакцию напрямую, без участия браузера.
Шаги 5–7: Мемпул, включение в блок и подтверждение
Как только нода принимает транзакцию, она попадает в мемпул — область подготовки неподтверждённых транзакций. Нода проверяет их на соответствие правилам консенсуса (корректные подписи, допустимые UTXO, достаточные комиссии, ограничения ковенантов) и, в случае успеха, транслирует хеш транзакции своим пиринговым узлам.
Согласно вики Kaspa, транзакция, отправленная через RPC (от кошелька или сервиса), никогда не истекает из мемпула — она периодически ретранслируется. Транзакции, ретранслированные от пира к пиру, истекают через 60 блоков, если не были добыты. Это важно для ковенантных путей без ключей: если транзакция complete() транслируется до истечения задержки, она ожидает в мемпуле до выполнения условия, после чего майнеры могут включить её.
Включение в блок подчиняется стандартной экономике майнинга. Когда мемпул содержит больше транзакций, чем помещается в один блок, майнеры сначала выбирают транзакции с наивысшими комиссиями. Майнеры Kaspa формируют блоки, которые ссылаются на несколько родительских блоков в DAG, а протокол GHOSTDAG определяет канонический порядок. Транзакция, включённая в один из таких блоков, становится частью DAG — но «подтверждённость» — это спектр.
Подтверждение и финальность в Kaspa измеряются в синей работе (blue work). Чем больше синих блоков (хорошо связанных блоков, как классифицирует GHOSTDAG) строятся поверх блока, содержащего вашу транзакцию, тем она становится надёжнее. При скорости 10 блоков в секунду включение происходит примерно за секунду. Но «достаточно подтверждённой» зависит от варианта использования:
- Небольшой платёж может «осесть» за пару секунд.
- Вывод из хранилища с ковенантом не зависит от накопления синей работы — он обеспечивает задержку, измеряемую DAA-оценкой (тысячи блоков, обычно часы или дни), прежде чем путь
complete()станет допустимым. Скрипт в блокчейне читаетageUTXO — разницу между текущей DAA-оценкой и оценкой на момент создания UTXO. - Окно спора по эскроу (24–168 часов по DAA-оценке) даёт обеим сторонам время на оспаривание до срабатывания автоматического освобождения.
Как Kaspa Forge использует этот конвейер
Каждый продукт на платформе проходит через одно и то же ядро WASM и серверный ретранслятор:
Kaspa Safe использует его для операций с хранилищем — 7 различных путей расходования, каждый со своим построителем транзакций, скомпилированным в ядро WASM. Путь initiate формирует ковенантный переход из режима VAULT в UNVAULTING; путь complete() без ключей транслируется наблюдателем после истечения задержки; путь migrate требует подписей и горячего ключа, и ключа тревоги для мгновенного, неограниченного выхода.
Kaspa Escrow использует его для расчётов по сделкам — 10 путей расходования, покрывающих освобождение, возврат, взаимное согласие, спор, арбитраж и тайм-аут. Ковенант гарантирует, что средства всегда могут поступить только покупателю, продавцу или адресу комиссии. ИИ-медиатор и человек-арбитр разрешают споры, но ни один из них не может перенаправить средства.
Кошелёк Desk использует его для обычных P2PK-отправок — агрегирует UTXO с HD-производных адресов, формирует стандартные транзакции и подписывает их производным ключом.
Все три продукта используют один и тот же Rust-крейт, один и тот же серверный ретранслятор, один и тот же зашифрованный профиль Desk и один и тот же формат резервной копии ключевых файлов .age. Скрипты ковенантов различаются (хранилище vs. эскроу), но конвейер формирования и подписания транзакций идентичен.
Посмотрите конвейер в действии. Создайте хранилище Kaspa Safe и наблюдайте, как транзакция проходит путь из вашего браузера в blockDAG — ключи генерируются на стороне клиента, правила соблюдаются в блокчейне. Операции в блокчейне бесплатны навсегда; вы платите только сетевую комиссию Kaspa (≈0,0001 KAS за UTXO).
Компромиссы и текущие ограничения
Вес WASM-сборки. Бинарный файл WASM kaspa-safe-core включает компилятор Silverscript, криптографию secp256k1 и все построители транзакций. Это увеличивает начальную загрузку страницы (кэшируется после первого посещения). Альтернатива — построение на стороне сервера — нарушила бы некастодиальность. Это осознанный компромисс.
Точность u64 в JavaScript. Суммы Kaspa в сомпи (sompi) превышают безопасный диапазон целых чисел JavaScript. Протокол txjson решает это с помощью строкового кодирования сумм, а арифметика выполняется внутри модуля WASM. Любая интеграция, которая прогоняет необработанные суммы через JSON.parse без строкового кодирования, незаметно исказит значения — реальная ловушка для каждого веб-кошелька Kaspa.
Один вход означает один депозит в хранилище на транзакцию. Инвариант безопасности, согласно которому каждый ковенантный путь потребляет ровно один UTXO, означает, что вы не можете объединить несколько депозитов в хранилище в одном выводе. Каждый депозит создаёт независимый UTXO, который должен быть потрачен в собственной транзакции. Безопасность важнее удобства.
Серверный ретранслятор — мягкая зависимость. Если сервер Kaspa Forge недоступен, обычный пользовательский интерфейс не сможет отправлять транзакции. Поскольку архитектура некастодиальна, вы всегда можете использовать инструмент командной строки с открытым исходным кодом (vaultctl) или отправить транзакцию напрямую любой ноде Kaspa. Сервер — это удобство, а не привратник.
Пороги подтверждения — вопрос суждения. При скорости 10 BPS транзакции попадают в DAG почти мгновенно, но «достаточно подтверждённой» зависит от суммы и контекста. Наблюдатель Kaspa Forge использует настраиваемые пороги по синей оценке (blue-score) для своих автоматических действий — не существует единого числа, подходящего для всех сценариев. Для ковенантных блокировок по времени DAA-оценка обеспечивает детерминированные часы, независимые от порогов синей оценки.
FAQ
Сколько времени занимает подтверждение транзакции Kaspa?
При скорости 10 блоков в секунду транзакция обычно появляется в DAG в течение одной секунды. «Достаточно подтверждённой» зависит от вашей модели угроз — для оплаты кофе нужны секунды, тогда как вывод из хранилища обеспечивает задержку, измеряемую тысячами блоков по показателю DAA-оценки.
Что такое UTXO в Kaspa?
UTXO (Unspent Transaction Output) — это отдельный «кусочек» монет KAS, привязанный к адресу, как купюра в вашем кошельке. Вы тратите целые UTXO и получаете сдачу в виде нового. Ваш баланс — это сумма всех ваших UTXO.
Почему Kaspa Forge использует WebAssembly вместо JavaScript?
Один и тот же Rust-крейт компилируется как в браузерный WASM, так и в нативные серверные бинарные файлы. Логика построения транзакций и проверки ковенантов написана один раз и используется в обеих средах — вторая реализация не требуется и не может рассинхронизироваться.
Можно ли отменить транзакцию Kaspa после её подтверждения?
Нет. Как только транзакция включена в blockDAG и над ней накоплено достаточное количество синей работы (blue work), она становится практически необратимой. Это фундаментальная гарантия proof-of-work.
Что произойдёт, если мой браузер вылетит во время подписания?
Если транзакция ещё не отправлена, ничего не произойдёт — средства не переместятся. Профиль Desk зашифрован локально; сбой не раскрывает ключи. Откройте страницу заново и попробуйте снова.
Как рассчитываются комиссии за транзакцию Kaspa?
Базовая комиссия составляет примерно 0,0001 KAS за каждый используемый UTXO. Ковенантные транзакции добавляют настраиваемый бюджет комиссии (feeBudget, 0,01–0,1 KAS), который ограничивает максимальную комиссию, разрешённую скриптом в блокчейне.
Держите KAS там, где кражу можно отменить
Ковенант-сейф в мейннете Kaspa: ваши ключи, ваши правила, наш инструмент. Ончейн — бесплатно, навсегда.
Создать сейф
