Вычисление идентификатора транзакции
Это вторая публикацией из цикла статей объясняющих устройство блокчейна. Первую я публиковал на стиме т.к. голоса ещё не было. В ней я рассказал как вычислить биткоин адрес по известному публичному ключу.
Рассмотрим вычисление идентификатора транзакции на примере самой первой транзакции из блокчейна биткоина. В этой транзакции на кошелек сатоши начисляется 50 биткоинов. Но сначала рассмотрим, что же в ней содержится.
Каждая транзакция состоит из одного или нескольких входов и из одного или нескольких выходов.
Все транзакции кроме транзакции генерации новых биткоинов в качестве входов используют выходы более ранних транзакций.
Структура входа транзакции следующая:
TxOutHash (32 байта) – идентификатор транзакции содержащей используемый выход
TxOutIndex (4 байта) – порядковый номер используемого выхода внутри транзакции
Script length (от 1 до 9 байт, 1 байт в случае числа меньше 253) - длинна скрипта в байтах
Script (длинна определеятся по script length) - скрипт;
Sequence (4 байта) – порядковый номер этого входа начиная с нуля
Для транзакции генерации биткоинов нет входа (предыдущей транзакции), по этому в качестве TxOutHash будет использоваться 0 а в качестве TxOutIndex 2^32-1 (что в другом прочтении можно считать -1). Скрипт содержит помещение произвольные байт в стек (не совсем так но об этом в другой раз).
Когда сатоши создавал первый блок он хотел поместить в него доказательство того, что блок был создан не раньше 03/01/2009 поэтому cкрипт первой транзакции создания монет кладёт в стек 3 значения третье из которых заголовок The Times от 03/01/2009:
"The Times 03/Jan/2009 Chancellor on brink of second bailout for banks".
В шестнадцатиричном виде это строка имеет вид:
5468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6
e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73
Скрипт первой транзакции создания монет имеет вид:
PUSHDATA(4)[ffff001d] PUSHDATA(1)[04]
PUSHDATA(69)[5468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f7
2206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73]
Операции PUSHDATA(4)
соответствует 04
, PUSHDATA(1)
соответствует 01
и PUSHDATA(69)
соответствует 45
(шестнацатиричная запись 69). Итого скрипт:
04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6
f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73
Структура выхода транзакции следующая:
Value (8 байт) – величина выхода измеряется в минимальнах неделимых единицах биткоина “сатоши” (10^-8 биткоина).
Script length (от 1 до 9 байт, 1 байт в случае числа меньше 253) - длинна скрипта в байтах
Script (длинна определеятся по script length) - скрипт
Sequence (4 байта) – порядковый номер этого выхода начиная с нуля
Cкрипт зачисления биткоинов на кошелёк имеет вид: <pubKey> OP_CHECKSIG
Публичный ключ кошелька Сатоши из первого блока:
04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb
649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f
Его длинна составляет 65 байт. Для записи этих 65 байт в скрипт нужно добавить перед ним PUSHDATA(65)
в шестнадцатиричном виде записывается как 41.
OP_CHECKSIG
– операция проверки того что подпись соответствует публичному ключу. Этой операции соответствует значение байта ac (172).
В итоге скрипт начисления биткоинов:
4104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb
649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac
Перейдём к транзакции, её структура:
Описание | # | Значение | Пояснение |
---|---|---|---|
Версия формата транзакции | 4 | 01000000 | 1 => 00 00 00 01 |
Количество входов транзакции | VI | 01 | 1 => 01 |
Id транзакции содержащей используемый выход (TxOutHash) | 32 | 00000000000000000000000000000000 00000000000000000000000000000000 | 0 |
Порядковый номер выхода (TxOutIndex) | 4 | ffffffff | -1 => ff ff ff ff |
Длинна скрипта | VI | 4d | 77 => 4d |
Скрипт | 04ffff001d0104455468652054696d65 732030332f4a616e2f32303039204368 616e63656c6c6f72206f6e206272696e 6b206f66207365636f6e64206261696c 6f757420666f722062616e6b73 | nonce + ‘The Times 03/Jan/2009 Chancellor on brink of second bailout for banks’ | |
Порядковый номер | 4 | ffffffff | -1 => ff ff ff ff |
Количество выходов транзакции | VI | 01 | 1 => 01 |
Величина (Value) | 8 | 00f2052a01000000 | 5000000000 => 00 00 00 01 2a 05 f2 00 |
Длинна скрипта | VI | 43 | 67 => 43 |
Скрипт | 4104678afdb0fe5548271967f1a67130 b7105cd6a828e03909a67962e0ea1f61 deb649f6bc3f4cef38c4f35504e51ec1 12de5c384df7ba0b8d578a4c702b6bf11d5fac | ||
Порядковый номер | 4 | 00000000 | 0 => 00 00 00 00 |
В итоге имеем шестнадцатиричную (base256) запись транзакции (rawtransaction).
01000000010000000000000000000000000000000000000000000000000000000000000000
ffffffff4d04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368
616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f75742066
6f722062616e6b73ffffffff0100f2052a01000000434104678afdb0fe5548271967f1a671
30b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c38
4df7ba0b8d578a4c702b6bf11d5fac00000000
Для того, что бы перевести это представление в двоичный код воспользуемся любым подходящим онлайн сервисом. Примеры используемых сервисов можно найти в первой статье. Вводим rawtransaction, на выходе получаем бинарный файл.
Используем подходящий сервис для вычисления sha256 полученного файла. Загружаем файл и на выходе получаем строку:
27362e66e032c731c1c8519f43063fe0e5d070db1c0c3552bb04afa18a31c6bf
Повторяем то же самое для неё. Переводим в бинарный файл и считаем для файла sha256. На выходе получаем строку:
3ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a
Записывая байты (2 шестнадцатеричных символа) в обратном порядке получаем
Искомый идентификатор транзакции (txid)
4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b