Как происходит расшифровка P2PKH адресации в транзакции Биткоина

14.02.2024

В этой статье мы рассмотрим один из популярных методов адресации в Bitcoin-сети, который начал свое существование еще в 2011 году. P2PKH (Pay To PubKey Hash) – это один из самых распространенных методов адресации в Bitcoin. Он используется для отправки биткоинов на обычный адрес (начинается с букв 1 или 3).

Вот почему пользователи Биткоина не отказываются от транзакций (P2PKH)

Цель этой статьи — дать подробное представление о наиболее распространенном типе биткойн-транзакций — хэше с оплатой по публичному ключу (P2PKH). Для этого предлагается следующее:

  • Краткий обзор концепции неизрасходованного вывода транзакции (UTXO) и того, как формируется транзакция.
  • Разбивка каждой части транзакции P2PKH
  • Обзор того, как работают скрипты разблокировки и блокировки в сочетании с тратой средств.

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

Неизрасходованные выходы транзакций (UTXO)

Очень важная концепция, которую следует понять, прежде чем углубляться в разбивку транзакций, — это неизрасходованный вывод транзакции или UTXO. В транзакции Биткойн UTXO — это то, что потребляется или тратится. UTXO можно потратить только один раз. После того, как они потрачены, они называются потраченными выходными транзакциями .

Трата UTXO аналогична использованию 20-долларовой купюры для покупки чего-либо за 10 долларов, но вместо того, чтобы кассир хранил 20-долларовую купюру, он поджигает ее и создает из воздуха две новые 10-долларовые купюры, оставляя одну и возвращая вам другую. изменять.

В этой аналогии сожженная 20-долларовая купюра начиналась как UTXO, но как только она была израсходована, она превратилась в результат потраченной транзакции, что привело к появлению двух новых 10-долларовых купюр, представляющих собой два новых UTXO, готовых к использованию в будущих транзакциях.

Все биткойны, доступные для потребления в сети, называются набором UTXO .

Процесс построения транзакции

Каждая транзакция состоит из номера версии , ввода , вывода и времени блокировки .

Входные данные содержат конечные точки , порядковый номер и сценарий разблокировки , также называемый scriptSig .

Вывод содержит значение потраченной суммы и скрипт блокировки , также называемый scriptPubKey .

Время блокировки определяет, в какое время транзакция становится действительной.

Каждая транзакция имеет как минимум один вход и один выход. Входные данные содержат логику, которая сообщает сети, какие UTXO использовать (через выходные точки), и доказывает, что ей разрешено их использовать (через сценарии разблокировки). Вывод содержит логику, которая сообщает сети условия, при которых будущей транзакции разрешено использовать вновь созданные UTXO (через сценарий блокировки).

На рисунке ниже показано взаимосвязь между подтвержденной транзакцией с израсходованными выходами, подтвержденными транзакциями с неизрасходованными выходами и новыми, неотправленными транзакциями.

Как происходит расшифровка P2PKH адресации в транзакции Биткоина
Транзакционные отношения

Шаги по созданию транзакции

Шаги для создания транзакции P2PKH следующие:

  1. Определите предыдущую транзакцию, содержащую UTXO, которые вы контролируете (только биткойн, который у вас уже есть).
  2. Создайте исходные точки входа новой транзакции, чтобы определить UTXO предыдущей транзакции, который нужно потратить.
  3. Создайте выходные данные новой транзакции так, чтобы сценарий блокировки содержал условия, при которых вновь созданные UTXO могут быть потрачены/разблокированы следующей транзакцией.
  4. Создайте сценарий разблокировки, чтобы он соответствовал условиям, заданным сценарием блокировки вывода предыдущей транзакции. Он содержит подпись получателя и создается на самом последнем этапе, но во многом является частью ввода и физически размещается в середине транзакции.

Введение в сериализованную транзакцию

Полная подписанная биткойн-транзакция P2PKH подробно обсуждается ниже.

Эта транзакция была случайно выбрана на Blockchain.com, и ее можно просмотреть здесь ( необработанные значения ).

С UTXO со значением 17 373 066 адрес 19iy8HKpG5EbsqB2GUNVPUDbQxiTrPXpsx отправляет 390 582 сатоши на адрес 1JKRgG4F7k1b7PbAhQ7heEuV5aTJDpK9TS и получает обратно 16 932 484 сатоши в качестве сдачи. Оставшаяся разница между входами и выходами поступает майнеру в качестве комиссии за обработку транзакции.

Номер версии


Номер версии имеет длину четыре байта и выражается в виде шестнадцатеричного значения в формате с прямым порядком байтов.

Существует два типа версий. Версия 01 указывает на отсутствие относительной блокировки по времени. Версия 02 указывает на то, что может быть относительная блокировка по времени. Версия 02 была представлена ​​в BIP0068 , в который был добавлен OP_CHECKSEQUENCEVERIFY вместе с BIP0112 , который обновил ее. Версия 02 используется вместе с порядковым номером, который описан ниже.

Пример транзакции — версия 01.

Ввод транзакции

Каждый вход транзакции указывает на выход предыдущей транзакции. Если сценарий разблокировки во входной текущей транзакции соответствует условиям, установленным выходным сценарием предыдущей транзакции, то UTXO, который «удерживает» предыдущая транзакция, может быть потрачен.

Количество минусов

Следующие от одного до девяти байты во входных данных транзакции определяют количество включенных минусов и имеют тип VarInt. Для каждого потребляемого UTXO всегда есть один минус.

Пример транзакции с входом 1 UTXO.

Транзакция

Каждый минус — это ссылка на хеш предыдущей транзакции и соответствующий индекс, указывающий на точный расходуемый UTXO.

Первые 32 байта минусовой точки — это ссылка на хэш предыдущей транзакции, содержащий UTXO, используемый в формате с прямым порядком байтов. Например, хэш предыдущей транзакции:

и когда он включен в исходную точку транзакции, он выражается в формате с прямым порядком байтов (обратный порядок байтов):

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

Транзакцию, содержащую тратимые UTXO, можно просмотреть здесь необработанные значения ). Первая запись в ключе «out» предыдущей транзакции показывает, что в текущей транзакции используется UTXO, содержащий десятичное значение 17 373 066 сатоши. Обратите внимание, что текущая транзакция явно не включает UTXO на сумму 17 373 066 сатоши, а только ссылку на него через содержимое выходной точки.

Скрипт разблокировки

Сценарий разблокировки, также называемый scriptSig, содержит сценарий стека (подпись) и сценарий погашения (публичный ключ) пользователя, осуществляющего транзакцию и получающего средства.


Разблокировка длины скрипта

Первые 1–9 байтов имеют тип VarInt и определяют количество последующих байтов, составляющих сценарий стека и сценарий погашения. В этом случае первый байт (0x6a) объявляет, что следующие 106 байтов помещаются в стек (обсуждается ниже).

Скрипт стека (подпись)

Stack Script Signature Скрипт Стека Подписи

Скрипт стека содержит подпись человека, отправляющего транзакцию в сеть, и sighash. Это часть доказательства, подтверждающего, что пользователю (подписавшему) разрешено тратить UTXO, на которые указывает выходная точка транзакции.

Первые 1–9 байтов имеют тип VarInt и определяют количество последующих байтов, составляющих подпись.

В этом случае первый байт (0x47) объявляет, что следующие 71 байт — это подпись и sighashПодпись создается на основе закрытого ключа пользователя.

Подпись можно разбить следующим образом:

  • 30 Маркер подписи DER
  • 44 — заявляет, что длина подписи составляет 68 байт.
  • 02 – маркер значения R
  • 20 — объявить, что значение R имеет длину 32 байта
  • 3da9d487be5302a6d69e02a861acff1da472885e43d7528ed9b1b537a8e2cac9 — значение R
  • 02 – маркер значения S
  • 20 — объявить значение S длиной 32 байта
  • 02d1bca03a1e9715a99971bafe3b1852b7a4f0168281cbd27a220380a01b3307 – значение S

Наконец, к подписи добавляется один байт, представляющий sighash. В транзакции P2PKH и sighash может быть одним из следующих:

  • SIGHASH_ALL (0x01): подпись применяется ко всем входам и выходам, это наиболее распространено для транзакций P2PKH.
  • SIGHASH_SINGLE (0x03): подпись применяется ко всем входам и одному выходу.
  • SIGHASH_ANYONECANPAY в сочетании с SIGHASH_ALL (0x81): подпись применяется к одному входу и всем выходам.
  • SIGHASH_ANYONECANPAY в сочетании с SIGHASH_SINGLE (ox83): подпись применяется к одному входу и одному выходу.

Redeem ScriptАктивировать скрипт

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

Первые 1–9 байтов сценария погашения типа VarInt и определяют количество последующих байтов, составляющих hash публичного ключа.

В этом случае первый байт (0x21) объявляет, что следующие 33 байта представляют собой хэш публичного ключа пользователя. Алгоритм хеширования — HASH160, который представляет собой SHA256, за которым следует хэш RIPEMD160. публичный ключ получается из закрытого ключа пользователя.

2102c9950c622494c2e9ff5a003e33b690fe4832477d32c2d256c67eab8bf613b34e

Sequence Number – Порядковый Номер (nSequence)

nSequence имеет длину четыре байта и выражается в виде шестнадцатеричного значения в формате с прямым порядком байтов.

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

Первоначально nSequence использовался только для отключения nLockTime (обсуждается ниже). Если для nSequence установлено значение 0xFFFFFFFF, то nLockTime игнорируется.

BIP0125 представил новое использование nSequence, используя его для сигнализации RBF, если его значение меньше 0xFFFFFFFE. Примером того, когда это желательно, является случай, когда пользователь отправляет свою транзакцию в сеть, но понимает, что комиссия недостаточна, и хочет повторно отправить транзакцию, которая назначает более высокую комиссию.

Транзакции часто по умолчанию используют значение nSequence равное 0xFFFFFFFE, отказываясь от RBF и разрешая nLockTime. Чтобы использовать nLockTime и подписаться на RBF, обычно для nSequence задается значение 0xFFFFFFFD.

В BIP0068 nSequence был перепрофилирован, чтобы можно было использовать блокировки относительного времени. Эта функциональность реализуется тогда и только тогда, когда транзакция имеет версию 02.

nSequence — это, по сути, продолжительность времени, которая должна пройти для подтверждения транзакции и указывается через высоту блока или в наборах по 2⁹ (512) секунд от текущего времени. Транзакция, заблокированная по относительному времени, недействительна до тех пор, пока (nSequence * 521 секунда) или (nSequence * количество блоков) не будут подтверждены ее родительские транзакции.

18 из 32 бит значения nSequence используются для блокировки относительного времени. Остальные 14 бит зарезервированы для будущих обновлений, как показано ниже:

Как происходит расшифровка P2PKH адресации в транзакции Биткоина

Подробное объяснение временных блокировок можно найти здесь . ( Временные замки Биткоина Bitcoin’s Time Locks )

Пример транзакции — версия 01 с порядковым номером 0xFFFFFFF, отказ от RBF и использование nLockTime.

Выходы транзакций

Выходные данные транзакции содержат выходные сценарии и сумму, которую контролируют эти сценарии. Чаще всего транзакция имеет более одного выхода. В типичном P2PKH транзакция имеет выход, содержащий выход расходов и выход сдачи. Каждый выход содержит потребленную сумму в сатоши и условия, которые необходимо выполнить, чтобы их потратить.

Количество выходов

Первый байт вывода транзакции определяет количество выходов и имеет тип VarInt.

В этой транзакции есть два выхода: один для суммы, потраченной из входящего UTXO, а другой для суммы сдачи.

Выходы

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

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

Эта транзакция P2PKH потребляет UTXO, ранее контролируемый адресом 19iy8HKpG5EbsqB2GUNVPUDbQxiTrPXpsx, со значением 17 373 066 сатоши. Первый вывод этой транзакции создает новый UTXO стоимостью 390 582 сатоши, который контролируется адресом получения 1JKRgG4F7k1b7PbAhQ7heEuV5aTJDpK9TS.

Второй вывод этой транзакции создает новый UTXO стоимостью 16 932 484 сатоши, который контролируется исходным адресом отправки 19iy8HKpG5EbsqB2GUNVPUDbQxiTrPXpsx. Это «сдача» от транзакции.

Первый вывод

Первая выходная сумма в десятичном значении составляет 390 582 сатоши (шестнадцатеричный 0x0005F5B6).

Скрипт блокировки извлекается из адреса пользователя, получающего средства.

Скрипт блокировки — это всего лишь скрипт, фрагмент кода, который сообщает сети, как можно потратить эту сумму. Код написан на Bitcoin Script, который представляет собой стековой язык обратной польской нотации (RPN), который является неполным по Тьюрингу. Это очень примитивный язык, который, по сути, просто извлекает значения из стека и выполняет операции с элементами с помощью серии команд, называемых OP_CODES .

Скрипт блокировки извлекается из адреса лица, получающего средства, и разбивается следующим образом:

  • 19 – (25 байт) длина следующего скрипта разблокировки.
  • 76 — OP_DUP: дублирует верхний элемент стека.
  • a9 — OP_HASH160: входные данные хешируются дважды: сначала с помощью SHA-256, а затем с помощью RIPEMD-160.
  • 14 – (20 байт) длина следующего хеша публичного ключа.
  • 88 — OP_EQUALVERIFY: возвращает 1, если входные данные абсолютно равны, и 0 в противном случае. Затем запускается OP_VERIFY, который терпит неудачу и помечает транзакцию как недействительную, если значение верхнего стека ложно.
  • ac — OP_CHECKSIG: все выходные данные, входные данные и сценарий хешируются. Подпись, используемая OP_CHECKSIG, должна быть действительной подписью для этого хеша и публичного ключа. Если да, возвращается 1, в противном случае 0.
  • bdf63990d6dc33d705b756e13dd135466c06b3b5 – хеш публичного ключа получателя средств.

Второй вывод

Второе выходное значение — 16 932 484 сатоши.

Скрипт блокировки для второго вывода отправляет отправителю обратно 16 932 484 сатоши. Это изменение отправителя.


Сценарий блокировки можно разобрать следующим образом.

  • 19 – (25 байт) длина следующего скрипта разблокировки.
  • 76 — OP_DUP: дублирует верхний элемент стека.
  • a9 — OP_HASH160: входные данные хэшируются дважды: сначала с помощью SHA-256, а затем с помощью RIPEMD-160.
  • 14 – (20 байт) длина следующего хеша публичного ключа.
  • 88 — OP_EQUALVERIFY: возвращает 1, если входные данные абсолютно равны, и 0 в противном случае. Затем запускается OP_VERIFY, который терпит неудачу и помечает транзакцию как недействительную, если значение верхнего стека ложно.
  • ac — OP_CHECKSIG: все выходные данные, входные данные и сценарий хешируются. Подпись, используемая OP_CHECKSIG, должна быть действительной подписью для этого хеша и публичного ключа. Если да, возвращается 1, в противном случае 0.
  • 5fb0e9755a3424efd2ba0587d20b1e98ee29814a – хеш публичного ключа получателя средств.

Комиссия на перевод

Комиссия за транзакцию, которая поступает майнеру, представляет собой разницу между общей суммой ввода и вывода. В примере транзакции комиссия майнера рассчитывается как:

Время блокировки (nLockTime)

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

Если nLockTime равен 0, блокировки по времени нет. Транзакция становится действительной немедленно.

Если nLockTime больше 0 и меньше 500 000 000, абсолютное время блокировки измеряется в единицах количества блоков.

Если nLockTime больше или равно 500 000 000, абсолютное время блокировки измеряется в единицах времени эпохи.

Важно отметить, что если для nSequence установлено значение 0xFFFFFFFF, то nLockTime полностью отключается.

В примере транзакции nLockTime имеет значение 0.


Разблокировка Bitcoin Script

Ниже показано, как сценарии блокировки и разблокировки работают вместе, чтобы разблокировать средства в выводе P2PKH. Показаны только значения для первого выхода, но эта логика применима к обоим выходам.

В крайнем левом столбце отображается содержимое сценария блокировки, в среднем столбце отображается содержимое сценария разблокировки, а (помните, что Bitcoin Script — это язык RPN, подобный Форту), самый правый столбец показывает, как строится стек.

Как происходит расшифровка P2PKH адресации в транзакции Биткоина

Скрипт выполняется следующим образом:

Как происходит расшифровка P2PKH адресации в транзакции Биткоина

Поместите подпись, а затем публичный ключ в стек:

Как происходит расшифровка P2PKH адресации в транзакции Биткоина

OP_DUP дублирует верхний элемент стека, публичный ключ, и помещает его на вершину стека:

Как происходит расшифровка P2PKH адресации в транзакции Биткоина

OP_HASH160 извлекает верхний элемент из стека и выполняет для него хэш SHA256, а затем RIPEMD160:


Затем он помещает этот хеш на вершину стека:

Как происходит расшифровка P2PKH адресации в транзакции Биткоина

Хэш публичного ключа помещается на вершину стека:

Как происходит расшифровка P2PKH адресации в транзакции Биткоина

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

Как происходит расшифровка P2PKH адресации в транзакции Биткоина

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

Если OP_CHECKSIG выполняется успешно, он помещает 1 в стек, и транзакция действительна и завершена.

Если пользователь не предоставил действительную подпись для публичного ключа, OP_CHECKSIG помещает в стек 0, указывая, что транзакция недействительна.

Как происходит расшифровка P2PKH адресации в транзакции Биткоина

Заключение: Транзакции Bitcoin P2PKH являются основным элементом криптографического экосистемы. Они обеспечивают безопасность, надежность и высокую эффективность всей системы. С помощью P2PKH-транзакций можно осуществить множество операций с Bitcoin, в том числе отправить, получить или управлять данными в криптовалюте. Поскольку этот тип транзакций обеспечивает высокий уровень безопасности, он является одним из самых популярных в мире Bitcoin.


Useful information for enthusiasts:

Contact me via Telegram: @ExploitDarlenePRO