Kaspa Forge
Разбор

Подтверждения платежей Kaspa: от события BlockDAG к бизнес-вебхуку

22 августа 2026 Автор — ИИ-команда OfficeForge · проверено командой 14 мин чтения
Подтверждения платежей Kaspa: от событий BlockDAG к вебхукам

Мерчант, принимающий KAS, сталкивается с проблемой, которую Bitcoin решил много лет назад, — и с ещё более сложной, которой у Bitcoin никогда не было. Транзакции Kaspa не содержат поля для метаданных, нет OP_RETURN, нет способа встроить ссылку на заказ прямо в перевод. В то же время BlockDAG Kaspa производит блоки каждые 100 мс, а значит, «подтверждение» не соответствует линейной цепочке блоков Bitcoin. Платёжная система для Kaspa должна решить две задачи одновременно: атрибуция (к какому счёту относится этот платёж?) и финальность (когда безопасно отгружать товар?).

В этой статье прослеживается полный путь KAS-платежа — от момента генерации уникального адреса до момента отправки подписанного вебхука с бизнес-событием — на примере реальной продакшен-системы. Решение достаточно универсально, чтобы его можно было применить к любой интеграции Kaspa-мерчанта.

Проблема атрибуции: один адрес на счёт

В Bitcoin мерчанты иногда переиспользуют один адрес и различают платежи по данным OP_RETURN или сумме. В Kaspa такого поля нет. Элегантное решение — HD-деривация (иерархически детерминированная): генерация уникального адреса для каждого счёта на основе одного расширенного публичного ключа.

Процесс:

1. Мерчант владеет xpub (расширенным публичным ключом). Соответствующий приватный сид хранится офлайн или в отдельной защищённой среде — платёжный сервер никогда его не видит. 2. Для каждого нового заказа сервер вызывает функцию деривации со следующим последовательным индексом:

address_0 = derive(xpub, index=0)   → kaspa:qz...
address_1 = derive(xpub, index=1)   → kaspa:qp...
address_2 = derive(xpub, index=2)   → kaspa:qr...

3. Индекс сохраняется вместе с заказом. Поскольку каждый индекс порождает уникальный адрес, любой UTXO, появляющийся на этом адресе, однозначно является оплатой за конкретный заказ.

Это то же семейство деривации, что используется в HD-кошельках Bitcoin (BIP-32/44), адаптированное под формат адресов Kaspa. Ключевое свойство: сервер может генерировать адреса, но не может тратить полученные средства, потому что никогда не владеет приватным ключом. Это некастодиально по конструкции.

Определение

xpub (расширенный публичный ключ): Публичный ключ, из которого детерминированно могут быть выведены дочерние публичные ключи и адреса. Для деривации не требуется соответствующий приватный ключ, поэтому платёжный сервер может генерировать неограниченное количество адресов для приёма платежей, не обладая правом на расходование средств.

Наблюдение за BlockDAG: опрос vs. подписка

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

  • Подписка через WebSocket на события транзакций — реактивный, с низкой задержкой, но хрупкий при переподключениях. Если соединение разрывается и транзакция поступает в этот промежуток, она может быть пропущена, если только у наблюдателя нет механизма восстановления.
  • Опрос getUtxosByAddresses — наблюдатель запрашивает у узла текущие UTXO для набора адресов с регулярным интервалом (каждые несколько секунд). Это безданный и идемпотентный подход: даже если один опрос пропущен, следующий вернёт полную актуальную картину.

В продакшен-решении используется опрос. Наблюдатель ведёт список активных адресов («список наблюдения»), каждый из которых привязан к ID заказа, ожидаемой сумме и времени истечения. В каждом цикле он запрашивает у узла utxoindex — индекс всех непотраченных выходов транзакций, сгруппированных по адресам, который поддерживается узлом Kaspa. utxoindex должен быть включён на узле; во всех конфигурациях он включён по умолчанию не всегда.

# Псевдокод: цикл наблюдателя
for entry in watchlist:
    utxos = node.getUtxosByAddresses([entry.address])
    received = sum(utxo.amount for utxo in utxos)
    confirmations = current_blue_score - utxo.block_blue_score
    if received >= entry.expected and confirmations >= THRESHOLD:
        fire_callback(entry)

Компромисс здесь — задержка: опрос каждые N секунд означает, что обнаружение отстаёт от реального события BlockDAG максимум на N секунд. Для системы, обрабатывающей счета с 20-минутными окнами, это приемлемо. Для биржи в реальном времени больше подошёл бы гибридный подход (подписка плюс периодическая сверка).

Что означает «подтверждение» в BlockDAG

Здесь Kaspa принципиально отличается от Bitcoin.

В Bitcoin транзакция считается подтверждённой, когда она попадает в блок, и каждый последующий блок добавляет одно подтверждение. Цепочка линейна; глубина однозначна.

В протоколе GHOSTDAG Kaspa блоки образуют направленный ациклический граф (DAG), а не единую цепочку. Каждый блок имеет выбранный родительский блок (выбранный алгоритмом GHOSTDAG), и последовательность выбранных родителей формирует «выбранную цепочку». Но параллельно существуют множество других блоков — это блоки слияния, которые выбранная цепочка в конечном счёте поглощает.

Вики Kaspa определяет две ключевые метрики:

  • Blue score: количество *синих* (хорошо связанных) блоков в прошлом данного блока. Блок считается «синим», если он хорошо интегрирован в DAG — он вносит вклад в безопасность консенсуса. Blue score — это аналог высоты блока в Bitcoin, но нативный для DAG.
  • DAA score: blue score плюс количество красных (плохо связанных) блоков, которые были успешно объединены и вознаграждены. Эта метрика управляет графиком эмиссии.

Для подтверждения платежей Kaspa актуальной метрикой является blue score. Когда UTXO транзакции появляется в блоке с blue score B, а текущий виртуальный (концевой) blue score равен V, количество подтверждений равно V - B. Система ждёт, пока эта разница не достигнет настраиваемого порога, и только тогда считает платёж финальным.

Почему blue score, а не общее количество блоков? Потому что синие блоки — это те, которые алгоритм GHOSTDAG считает хорошо связанными и надёжными. Красные блоки — те, которые опоздали или плохо разошлись по сети, — объединяются, но несут меньший вес консенсуса. Подсчёт только синих блоков для подтверждений даёт более точную меру того, на глубоко транзакция погружена в консенсусную структуру DAG.

При текущей скорости Kaspa в 10 блоков в секунду даже скромный порог в 10–30 подтверждений по blue-score проходит за 1–3 секунды. Это на порядки быстрее, чем блоки Bitcoin примерно раз в 10 минут, но порог всё равно должен быть ненулевым, чтобы защититься от небольших реорганизаций DAG, которые GHOSTDAG допускает.

Определение

Реорганизация DAG: В отличие от редких реорганизаций цепочки в Bitcoin, BlockDAG Kaspa испытывает частые небольшие реорганизации, когда выбранная концевая вершина меняется. GHOSTDAG гарантирует, что они неглубокие и быстро стабилизируются, поэтому небольшого порога подтверждений по blue-score достаточно для финальности платежа.

Вебхук: от обнаружения к бизнес-событию

Как только наблюдатель определяет, что подтверждение платежа Kaspa достигнуто, он должен уведомить бизнес-уровень. Это и есть вебхук KAS-платежа — HTTP-обратный вызов с деталями платежа.

Полезная нагрузка вебхука включает:

{
  "order_id": "ord_abc123",
  "address": "kaspa:qz...",
  "txid": "7342e267...",
  "received_sompi": 199000000000,
  "daa_score": 12345678
}

Три проектных решения обеспечивают надёжность:

1. HMAC-подпись. Вебхук содержит криптографическую подпись (HMAC-SHA256) над полезной нагрузкой, используя общий секрет, известный только наблюдателю и бизнес-серверу. Получатель проверяет подпись перед обработкой. Это предотвращает подделку обратных вызовов для ложного выполнения заказов.

2. Идемпотентность по ID заказа. Конечная точка обратного вызова спроектирована так, что повторное получение одного и того же order_id даёт тот же результат — второй вызов возвращает ответ dedup: true и не выпускает вторую лицензию и не отправляет второе письмо. Это важно, потому что при развёртывании в два экземпляра (см. ниже) оба наблюдателя могут независимо обнаружить один и тот же платёж.

3. Идентификация через User-Agent. Практический урок: некоторые обратные прокси и CDN блокируют запросы со стандартными строками User-Agent из библиотек. Отправитель вебхука устанавливает собственный заголовок User-Agent, чтобы избежать молчаливых отказов 403 на сетевом уровне.

Отказоустойчивость с двумя экземплярами

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

Решение — активно-активная пара экземпляров с разделёнными индексами деривации:

Экземпляр A: генерирует адреса с нечётными индексами (1, 3, 5, 7, ...)
Экземпляр B: генерирует адреса с чётными индексами (0, 2, 4, 6, ...)

Оба экземпляра используют один и тот же xpub, но с шагом и смещением, гарантирующим, что они никогда не создадут одинаковый адрес. Оба регистрируют свои адреса в списке наблюдения бизнес-уровня. Если один экземпляр выходит из строя, другой продолжает обрабатывать свои адреса без перебоев.

Конечная точка вебхука на бизнес-уровне идемпотентна по ID заказа, поэтому если оба экземпляра независимо обнаружат и сообщат об одном и том же граничном платеже, дубликат будет безвредно поглощён.

Этот паттерн — разделённые индексы, активно-активные наблюдатели, идемпотентные обратные вызовы — превращает хрупкую одиночную конфигурацию в отказоустойчивый платёжный канал без необходимости выбора лидера или общего состояния между экземплярами.

Частичные платежи и переплаты

Транзакции Kaspa не содержат поля «сумма счёта». Клиент видит адрес и ожидаемую сумму, но ничто не обязывает его отправить именно эту сумму. Система должна обрабатывать три случая:

  • Точный платёж: получено ≥ ожидаемого (с небольшим допуском на округление) → подтвердить и выполнить заказ.
  • Недоплата: получено < ожидаемого → сообщить о недостаче. Клиент может отправить вторую транзакцию на тот же адрес. Наблюдатель суммирует все UTXO на адресе, поэтому много-транзакционные платежи работают естественным образом.
  • Переплата: получено > ожидаемого → выполнить заказ. Излишек не возвращается автоматически (транзакции Kaspa необратимы; возвраты требуют ручного вмешательства).

Порог допуска учитывает незначительные расхождения в округлении между отображаемой суммой в KAS и фактическими сомпи (наименьшая единица), которые отправляет кошелёк клиента.

Как Kaspa Forge использует эту схему

Инфраструктура подтверждения платежей, описанная выше, обеспечивает собственный конвейер продаж Kaspa Forge — приём KAS за продукты наряду с традиционными платёжными каналами. Архитектура следует той же философии самостоятельного хранения, которая пронизывает каждый продукт Kaspa Forge:

  • Kaspa Safe использует ковенант-контракты on-chain, где ключи пользователя никогда не покидают его устройство.
  • Kaspa Escrow блокирует средства в on-chain-контракте, а не у кастодиального посредника.
  • Deposit применяет ту же схему залога на основе ковенантов.
  • Desk хранит все ключи в зашифрованном профиле браузера; сервер никогда их не видит.

Платёжная система расширяет этот принцип на мерчант-уровень: сервер хранит только xpub, генерирует адреса, наблюдает за BlockDAG и отправляет вебхуки. Ни на каком этапе он не контролирует полученные средства. Если платёжный сервер исчезнет, средства остаются доступными тому, кто владеет сидом. Та же двухсервисная архитектура — тонкий бизнес-сервер и крипто-ориентированный шлюз — изолирует компилируемое Rust-колесо и весь криптографический материал от общего стека приложения.

Та же некастодиальная архитектура с собственным узлом, которая обеспечивает подтверждение платежей Kaspa, лежит в основе каждого продукта Kaspa Forge — от хранилищ на ковенантах Safe до P2P-сделок Escrow. Изучите полную архитектуру, чтобы увидеть, как on-chain-контракты заменяют кастодиальное доверие на каждом уровне.

Создать сейф

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

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

Задержка опроса. Наблюдатель опрашивает каждые несколько секунд, а не на каждый блок. Обнаружение отстаёт от BlockDAG на величину до интервала опроса. Для счетов с 20-минутными окнами это нормально. Для высокочастотной торговли или мгновенной розничной оплаты — нет.

Отсутствие push от узла. wRPC-интерфейс узла Kaspa поддерживает подписки, но продакшен-система их избегает, потому что обработка переподключений добавляет сложность и риск пропуска событий при обрыве сокета. Опрос проще и самовосстанавливается, ценой задержки.

Ручные возвраты. Транзакции Kaspa необратимы. Если клиент переплатил или оплатил просроченный счёт, система помечает это для ручного решения. Механизма возврата на уровне блокчейна нет.

Волатильность курса. Курс KAS/USD фиксируется при создании заказа с буфером в 2%. Если цена Kaspa изменится более чем на 2% в окне подтверждения, мерчант поглощает разницу. Это осознанный компромисс: больший буфер привёл бы к переплате клиентов; меньший — подверг бы мерчанта риску.

Карантин адресов после истечения. Адрес просроченного счёта помещается в карантин и никогда не используется повторно. Это предотвращает путаницу, если опоздавший платёж поступит на адрес, который был переназначен новому заказу. Опоздавшие платежи по-прежнему обнаруживаются и помечаются для ручной обработки.

Зависимость от utxoindex. Весь наблюдатель зависит от того, что utxoindex на узле включён и полностью синхронизирован. Во время начальной загрузки блоков (IBD) индекс недоступен, поэтому платёжная система не может запуститься, пока узел полностью не догонит сеть.

Итог: полный жизненный цикл

Клиент нажимает «Оплатить KAS»
  → Сервер генерирует уникальный адрес из xpub (следующий индекс)
  → Фиксирует курс KAS/USD, устанавливает 20-минутное окно
  → Возвращает адрес + сумму + QR-код (kaspa: URI)
  → Клиент отправляет KAS из своего кошелька

Наблюдатель опрашивает getUtxosByAddresses каждые N секунд
  → Обнаруживает UTXO на адресе счёта
  → Суммирует полученные средства по всем UTXO
  → Проверяет порог подтверждений по blue-score
  → Если получено ≥ ожидаемого И подтверждений ≥ порога:
      → Отправляет HMAC-подписанный POST-вебхук на бизнес-сервер
      → Бизнес-сервер проверяет подпись
      → Выпускает лицензию / выполняет заказ (идемпотентно по order_id)

Весь процесс — от HD-деривации адресов через наблюдение за BlockDAG до идемпотентного вебхука — представляет собой универсальную схему приёма платежей Kaspa без кастодиальных рисков. Высокая скорость блоков BlockDAG делает подтверждения быстрыми; метрика blue-score в GHOSTDAG делает их осмысленными; а паттерн HD-деривации решает атрибуцию без каких-либо метаданных в самой транзакции. Для мерчант-платежей Kaspa это продакшен-основа: никаких сторонних процессоров, никаких кастодиальных рисков, никаких хаков на уровне протокола — только узел, наблюдатель и подписанный обратный вызов.

FAQ

Сколько подтверждений нужно для платежа в Kaspa?

Порог настраивается для каждого развёртывания. При скорости Kaspa в 10 блоков в секунду даже 10–30 подтверждений по blue-score проходят за 1–3 секунды. Точное число зависит от вашей толерантности к риску.

Что такое blue score и почему он важен для платежей?

Blue score — это количество синих (хорошо связанных) блоков в прошлом данного блока в структуре GHOSTDAG. Он заменяет линейную высоту блока из Bitcoin в качестве метрики подтверждения в BlockDAG Kaspa.

Что произойдёт, если клиент отправит сумму меньше, чем указано в счёте?

Система обнаружит частичный платеж, сообщит о недостаче и дождётся доплаты на тот же адрес. Наблюдатель суммирует все UTXO на адресе, поэтому много-транзакционные платежи работают естественным образом.

Поддерживает ли Kaspa метаданные платежей или OP_RETURN?

Нет. Транзакции Kaspa не содержат поля для метаданных. Стандартный подход — генерировать уникальный адрес для каждого счёта на основе расширенного публичного ключа (xpub), чтобы любой платёж на этот адрес однозначно привязывался к заказу.

Могу ли я создать аналогичный вебхук подтверждений для своего проекта?

Да. Описанная схема — деривация из xpub, опрос UTXO через utxoindex, порог blue-score, HMAC-подписанный обратный вызов — является универсальным решением. Вам понадобится узел Kaspa с включённым utxoindex и небольшой сервис-наблюдатель.

Является ли платёжная система кастодиальной?

Нет. Сервер хранит только расширенный публичный ключ (xpub). Приватный сид ни покидает защищённую среду оператора. Сервер генерирует адреса, но не может потратить полученные средства.

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

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

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

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

Создать сейф