Домой Технологии и рынок Понимание заголовков блоков в блокчейне Биткойна

Понимание заголовков блоков в блокчейне Биткойна

0

Составление заголовка блока — довольно сложно устроенный и в высшей степени значимый процесс. Если Биткойн — живой дышащий организм, то заголовок блока — это сердце всей машины. Каждые 10 минут в блоках Биткойна перемещаются и рассчитываются миллионы долларов капитала. Заголовок блока как будто заверяет нотариально перемещение средств в транзакциях, сигнализирует о поддержке предложений об изменении сети и в конечном счете определяет движение и правомерность биткойн-транзакций.

Номер версии предоставляет возможность для обновления сети посредством софт-форков. Хеш предыдущего блока связывает текущий блок с родительским, создавая цепочку из блоков — блокчейн. Корень Меркла криптографически связывает все транзакции в блоке с его заголовком. Метки времени действуют как верифицируемая система, полезная для работы многих приложений на основе Биткойна. Закодированная целевая сложность дает майнерам знать, какой хеш сеть примет как валидный. Наконец, nonce обеспечивает выделенное пространство для поиска валидного хеша, чтобы майнеры могли выполнять свою работу, обеспечивая работу сети.

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

Введение

Блокчейн Биткойна состоит из блоков. Блоки (и транзакции) представляют собой версионированные двоичные структуры данных. Блок состоит из двух частей: блока транзакций (в котором содержатся все включенные в блок транзакции) и заголовка блока. Заголовок — это короткое и строго форматированное поле данных, предваряющее каждый блок. Он включает в себя шесть полей, все с различными функциональными возможностями, и SHA256d-хеш этих полей действует как идентификатор блока. В центре внимания этой статьи находится именно заголовок блока, и мы продолжим в него углубляться, но сначала давайте кратко коснемся блока транзакций.

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

Майнер выполняет большое количество операций хеширования в поисках допустимого хеша, отвечающего этому условию. Для создания новых хешей из тех же данных блока, используется поле заголовка, называемое nonce, которое майнер может быстро изменять, чтобы генерировать уникальные хеши в поиске первого валидного. Как еще будет описано ниже, nonce содержит только четыре байта (2³² бита), которые можно изменять. Таким образом, пространство поиска составляет 2³² бита, то есть через изменение только поля nonce для блока может быть сгенерировано до 4 294 967 296 уникальных хешей. Это может показаться большим пространством для поиска, но на самом деле оно довольно мало, учитывая мощности доступного сегодня ASIC-оборудования. Например, производительность Antminer S19 Pro от Bitmain составляет 110 Тхеш/сек. Это около 2⁴⁶ хешей в секунду. То есть эта машина полностью исчерпывает пространство поиска, предоставляемое полем nonce, менее чем за одну миллисекунду.

Если пространство поиска оказывается исчерпано, а валидный хеш не найден, то майнеру придется формировать новый блок из нового набора транзакций. Сбор нового блока может быть вычислительно затратным и интенсивным с точки зрения пропускной способности. Поэтому у майнеров есть стимул находить способы к расширению пространства поиска за пределы выделенного четырехбайтового nonce. Есть несколько способов расширить пространство поиска: использовать (1) свободные биты поля версии, (2) часть битов поля времени, (3) несколько дополнительных битов в подписи скрипта coinbase-транзакции. Последнее часто называют extranonce, хоть в протоколе Биткойна это и не является формально определенным полем.

Как и любые данные, транзакции сводятся к последовательностям байтов. Иметь слишком «тяжелые» блоки, «весящие» слишком много байтов, нежелательно по причине различных ресурсных ограничений. Два наиболее распространенных из них связаны с (1) каналом исходящей связи (пропускная способность / задержка) и (2) проверкой (насколько быстро CPU может проверять транзакции). Ограничения, связанные с хранением данных, сейчас не представляют большой проблемы, поскольку оно стоит сравнительно недорого, а ноды могут сжиматься. Однако большие блоки могут помешать людям с ограниченным местом для хранения данных запускать полную ноду, тем самым нанося ущерб децентрализации сети. Кроме того, без ограничения размера блока сеть становится восприимчивой к DDoS-атакам со стороны злоумышленников, транслирующих в нее огромное количество транзакции с минимальной стоимостью. Чтобы противостоять этим явлениям, существует определенное консенсусом сети ограничение размера блока, называемого весом блока.

Что побуждает майнеров майнить блоки? У майнеров есть два источника дохода: субсидия блока (о которой мы еще будем говорить позже) и комиссии за транзакции. Им нужно соблюсти тонкий баланс: максимизировать прибыль от комиссий, включив в блок-кандидат как можно больше транзакций, но при этом сохранить вес блока ниже 4 Мб. Это сродни известной задаче о рюкзаке.

Есть также один особый тип транзакций, имеющий отношение к теме заголовка блока: coinbase-транзакция. Coinbase-транзакция включается в каждый блок первой и отвечает за создание новых биткойнов (субсидии блока) и выплату вознаграждения майнеру. И как я уже упоминал, несколько дополнительных битов в coinbase-транзакции используются майнерами для увеличения пространства поиска хеша.

Заголовок блока

Теперь мы готовы переходить к обсуждению заголовка блока в Биткойне. Заголовок имеет размер 80 байт и содержит шесть различных полей данных, все в формате little-endian.

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

Системы счисления и порядок следования байтов

Двоичная, десятичная и шестнадцатеричная системы счисления

Целые числа чаще всего выражаются в системе счисления с основанием 10, десятичной системе. Но в равной мере они могут быть выражены и в системе с любым другим основанием. Две другие системы счисления, полезные для понимания более низкоуровневых концептов Биткойна, — это двоичная (с основанием 2) и шестнадцатеричная (с основанием 16). Изменение основания с 10 на 2 или 16 (или любое другое число, если на то пошло) не меняет значение целого числа, только то, как оно выражается.

В двоичной системе числа имеют основание 2, и для выражения полного диапазона целых чисел требуется только два значения: 0 и 1. Приведу в качестве примера следующие числа типа u8 (каждое число имеет длину 8 бит):

Сравнение десятичных и двоичных чисел

Обратите внимание, насколько длиннее записываются двоичные числа в сравнении с десятичными.

Обычно к двоичным числам добавляется в качестве идентификатора символ b. Например, двоичный эквивалент десятичного числа 4 записывается как b0100.

Вы можете спросить, почему для выражения, например, двоичного числа b0000 0001 используется четыре цифры. Почему не просто b1? Это потому, что в памяти компьютера необходимо заранее выбрать количество битов, требуемое для целого числа. Так что если целое число может представлять любое число до b1111 1111, то в памяти целое число всегда должно занимать восемь цифр, даже если в действительности оно использует не все их.

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

В шестнадцатеричной системе числа имеют основание 16, поэтому для выражения полного диапазона целых чисел требуется шестнадцать значений: 0–9 и A–F.

Сравнение десятичных и шестнадцатеричных чисел

Заметьте, что в этом случае десятичная система обладает более пространной записью, чем шестнадцатеричная.

Обычно к шестнадцатеричным числам добавляются в качестве идентификатора символы 0x. Например, шестнадцатеричный эквивалент десятичного числа 3 735 928 559 записывается как 0xDEADBEEF.

Обратите внимание, что 0xDEADBEEF — это четырехбайтовое число. Каждые два символа эквивалентны одному байту: 0xDE — это один байт, 0xAD — один байт и так далее.

Для полноты сравнения, двоичный эквивалент десятичного числа 3 735 928 559 записывается как b1101 1110 1010 1101 1011 1110 1110 1111.

Порядок следования байтов

Понятие «порядок следования байтов» можно наглядно продемонстрировать на следующем примере: в русском языке мы говорим «23», а, например, в немецком это число произносится как «3 и 20». Это одно и то же число, только выраженное по-разному. Порядок следования байтов — аналогичная концепция: при прямом порядке (от старшего к младшему) сначала считываются наибольшие значения, при обратном порядке (от младшего к старшему), наоборот, сначала считываются наименьшие. Английские термины, используемые для обозначения порядка байтов — big-endian (от большего к меньшему) и little-endian (от меньшего к большему), — являются отсылкой к «Путешествиям Гулливера» Джонатана Свифта. В романе Свифта были две враждующие группы людей: тупоконечники (Big Endian) и остроконечники (Little Endian). Одни разбивали и начинали чистить яйца с широкой части, другие — с узкой. В романе эта незначительная разница в методологии разбивания яиц в итоге приводит к хаосу.

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

В формате big-endian сначала считываются наиболее значимые байты. Именно так мы интуитивно читаем числа. Десятичное число 3 735 928 559 в шестнадцатеричном big-endian формате записывается как 0xDEADBEEF — совершенно ожидаемым образом. В big-endian системе это число в двоичном формате хранится в памяти компьютера следующим образом (шестнадцатеричные значения тоже представлены для наглядности):

Двоичные и шестнадцатеричные числа в формате big-endian

Или же число может сохраняться в памяти компьютера в формате little-endian (от младшего к старшему). В little-endian сначала считываются наименее значимые байты числа. Это не то, как мы интуитивно читаем числа.

В little-endian системе это число в двоичном формате хранится в памяти компьютера следующим образом (шестнадцатеричные значения тоже представлены для наглядности):

Двоичные и шестнадцатеричные числа в формате little-endian

При сравнении big-endian и little-endian форматов (надеюсь) становится ясно, что единственное различие заключается в порядке байтов. В big-endian шестнадцатеричный эквивалент числа 3 735 928 559 записывается как 0xDEADBEEF. В little-endian он записывается как 0xEFBEADDE. Порядок следования байтов важно иметь в виду, потому что в формате little-endian число 0xEFBEADDE по-прежнему эквивалентно десятичному числу 3 735 928 559, а не 4 022 250 974.

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

В Биткойне (в основном) используется формат little-endian и это важно знать перед тем, как двигаться дальше.

Возвращаясь к заголовку блока

Вернемся к заголовку блока.

В шестнадцатеричном формате типичный заголовок блока выглядит следующим образом:

Заголовок блока Биткойна на высоте 645 536

Этот заголовок взят из блока на высоте 645 536, добытого Slushpool. Мы будем использовать его в качестве примера на протяжении всей статьи.

Каждое поле, его тип данных и краткое описание поля приведены в следующей таблице.

Поля данных заголовка блока

Как заголовок блока используется в процессе майнинга

На высоком уровне процесс майнинга сводится к следующим этапам:

  • Выбор подходящего номера версии и времени в текущей эпохе. Из сети получается хеш предыдущего блока (из последнего блока в самой длинной ветке блокчейна) и целевое значение хеша.
  • Выбор неподтвержденных транзакций из мемпула для включения в блок-кандидат.
  • Создание coinbase-транзакции.
  • Вычисление корня Меркла из всех транзакций блока, включая coinbase-транзакцию.
  • Конкатенация этих значений для создания сообщения блока.
  • Выбор числа для nonce и добавление его к сообщению блока — завершение создания полного заголовка блока-кандидата.
  • Выполнение SHA256-хеширования заголовка блока (дважды) и сравнение результата с целевым значением.
  • Если хеш заголовка блока меньше или равен целевому значению, то блок валиден, и майнер транслирует его в сеть для подтверждения другими участниками. Затем он возвращается к шагу 1 и начинает майнинг следующего блока-кандидата.
  • Если хеш заголовка блока не удовлетворяет целевому значению, то блок невалиден, и майнер возвращается к шагу 6, увеличивая значение nonce и снова испытывая удачу.
  • Эти шаги показаны на схеме:

    Схема процесса майнинга для построения заголовка блока

    Теперь, когда мы дали определение заголовку блока и описали, насколько важную роль он играет в Биткойне, можно более подробно изучить каждый из его параметров.

    Версия

    Поле версии в блоке на высоте 645 536

    Поле версии обычно обрабатывается как четырехбайтовое число в формате big-endian, интерпретируемое как тип int32 и содержащее дополнительные биты, которые майнеры могут использовать для подачи сигнала о готовности поддержать софт-форк и для получения дополнительных 2¹⁶ пространства поиска.

    На первый взгляд непритязательное, на поверку поле версии блока оказывается не так просто устроено. Номер версии предоставляет майнерам инструмент для сигнализации о своей готовности поддержать те или иные обновления сети посредством софт-форка. Успех или непринятие активируемого майнерами софт-форка зависит от того, достаточное ли количество поступающих в сеть валидных блоков сигнализировало о готовности принять предлагаемые изменения. «Готовность» здесь означает, что майнер обновил используемое ПО до совместимости с версией биткойн-клиента, содержащей предлагаемые изменения. Примером голосования по софт-форку и его фиксации может служить активация SegWit.

    Три бита с самым большим значением в поле версии зарезервированы для возможных будущих обновлений механизма. В настоящее время три самых значимых бита должны быть установлены в значение b001. Это значит, что минимально допустимый номер версии в формате big-endian — это 0x2000000 (b0010 0000 0000 0000 0000 0000 0000 0000). Максимальный номер версии в big-endian формате — 0x3FFFFFF (b0011 1111 1111 1111 1111 1111 1111 1111).

    На момент написания этой статьи (декабрь 2020) номер версии записывается в соответствии со спецификацией BIP9. Прежде чем углубиться в BIP9, давайте посмотрим, как изменялся номер версии с момента основания сети.

    Краткая история поля версии в заголовке блока

    Версия 1 началась с блока генезиса в 2009 году. До сентября 2012 никакого значимого сигнализирования не просматривается.

    В сентябре 2012 Bitcoin Core v0.7.0 представило BIP34, выводившее блоки версии 1 из стандарта Биткойна. Это BIP подразумевало введение двух новшеств:

  • Структурированный способ для майнеров сигнализировать о своей готовности принять предлагаемый софт-форк. Это достигалось с помощью механизма переключения с двойным порогом, метода IsSuperMajority(), в котором определены два пороговых значения, называемые правилом 75% и правилом 95%. Правило 75% гласит, что, как только 750 из последних 1000 блоков сигнализируют о готовности принять изменения, установив номер версии на 2 или выше, все новые блоки, в заголовке которых указана версия 2, должны соответствовать предлагаемым в софт-форке спецификациям. Иначе блок будет отклонен сетью, даже будучи валидным по стандартам версии 1. Правило 95%, следующий этап, гласит, что, как только 950 из последних 1000 блоков будут иметь версию 2 или выше, все блоки с версией 1 будут отклоняться сетью как недействительные.
  • Актуальное предложение о софт-форке, требовавшее, чтобы все блоки версии 2 или выше включали высоту блока как первый элемент в подписи скрипта coinbase-транзакции.
  • На то, чтобы блоки версии 2 стали стандартом, ушло около шести месяцев, а последний блок версии 1 на высоте 227 835 имел метку времени 2013–03–24 15:49:13 GMT.

    Предложение софт-форка, определяющее версию 3, описано в BIP66 и было представлено в феврале 2015 в Bitcoin Core v0.10.0. Блоки версии 3 ограничивают подписи строго кодировкой DER. Метод подачи сигнала о поддержке софт-форка соответствовал BIP34.

    Предложение софт-форка, определяющее версию 4, описано в BIP65 и было представлено в ноябре 2015 в Bitcoin Core v0.11.2. Блоки версии 4 стали распознавать новый опкод для системы скриптов Биткойна, OP_CHECKLOCKTIMEVERIFY, позволяющий блокировать UTXO от расходования на заданное время.

    Хотя метод подачи сигнала IsSuperMajority(), описанный в BIP34, работал, он имел некоторые недочеты. А именно (1) отсутствие таймаута и (2) использование для подачи сигнала целых числовых значений, а не битов (объясняется ниже). BIP9 решил обе эти проблемы.

    Улучшения поля версии в BIP9

    BIP9 определяет поведение поля версии, применяемое сегодня. Требуется, чтобы каждое предложение софт-форка имело четыре параметра:

  • Отличительное название.
  • Бит в поле версии, изменение которого будет сигнализировать о готовности майнера принять изменения. Номер позиции бита обозначается .
  • Время старта: с какого момента определенный бит обретает актуальное сигнальное значение.
  • Тайм-аут: если предложение не будет принято к определенной дате , оно будет считаться непрошедшим.
  • Изменение одного бита в поле версии, вместо записи в поле заданного целого числа (как в BIP34), позволяет подавать сигналы по нескольким предложениям одновременно.

    В блогпосте (англ.) Расти Рассела отлично объясняется эволюция и значимость поля версии. Отталкиваясь от этого поста, здесь я буду рассказывать о поле версии более детально. Давайте начнем с того, как именно работает сигнализация с помощью битов, описанная в BIP9.

    Полное 32-битное двоичное представление типичного big-endian номера версии 0x20000000 выглядит так:

    b0010 0000 0000 0000 0000 0000 0000 0000

    Это соответствует правилам, установленным в BIP9, согласно которым самые верхние биты должны быть b001 или больше.

    Теперь представим, что есть новое предложение о софт-форке, называемое BIPN₀, которое устанавливает позицию сигнального бита на 0 (N = 0). Для сигнализации о поддержке предложения нулевой бит нужно изменить на 1. Тогда номер версии в big-endian формате будет выглядеть как 0x20000001, или

    b0010 0000 0000 0000 0000 0000 0000 0001

    Теперь этот майнер сигнализировал о своей поддержке BIPN₀.

    Теперь представим, что одновременно активны еще два предложения по софт-форку: BIPN₁ (N = 1) и BIPN₂ (N = 2). Наш майнер готов поддержать только BIPN₀ и BIPN₂, но не BIPN₁. С механизмом BIP9 это не проблема. Сигнализировать о поддержке только BIPN₀ и BIPN₂ можно, установив значения нулевого и второго битов на 1, а бит на первой позиции оставить без изменений: 0. Тогда номер версии в big-endian формате будет выглядеть как 0x20000005, или

    b0010 0000 0000 0000 0000 0000 0000 0101

    Возможность в любой момент времени иметь несколько активных предложений о софт-форке делает этот механизм более совершенным в сравнении с использованием целочисленных значений согласно BIP34.

    Также майнеры могут использовать и используют поле версии для получения дополнительного пространства поиска хеша. Первоначально, после того как было представлено BIP9, майнеры по-прежнему использовали для расширения пространства поиска все свободные биты поля версии. Однако это привело к тому, что ноды генерировали предупреждения, поскольку пытались интерпретировать биты как сигнал по несуществующим предложениям о софт-форке. С BIP320 эта проблема была решена путем выделения 16 бит для расширения пространства поиска и резервирования 13 бит для подачи сигналов по софт-форкам. Это позволяет майнеру расширить пространство поиска на 2¹⁶ и оставляет место для подачи сигналов по 13 актуальным предложениям о софт-форке.

    Хеш предыдущего блока

    Поле хеша предыдущего блока в блоке на высоте 645 536

    Поле хеша предыдущего блока представляет собой 32-битное значение в формате little-endian, интерпретируемое как тип char[32], и является хешем предыдущего блока. Это поле обеспечивает связь между текущим и предыдущим блоком в сети.

    Корень Меркла

    Поле корня Меркла в блоке на высоте 645 536

    Поле корня Меркла представляет собой 32-байтовое значение в формате little-endian, интерпретируемое как тип char[32]. Структура дерева Меркла используется в области компьютерных наук для многих целей. В Биткойне дерево Меркла используется для криптографической привязки каждой транзакции в блоке к заголовку этого блока в лаконичных 32 байтах.

    Каждая транзакция — это лист дерева Меркла. Транзакции должны быть включены в блок в топологическом порядке. То есть, если txₙ₊₁ расходует выход txₙ, то txₙ₊₁ должна быть отсортирована на более позднюю позицию в блоке, чем txₙ. А самый первый лист в дереве Меркла зарезервирован для coinbase-транзакции.

    Поиск корня Меркла

    После того как майнер отобрал транзакции для включения в блок-кандидат, для получения корня Меркла выполняются следующие шаги:

  • Id (SHA256d-хеш) каждой транзакции попарно конкатенируются в один.
  • Конкатенированная пара транзакций хешируется алгоритмом SHA256d. Получаемая хеш-сумма становится новой ветвью в дереве.
  • Хеш-суммы, опять же, попарно конкатенируются и хешируются алгоритмом SHA256d, создавая новую ветвь в дереве.
  • Шаг 3 повторяется, пока не останется только один хеш, корень Меркла. Это значение и сохраняется в заголовок блока.

    Мерклизация произвольного набора данных

    Время

    Поле времени в блоке на высоте 645 536

    Поле времени представляет собой четырехбайтовое значение в формате little-endian, интерпретируемое как тип unit32, которое является меткой времени внутри эпохи для текущего блока. С помощью меток времени сеть может определить текущую скорость подтверждения блоков, чтобы при необходимости периодически ее корректировать (каждые 2016 блоков, или около 2 недель). Правила консенсуса ограничивают диапазон допустимых значений временных меток примерно трехчасовым окном, оставляя свободными 2¹³ бит, которые можно использовать для расширения пространства поиска.

    Валидная метка времени должна быть больше, чем среднее значение временных меток предыдущих 11 блоков. При скорости подтверждения 10 минут на блок, это составляет один час с момента отправки блока-кандидата. Метка времени должна быть также меньше времени, скорректированного по сети, плюс два часа. Это трехчасовое окно составляет 10 800 секунд, что дает дополнительные 2¹³ бит для расширения пространства поиска хеша:

    2ˣ = 10 800
    x = ln(10 800) / ln(2)
    x = 13,3987 => 13

    Скорректированное по сети время — это локальное время (UTC) ноды плюс медианное смещение всех подключенных нод. Время сети никогда не корректируется более чем на 70 минут от локального системного времени.

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

    Биты

    Поле битов в блоке на высоте 645 536

    Поле битов представляет собой четырехбайтовое значение в формате little-endian, интерпретируемое как тип int32, в котором кодируется текущий целевой порог для валидного хеша. Результирующий хеш блока, чтобы рассматриваться сетью как допустимое решение, должен быть меньше либо равен этому целевому значению. Целевое значение обновляется каждые 2016 блоков (около двух недель), так что каждый заголовок блока, транслированный в течение этого периода в 2016 блоков, будет иметь одно и то же целевое значение.

    Как мы знаем, для поиска хеша блока поля данных в заголовке блока (версия, хеш предыдущего блока, корень Меркла, целевой порог хеша, время и nonce) конкатенируются и хешируются вместе с помощью SHA256d. Результирующий хеш является хешем заголовка блока-кандидата и выступает уникальным идентификатором этого блока. Чтобы считаться валидным, хеш должен быть меньше либо равен текущему целевому значению, устанавливаемому сетью, — таким образом задается сложность добычи валидного блока для майнера. Без целевого порога создать допустимый блок не составляло бы никакого труда, и сеть бы просто распалась.

    Максимальное целевое значение, создаваемое хешем SHA256d — это 0x00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF или в десятичной системе счисления 26 959 946 667 150 639 794 667 015 087 019 630 673 637 144 422 540 572 481 103 610 249 215. Это очень большое число. Биткойн хранит целевое значение в виде числа с плавающей точкой, поэтому используется усеченная форма 0x00000000FFFF0000000000000000000000000000000000000000000000000000, эквивалентная 26 959 535 291 011 309 493 156 476 344 723 991 336 010 898 738 574 164 086 137 773 096 960 в десятичной системе счисления. Это все еще огромное число.

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

    1. Изменение формата следования байтов с little-endian (используемого в заголовке) на big-endian: 0x2F931D1A → 0x1A1D932F. В конечном счете важно не то, какой порядок байтов используется, но постоянство и последовательность подхода.

    2. Отделение первого байта, 0x1A, от остальных, 0x1D932F. Этот первый байт называется мантиссой. Мантисса — это часть числа с плавающей точкой, представляющая количество значащих цифр. Затем мантисса умножается на основание (в данном случае 2) и возводится в степень, чтобы получить значение числа.

    То есть целевое значение [хеша] извлекается из поля битов с помощью следующей операции:

    Target = мантисса × основание(экспонент — длина мантиссы)

    Используя это уравнение, вычислим целевой порог для нашего блока:

    Target = 0x1D932F × 2⁽⁸ˣ⁽⁰ˣ¹ᴬ ⁻ ³⁾⁾
    = 0x1D932F × 2⁽⁸ ˣ ⁽²⁷ ⁻ ³⁾⁾
    = 0x1D932F0000000000000000000000000000000000000000000000

    Обратите внимание, что разность между экспонентой и длиной мантиссы в приведенном выше уравнении умножается на 8. Это небольшое сокращение, основанное на том факте, что в одном байте содержится восемь битов. Так что, вместо того чтобы записывать каждый из параметров в двоичном формате, что было бы гораздо более длинно, каждый байт берется целиком.

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

    0x0000000000001D932F0000000000000000000000000000000000000000000000
    0x00000000000016BF116FC90CF45AEC2DA4D13349358159D8B4EDDCB37EAB295B

    Запись тех же чисел с основанием 10 выглядит следующим образом:

    47525089675259291211422247200069659468817014361857087365971968
    36551990950853533658225321687497789580066641734434828845787483

    Следовательно, поскольку значение хеша меньше целевого, заголовок является валидным.

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

    Рассмотрим 16-битный регистр, содержащий число 11:

    b0000 0000 0000 1011

    В 16-битном регистре, как вы уже догадались, есть место только для 16 бит. Если мы сместим биты на количество доступных битов (16), то столкнемся с переполнением и потеряем наше число 11:

    Lost Bits | Remaining Bits
    1011 | 0000 0000 0000 0000

    Чтобы этого избежать, мы устанавливаем, что можем смещаться только на доступное количество битов минус то число битов, которые мы хотим сохранить. В данном случае, 16 – 4 = 12, что даст:

    Lost Bits | Remaining Bits
    |1011 0000 0000 0000

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

    Nonce

    Поле nonce в блоке на высоте 645 536

    Поле nonce представляет собой четырехбайтовое значение в формате little-endian, интерпретируемое как тип int32, которое пошагово увеличивается для создания новых хешей текущего блока, чтобы найти удовлетворяющий целевому значению. Оно обеспечивает 2³² бита дополнительного пространства поиска хеша.

    Параметр nonce играет важную роль в поиске валидного блока. Без nonce, когда майнер создает блок, не соответствующий сложности сети, для получения нового хеша ему пришлось бы изменять набор транзакций в блоке, пересчитывать корень Меркла и перестраивать заголовок блока. Такой процесс требует немалого объема вычислительной работы. С nonce же майнеру достаточно один раз создать заголовок блока-кандидата и сохранять постоянными все переменные, за исключением nonce. Майнер пошагово увеличивает значение nonce и пересчитывает хеш до тех пор, пока либо (1) хеш заголовка блока не будет соответствовать порогу сложности (найден валидный заголовок блока), либо (2) блок станет устаревшим (конкурирующий майнер нашел валидный заголовок блока), либо (3) будет исчерпано пространство поиска внутри поля nonce.

    Coinbase-транзакция

    Coinbase-транзакция — это особый тип транзакции в каждом блоке Биткойна, единственная транзакция, которая не указывает на существующий UTXO, но вместо этого выпускает новые BTC в соответствии с монетарной политикой протокола.

    Coinbase-транзакции важны по трем основным причинам: (1) в них создаются новые UTXO, (2) они обеспечивают дополнительное пространство для поиска хеша и (3) позволяют майнерам помечать блоки как собственные.

    Coinbase-транзакция для блока 645 536 выглядит следующим образом:

    Coinbase-транзакция в блоке на высоте 645 536

    Каждое поле, его тип данных и краткое описание поля приведены в таблице:

    Поля данных транзакции

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

    Подпись скрипта (скрипт разблокировки)

    Подпись скрипта в coinbase-транзакции блока на высоте 645 536

    Подпись скрипта, называемая также скриптом разблокировки, имеет переменную длину в байтах, которая ограничивается консенсусом сети. Обычно скрипт разблокировки содержит условия, позволяющие использовать UTXO предыдущей транзакции. Однако в coinbase-транзакции существующие UTXO не используются, а только создаются новые. Вместо этого, подпись скрипта содержит высоту блока (в соответствии с BIP34) и любую другую информацию, которую майнер решит здесь разместить. Очень часто сюда включаются параметры extranonce, а также любые идентифицирующие «подписи», которые майнер может размещать по своему усмотрению.

    Параметр extranonce — это не строгое поле, определенное протоколом Биткойна, но просто некоторые биты, которые майнер может использовать для расширения пространства поиска хеша. Многие пулы поддерживают параметр extranonce и накладывают ограничения на его длину. Чаще всего можно увидеть восьмибайтовый extranonce.

    Разбирая подпись скрипта, первые 1–9 байтов обозначают длину скрипта разблокировки, являющуюся переменной. В данном случае длина составляет 0x4B (десятичные 75) байт.

    Следующий байт обозначает длину следующей части coinbase-транзакции. В данном случае это 0x03, что говорит о том, что следующие три байта, 0xA0D909, имеют значение. В эти байтах записана высота блока, 645 536, в шестнадцатеричном little-endian формате, в соответствии с BIP34. Следующие 64 байта содержат extranonce и любую другую информацию, которую майнер решит здесь разместить. Размер параметра extranonce варьируется от пула к пулу.

    Наконец, последние семь байтов, 0x2F736C7573682F, — это необязательный идентификатор, используемый SlushPool для пометки своих блоков, /slush/. Снабжая блок этим идентификатором, пул публично сообщает, что этот блок был получен от него.

    Конечно, любой другой субъект сети, добывший валидный блок, может включить в coinbase-транзакцию тот же текст и притвориться SlushPool или каким-то другим майнером. И наоборот, Slush (или любой другой майнер) может исключить из подписи скрипта свой обычный идентификатор и добыть блок анонимно.

    Большинство майнеров обычно добавляют свое имя, чтобы показать, что они добывают блоки (это имеет смысл с точки зрения маркетинга, чтобы продемонстрировать успешность вашего пула), но точно так же здесь можно разместить любые другие данные или не размещать ничего. Чтобы составить представление о том, какой процент майнеров включают в coinbase-транзакцию свой идентификатор, в четырехдневный период с 25 по 28 сентября 2020 года идентификатор присутствовал в 77,7% блоков.

    Заключение

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

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

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

     

    Подписывайтесь на BitNovosti в Telegram!

    Источник: bitnovosti.com