SegWit в Bitcoin: witness и идентификатор txid
Мы разобрали условие траты и данные подписи. SegWit разделяет часть данных транзакции и её свидетель — witness. Это разделение влияет на идентификаторы, оценку размера и способ подтверждения содержания. В уроке научимся различать txid, wtxid и байты подписи, не меняя основную модель UTXO.
Пример сохраняется: читатель расходует один выход на 80 000 сатоши, библиотеке создаётся выход 30 000, а сдача равна 49 300. Мы рассматриваем структуру, не создавая и не отправляя бинарную транзакцию.
Свидетель расходования
Witness содержит данные, используемые для удовлетворения соответствующего условия расходования SegWit. Они относятся к входу новой транзакции. Условия получения находятся в предыдущем выходе. Поэтому слово «свидетель» не означает отдельного человека, который подтверждает покупку библиотеке: это часть протокольного представления данных.
Для обычного P2WPKH-расходования в свидетель входят подпись и открытый ключ в установленной структуре. Для другого типа выхода состав иной. Нельзя определить универсальный список полей witness для всех видов, включая Taproot, по одному примеру с двумя элементами.
При создании нового выхода отправитель задаёт witness-программу в scriptPubKey. При последующем расходовании используются данные свидетеля и проверка по соответствующей версии. Разделение сохраняет знакомую логику: выход задаёт условие, вход предоставляет данные разрешения.
Два идентификатора
txid SegWit-транзакции вычисляется по предусмотренному представлению без witness-данных. wtxid относится к представлению с ними. Поэтому изменение свидетеля может затронуть wtxid, не изменив txid, если остальная сериализация сохраняется. Это различие важно для ссылок на выходы: обычный outpoint использует txid и индекс.
Схематично:
основные поля ──────────────→ txid
основные поля + свидетель ──→ wtxid
новый выход ────────────────→ txid:vout
Схема не содержит алгоритма сериализации и не заменяет его. Если взять JSON и удалить поле witness, затем хешировать строку, не получится автоматически корректный txid. Идентификаторы определяются бинарными правилами Bitcoin, а представление RPC является отдельным слоем.
Для библиотеки это позволяет хранить устойчивую идентичность собственного выхода через outpoint. Поле wtxid, если оно доступно и нужно диагностике, сохраняется отдельно. Нельзя использовать два значения как взаимозаменяемые ключи журнала. Иначе повторный ответ может создать дубликат оплаты или потерять связь расходования.
Что исправляет разделение
Исторические формы допускают особенности изменения транзакционных данных, которые могли влиять на идентификатор до подтверждения. Разделение witness уменьшает определённые проблемы изменяемости идентификатора для соответствующих расходов. Однако оно не запрещает владельцу входа подписать другую транзакцию и не создаёт гарантию включения первоначального кандидата.
Для сайта это различие принципиально. Слово «SegWit» на адресе не делает нулевые подтверждения окончательными. Возможность конкурирующего расходования и выбор цепочки по-прежнему требуют наблюдения. Наше правило принятия проверяет фактическое поступление, а не обещание неизменности любой подготовленной операции.
Не каждый вход смешанной транзакции обязательно имеет одинаковый тип. Если она использует и исторические, и SegWit-выходы, структура и риски должны рассматриваться по реальному набору. Упрощённая фраза «все подписи вынесены наружу» недостаточна для точного описания такого случая.
Обязательство блока
Блок должен связывать принятую историю с необходимыми данными свидетеля. Для этого SegWit предусматривает отдельное обязательство, размещаемое по установленным правилам. Обычная схема дерева транзакционных идентификаторов из предыдущего урока не рассказывает всю проверку witness сама по себе.
Полный узел проверяет соответствие обязательств и правила расходования. Сайт библиотеки обычно получает результат через свой узел и не реализует все проверки заново. Но разработчик должен понимать, почему один путь Меркла для txid не обязательно является автономным доказательством всех предоставленных witness-байтов.
Если приложение архивирует сырую транзакцию, полезно отмечать, какое представление сохранено. Для дальнейшего воспроизведения недостаточно набора красивых строк без структуры. В этом курсе мы сохраняем идею архива, но не утверждаем, что получили реальные witness-данные в запущенной сети.
Размер выражается весом
SegWit вводит вес, который по-разному учитывает базовые и witness-данные. Поэтому стоимость включения нельзя оценить, просто умножив полную длину файла на ставку, которую интерфейс показывает в сатоши за виртуальный байт. Следующий урок подробно рассчитает вес и округление.
В нашем денежном примере бюджет 700 остаётся выбранным числом. Если меняется тип входа, размер и требуемая комиссия могут измениться. Сумма входа 80 000 сама не сообщает размер расходования: для большого и малого платежа с одинаковой структурой число байтов может быть близким.
Разделим три описания: денежный план, транзакционные поля и ресурсный размер. В плане хранится 30 000 получателю; в структуре — конкретный скрипт и вход; в оценке — ожидаемые weight и vsize. Подписант проверяет согласованность этих описаний, а не полагается на одно число в интерфейсе.
Результат для журнала
Для библиотеки оставляем ключ платежного выхода network:txid:vout. Witness не становится номером заказа, а wtxid не заменяет цену. Если API возвращает оба идентификатора, адаптер именует их явно и не заполняет поле txid случайно выбранным хешем.
Ожидаемый разбор состоит в сопоставлении двух сериализаций одного содержания по спецификации. Самостоятельно вычислять их будем только при отдельном разрешённом запуске лаборатории. Сейчас результат — правильная модель полей и ограничения утверждений.
Типы полей в приложении
Внутренний объект может явно содержать transactionId и witnessTransactionId, а не два одинаково названных поля hash. Это уменьшает риск ошибочного объединения источников. При сохранении выхода достаточно устойчивого протокольного outpoint; при анализе архивированных байтов может понадобиться второй идентификатор. Если API не вернул его, адаптер не копирует txid в пустое поле только ради заполненной формы. Отсутствующий контекст отмечается отдельно. Такой приём полезен и вне Bitcoin: название данных должно сообщать, какое именно содержание идентифицируется, а не только формат печатной строки.
Правила описаны в BIP 141, а сообщение подписи для соответствующих расходов — в BIP 143. После урока слово SegWit означает для вас конкретное разделение данных, а не обещание мгновенного окончательного платежа.