Watch-only кошелёк Bitcoin и отдельный подписант
Библиотеке требуется автоматически обнаруживать оплату, но не обязательно автоматически расходовать выручку из веб-процесса. Watch-only-модель разделяет эти возможности. В уроке построим маршрут, где сервер знает публичные условия получения, а независимый подписант разрешает подготовленное действие после собственной проверки.
Предпосылка — дескрипторы получения и сдачи из предыдущего урока. Мы не импортируем ключи и не создаём PSBT в узле; описываем интерфейсы и ожидаемые ограничения для локального проекта.
Что умеет наблюдатель
Наблюдающий кошелёк знает условия, которые позволяют распознать собственные выходы. Он может получать сведения о транзакциях, показывать историю и участвовать в подготовке неподписанного расходования. При отсутствии приватных ключей он не должен самостоятельно выдавать требуемые подписи.
В библиотеке наблюдатель нужен для связи адресов со счетами. Он знает, что выход на конкретный скрипт относится к нашему набору. Приложение затем связывает этот выход со счётом library-17-001 и суммирует поступления. Никакой этап не требует передачи секрета читателю.
Поле баланса наблюдателя не означает доступность расходования веб-сервером. Поэтому интерфейс администратора должен отличать наблюдаемые средства от готовности подписанта. Иначе оператор может принять отсутствие подписи за повреждение кошелька или пытаться «восстановить» ключи в небезопасном месте.
Где проходит граница
Выделим четыре сообщения:
сайт → наблюдатель: получить состояние назначений
наблюдатель → подготовитель: выбранные выходы и политика
подготовитель → подписант: пакет и заявка
подписант → отправитель: разрешённый завершённый результат
Подписант может быть аппаратным устройством, отдельной системой или совместной процедурой сотрудников. Важно не название, а то, какие данные он видит и какие ограничения проверяет. Если он автоматически подписывает произвольный пакет от веб-сервера, реальная граница полномочий существенно сужается.
Для возврата читателю сохраняем независимую заявку: получатель, сумма и основание согласования. Подготовленный пакет сравнивается с ней. Дескрипторы помогают подписанту распознать сдачу; внешний адрес получателя требует отдельной проверки. Выход, подписанный меткой change злоумышленником, не становится собственной сдачей.
Модель компрометации
Предположим, атакующий получил доступ к процессу сайта. Он может изменять отображаемые адреса, читать счета, мешать наблюдению или готовить вредоносные заявки. Если приватные ключи отделены, прямое расходование известной выручки не следует автоматически из этого доступа. Но риск подмены нового назначения остаётся.
Поэтому разделение ключей не отменяет защиты страницы оплаты. Сервер должен выдавать адреса из согласованного набора, сохранять связь счёта до ответа и контролировать изменения конфигурации. При обнаружении компрометации нельзя ограничиться заявлением «ключи в другом месте, значит проблем нет».
Атакующий может также раскрыть публичный дескриптор и связать историю. Это серьёзное нарушение приватности без кражи средств. Доступ к наблюдающей конфигурации даём только компонентам, которым она нужна. Учебный репозиторий содержит схему и явно искусственные данные, а не материал реальной библиотеки.
Полный набор наблюдения
Watch-only-набор должен включать необходимые ветви и исторические условия. Если сервер наблюдает получение, но не сдачу, собственный расход создаст выход, который не попадёт в ожидаемый баланс. Если отсутствует часть прежних типов адресов, восстановление даст неполную историю.
Диапазон индексов также является частью полноты. Новые счета не должны опережать подготовленный диапазон без его расширения. Журнал выдачи адресов позволяет понять, какие назначения уже показаны пользователям. Он особенно важен при поздних переводах на ранее выданные адреса.
Узкий публичный экспорт полезен для ограничения наблюдения. Если веб-сервис работает только с аккаунтом учебных продаж, ему не требуется весь публичный корень личного кошелька оператора. Организационные границы следует выразить в конфигурации, а не только в устной договорённости.
Неизвестность и отказы
Подписант может быть недоступен, пользователь может отказаться, а пакет может оказаться недостаточно полным. Это отдельные состояния исходящего маршрута. Они не означают, что библиотека не получила входящие средства. Платёжный журнал и очередь расходования имеют разные причины задержки.
Внутренний интерфейс полезно строить вокруг состояний prepared, awaiting_review, signed, broadcast_unknown и observed. Последние два отличаются: тайм-аут отправки не доказывает, что результат не попал в сеть. До повторного расходования требуется сверка конкретного объекта и выбранных входов.
Наблюдатель может дополнительно получать сведения о доступности подписанта, но не хранит секрет ради устранения неудобства. Временный отказ часто подталкивает к обходу архитектуры; досье должно заранее объяснять допустимый аварийный маршрут и ответственных участников.
Восстановление двух сторон
Для наблюдения нужны публичная политика, диапазон и доступ к истории. Для подписи нужны соответствующие секреты или действующий подписант. Для привязки к заказам нужна база приложения. Эти три восстановления независимы. Успешное восстановление только одного слоя не доказывает готовность всей библиотеки.
Ожидаемый учебный результат: наблюдающий компонент показывает собственное поступление, но не способен завершить подпись без внешнего участника. Мы пока не демонстрировали этот эффект исполнением. Его нужно проверить позже в изолированной сети на собственных данных, включая попытку расходования без подписанта.
Разбор ограничений без обхода
Если наблюдатель возвращает пакет без части контекста, подписант может отказать с понятной причиной. Это не является сбоем, который следует исправить экспортом секрета на сервер. Подготовитель дополняет необходимые публичные данные по поддерживаемому формату либо выбирает другой совместимый маршрут. Причина отказа сохраняется рядом с версией пакета. Новый пакет заново сравнивается с заявкой, поскольку изменение подготовки могло затронуть входы и расход.
Для обычной входящей оплаты такой отказ вообще не должен закрывать доступ к наблюдению. Библиотека продолжает принимать сведения о получении, а очередь возвратов показывает отдельное ожидание. Разделение статусов помогает поддержке объяснить, почему баланс известен, но исходящая операция ещё не разрешена. Это конкретное проявление архитектурной границы, а не недостаток кошелька.
Роль подписанта фиксируется независимо от наличия административного доступа к сайту. Администратор интерфейса не становится владельцем секрета по одному изменению прикладной роли.
Параметры такого кошелька описаны в createwallet и документе PSBT. После урока граница сформулирована точно: публичное наблюдение помогает найти деньги, независимое согласование разрешает конкретное расходование, а прикладная база объясняет его назначение.