Перейти к содержанию

Подтверждения и реорганизация блокчейна Bitcoin

Библиотека обнаружила перевод на 30 000 сатоши в блоке. Для страницы оплаты это важный переход, однако одно включение не означает невозможность пересмотра истории. Рассмотрим число подтверждений как производное выбранной цепочки, а не необратимый счётчик в базе приложения.

В примере платеж находится в блоке A102 на высоте 102. Наш узел выбрал вершину A104 на высоте 104. Все обозначения относятся к модели; узел не запускается и реорганизация не создаётся учебными командами.

От включения к глубине

Если блок платежа принадлежит выбранной цепочке, типовой расчёт подтверждений выглядит как tipHeight - paymentHeight + 1. Для высот 104 и 102 получаем три. Единица учитывает сам блок включения: в момент появления в вершине транзакция уже имеет одно подтверждение.

Однако арифметику можно применять только после проверки принадлежности истории. Если транзакция записана в другой ветви на высоте 102, та же разность высот не даёт ей три подтверждения в выбранной цепочке. Именно поэтому одного paymentHeight в журнале недостаточно.

Полезно сохранять хеш блока включения и сверять его связь с актуальной ветвью. Ответ кошелька Core уже интерпретирует многие состояния относительно собственного узла, но приложение должно знать, какой кошелёк и сеть являются источником. Смешение ответов двух источников без согласования высот и хешей может создать искусственное противоречие.

Две ветви на одной высоте

Рассмотрим последовательность:

A101 → A102(платёж) → A103 → A104
    ↘ B102          → B103 → B104 → B105

Если новая допустимая ветвь выбирается узлом по правилам накопленной работы, блок A102 перестаёт быть частью выбранной истории. Это событие называют реорганизацией. Платёж может вернуться в очередь, появиться в новой ветви или конфликтовать с другим расходованием своего входа. Нельзя заранее выбрать единственный исход только по факту отключения блока.

Сценарий первый: PAYMENT_A включают в B105. Сумма и выход сохраняются, меняется принадлежность блоку и глубина. Сценарий второй: в новой ветви расходуется тот же вход другой транзакцией, которая не создаёт выход библиотеке. Теперь исходный платёж не обеспечивает получение по выбранной истории. Сценарий третий: транзакция пока не включена, но снова видна в mempool.

Во всех вариантах журнал сохраняет историческое наблюдение, а текущее состояние рассчитывает отдельно. Мы не стираем прошлый факт «узел сообщал A102», потому что он нужен для объяснения принятого решения и анализа сбоя. Но не продолжаем выдавать старое число подтверждений как актуальное.

Политика библиотеки

Порог принятия — решение приложения. Для учебной модели можно выбрать два подтверждения. Это не универсальная рекомендация для любых сумм и условий, а удобное правило, позволяющее увидеть ожидание и переход к выдаче. Реальная политика требует оценки риска, характера услуги и операционных возможностей.

Запишем решение:

{
  "invoiceId": "library-17-001",
  "policyVersion": "lab-confirmations-v1",
  "requiredConfirmations": 2,
  "observedConfirmations": 3,
  "decision": "accepted"
}

Число 3 соответствует нашему условному наблюдению вершины 104. Если источник перестал отвечать, значение не увеличивается с течением настенных минут. Блоки могут появляться с разным интервалом. Для интерфейса сохраняется время последней сверки, чтобы читатель видел свежесть.

Если подтверждённая оплата уже открыла материалы, а позже произошла реорганизация, возникает прикладной вопрос. Загруженный файл нельзя отозвать физически. Можно изменить будущее право доступа, приостановить новые загрузки или отправить запись на разбор по заранее описанной политике. Сайт должен разделять денежное наблюдение и действие выдачи, чтобы не делать повторную выдачу при возврате к подтверждённому состоянию.

Конфликт отличается от отсутствия

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

Внутренняя модель может иметь состояния unconfirmed, confirmed, conflicted и unknown. Последнее нужно для ошибки получения или отсутствия достаточных сведений. Если обработать сетевой тайм-аут как unconfirmed, приложение перепишет действительную историю ложным отрицательным наблюдением.

Для каждого перехода полезна причина: новый блок, откат общей точки, конфликт, обновление кошелька или ошибка источника. Это упрощает эксплуатацию и делает правило воспроизводимым по журналу. Одно поле paid=true не может выразить эти события.

Ожидаемый разбор

Проверка будущей реализации должна начать с платежа в A102, вершины A104 и принятого решения. Затем источник сообщает другую цепочку. Наблюдатель находит общую точку A101, отключает наблюдения старой ветви, применяет новую и пересчитывает счёт. Уже выполненная выдача остаётся одной записью с собственным идентификатором.

Если в новой ветви платеж вновь достигает порога, не создаём ещё один доступ. Меняется основание актуального решения, а не идентичность заказа. Этот принцип пригодится в платёжном курсе при transactional outbox и идемпотентном журналировании.

Время принятого решения

Пусть доступ выдан при вершине A104, а реорганизация обнаружена через минуту. Запись решения содержит вершину, версию правила и время действия. Это позволяет объяснить, что сервис использовал доступное тогда наблюдение, а не задним числом приписал себе знание будущей ветви. Новое решение сохраняется как переход, связанный с прежним счётом. Если политика допускает ручной разбор, система фиксирует причину и ответственного, не переписывая сетевое наблюдение ради удобства.

Другая ошибка — увеличивать подтверждения по таймеру страницы. Пока браузер открыт, число блоков не обязано расти, а при потере соединения оно может стать неизвестным. Клиент получает уже рассчитанное сервером значение со свежестью и идентификатором наблюдения. Таймер может обновлять надпись «сверка была столько-то назад», но не сетевую глубину. Для читателя это различие важнее ложной плавной анимации прогресса.

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

Значения подтверждений и конфликтов описаны в gettransaction. Сетевой выбор истории рассматривается в руководстве Bitcoin. Итог урока — подтверждения, рассчитанные из конкретного актуального наблюдения, и отдельная версия решения библиотеки.

Оглавление серии