July 30, 2022

Биткоин: работа продолжается. Глава 1

Технические инновации из окопов

Фото автора

Перевод NADO Book by Sjors Provoost.

Проект перевода организован HypeCoinNews.

Основы и Обзор

В этой части мы объясним ряд основных понятий, которые будут упоминаться в следующих главах. Чтобы получить более подробное и структурированное введение в биткоин, вы можете ознакомиться с Mastering Bitcoin Андреаса М. Антонопулоса, или Grokking Bitcoin Калле Розенбаума. Однако для понимания данного текста прочтение этих книг не обязательно.

В главе 1 мы объясняем, что биткоин-адрес — это не то, что лежит в блокчейне, а скорее соглашение, используемое программным обеспечением кошелька для указания, куда должны быть отправлены монеты. Мы также объясним, как эти адреса кодируются с использованием base58, а в последнее время и при помощи bech32.

В главе 2 мы объясняем, как при первом запуске вашего биткоин-узла он находит одноранговые узлы для связи. Также вы получите краткое введение в Tor.

В главе 3 рассказывается о софтфорке SegWit 2017 года и о том, как он позволил увеличить размер блока и проложил путь к появлению сети Lightning за счет исправления уязвимости в механизме формирования идентификатора транзакции.

Наконец, глава 4 объясняет, что такое библиотеки, как они вызывают проблемы и, в частности, что случилось с OpenSSL.

Советы по чтению

Каждая глава содержит QR-код, который позволяет перейти к соответствующему выпуску подкаста и примечаниям к нему. Номер эпизода указан под QR-кодом. Вы также можете найти эпизод в своем любимом приложении для подкастинга, выполнив поиск Bitcoin, Explained. Или воспроизведите ее в браузере.

Рядом с каждым URL-адресом отображается маленький QR-код. Для сокращения адресов используется сервис btcwip.com. Мы не будем вас отслеживать.

В тексте есть много ссылок на программное обеспечение узла Bitcoin Core и его встроенный кошелек. Приложение B содержит несколько скриншотов и показывает типичный рабочий процесс отправки и получения биткоинов.

Глава 1. Биткоин-адреса

Биткоин-адреса это не часть блокчейна Биткоина; скорее, это соглашения, используемые программным обеспечением Биткоина (кошельками) для сообщения, куда должны быть отправлены монеты: открытый ключ (P2PK), хеш открытого ключа (P2PKH), хэш скрипта (P2SH), хэш открытого ключа свидетельства. (P2WPKH) или хеш скрипта-свидетельства (P2WSH). Адреса также содержат некоторые метаданные о самом типе адреса.

Биткоин-адреса сообщают об этих возможностях оплаты, используя свои собственные системы кодирования, и в данной главе будет рассмотрено, что означают эти разные системы. Также будут рассмотрены некоторые преимущества использования биткоин-адресов в целом и адресов bech32 в частности. Также в ней будет описано, как первая версия адресов bech32 содержала (относительно безобидную) ошибку, и как она была исправлена. Глава заканчивается разговором о квантовых технологиях.

Немного истории

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

Самое банальное обременение - монету может потратить любой желающий. Это не очень хорошая идея, потому что ее очень быстро украдут. Поэтому в первые дни большинство монет в блокчеине были обременены одним из двух способов: оплата по открытому ключу (P2PK) и оплата по хэшу открытого ключа (P2PKH). Первое может быть прочитано как «только владелец закрытого ключа, соответствующего открытому ключу X, может потратить эту монету», а второе как «только владелец закрытого ключа, соответствующего (секретному) открытому ключу, хэш от которого равен X, может потратить эту монету».

В то время можно было отправлять биткойны на IP-адреса получателей, но в 2012 году от этой функции отказались. Пока это было возможно, вы могли подключиться к чьему-либо IP-адресу и попросить открытый ключ, и человек давал бы вам свой открытый ключ. Затем ваш кошелек создавал для отправляемой монеты обременение скриптом P2PK.

Примечание для любопытствующего археолога кода: на узле отправителя интерфейс представлял собой диалоговое окно, в котором запрашивалась сумма и IP-адрес. Функция StartTransfer() создала пустую "чековую транзакцию", в которую "выставляющий чек" на узле-получателе вставлял сценарий P2PK (как scriptPubKey). Далее функция OnReply2() вставляла сумму, подписывала транзакцию, возвращала ее получателю и транслировала в открытый доступ.

Сегодня этот рабочий процесс может показаться странным (и небезопасным, как признал Сатоши), но он соответствовал распространенному в то время шаблону работы одноранговых приложениях, таких как Napster или Kazaa, где вы могли напрямую подключаться к другим людям и загружать от них что-то. В наше время вы, вероятно, уже не знаете IP-адреса своих друзей, к тому же они могут постоянно меняться, если речь идет о мобильных устройствах. Хотя вы можете указать своему узлу Биткойн специально подключаться к дружественному узлу, обычно он просто подключается к случайным узлам (см. главу 2).

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

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

Третий способ совершения транзакций — это майнинг биткоинов, который включает в себя отправку вознаграждения за блок самому себе. Вначале в Биткоин была встроена часть программного обеспечения для майнинга, поэтому, если вы загружали софт для Биткоина, он просто сразу начинал "добычу" блоков. Затем он отправлял добытые монеты на ваш собственный кошелек, поэтому не было необходимости сообщать адрес. Эти монеты были обременены посредством P2PK.

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

Так что же содержится в адресе?

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

Пока аналогия с банковскими счетами верна, но в главе 10 мы узнаем, что сценарии могут быть гораздо более мощными, чем просто емкости для хранения денег своих владельцев.

Из двух основных типов скриптов, использовавшихся в то время, адреса использовались только для оплаты по хэшу открытого ключа (P2PKH). Когда кошелек видит такой адрес, он создает скрипт для блокчейна Биткоина, который требует, чтобы человек, который его тратит, имел открытый ключ, соответствующий хэшу (в главе 10 приводится текущий скрипт). Публикуется только хэш, поэтому открытый ключ остается секретным, пока получатель не потратит монеты.

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

Основания систем счисления

Чтобы понять, что такое base58, важно сначала узнать больше о системах счисления в целом.

Base10 легко объяснить на примере вашей собственной руки. У вас 10 пальцев. Таким образом, если вы хотите, например, выразить число 115 (1, 1, 5), вы можете сделать три жеста руками, показывая 1, 1 и 5. Аналогичным образом вы записываете и числа, которые — начиная с изобретения глиняных табличек и бумаги — удобнее, чем счет на пальцах. Таким образом, base10 — это десятичная система, которая использует 10 различных символов в различных комбинациях для представления любого числа (целого числа).

Однако существовали, да и сейчас существуют, иные системы счисления. Например, вавилоняне использовали основание 60. А для чтения машинного кода обычно используется шестнадцатеричный код, который имеет основание 16 — от 0 до 9, а затем от A до F. Между тем, сами компьютеры, как правило, используют base2 — двоичную систему счисления — потому что транзисторы либо включены, либо выключены. Это означает, что все требуется делать с использованием двух цифр, либо 0, либо 1, и таким образом можно выразить любое число.

Сатоши предложил систему base58, в которой используется 58 различных символов: от 0 до 9, а затем большая часть алфавита как в нижнем, так и в верхнем регистре. Но есть некоторые буквы и цифры, которые пропускаются, потому что они неоднозначны, и пользователи могут перепутать их друг с другом — например, цифра 0 и заглавная буква O, а также заглавная I и строчная l.

Вы когда-нибудь видели исходный код вложенного в электронное письмо файла или чего-то подобного? Там много странных символов. Это base64, а base58 основана на ней. Но base64 включает в себя такие символы, как подчеркивание, плюс, равенство и косая черта. В base58 они опущены, для упрощения внешнего вида и корректности использования в качестве части URL.

Base58 и оплата по хэшу открытого ключа

Итак, как это связано с P2PKH? Все просто: адрес состоит из цифры 1, за которой следует хэш открытого ключа, записанный в системе base58.

Это информация, которую вы отправляете кому-то другому, когда хотите, чтобы он отправил вам биткоины. Вы также можете просто отправить им 0x00, а затем открытый ключ. И, возможно, они смогли бы это корректно интерпретировать, но вряд ли.

Пара шестнадцатеричных цифр с префиксом 0x часто используется для обозначения байтов, которые содержат 16 × 16 = 256 бит, поэтому это представляет один байт со значением 0.

Теоретически вы можете отправить кому-нибудь биткоин-скрипт в шестнадцатеричном формате, который используется в блокчейне, потому что это всего лишь двоичная информация. В блокчейне есть скрипт, который говорит: «Если у человека есть правильный хэш открытого ключа и открытый ключ, соответствующий этому хэшу открытого ключа, вы можете потратить эти монеты». Чтобы узнать больше о том, как работают биткойн-скрипты, обратитесь к главе 10.

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

Помимо использования base58 для отправки биткоин-адреса, вы также можете использовать его для передачи закрытого ключа. В таком сценарии первым символом оказывается 5, что соответствует 128. Затем следует закрытый ключ.

Раньше у пользователей часто были бумажные кошельки, которые они могли распечатать. И если они были сгенерированы надежно и без бэкдоров, то на одной стороне листа бумаги было что-то, начинающееся с 1, а на другой стороне что-то, начинающееся с 5. Предполагается, что только биткоин-адрес может быть показан посторонним, но закрытый ключ не должен разглашаться.

Существуют также адреса, начинающиеся с 3, которые предназначены для монет, обремененных хэшем скрипта, а не хэшем открытого ключа. Мы рассмотрим платеж по хэшу скрипта (P2SH) в главе 10. Обычно это адреса с несколькими подписями, но они также могут быть адресами SegWit.

Как объяснено в главе 3, SegWit обычно использует адреса bech32. Но потребовалось много времени, чтобы все кошельки и биржи начали поддерживать отправку на адреса bech32. Чтобы немедленно начать пользоваться некоторыми преимуществами SegWit, был введен тип адреса, который выглядит для отправителя как обычный P2SH, но содержит под капотом магию SegWit. Это называется адресом P2SH-P2WPKH: https://bitcoincore.org/en/segwit_wallet_dev/

Хотя адреса base58 работали нормально, их можно было улучшить. И это улучшение пришло в виде bech32.

А вот и Bech32

В марте 2017 года Питер Вьюлле предложил новый формат адреса, bech32, который используется с момента появления SegWit. Как следует из названия, это система base32, что означает, что у вас есть почти все буквы и почти все цифры, за исключением некоторых неоднозначных символов, которые не нужны, потому что они слишком похожи на другие цифры или буквы.

Одно из самых больших различий между bech32 и base58 заключается в том, что в новом формате нет комбинации прописных и строчных букв. Вместо этого каждая буква встречается там только в одном регистре — либо в верхнем, либо в нижнем — что значительно упрощает чтение вслух. Точное сопоставление того, какая буква или цифра соответствует какому значению, фиксировано, как и в base58, но произвольно: тот факт, что P означает 0, а Q означает 1, не имеет более глубокого значения.

Таблица символов Bech32. Например, q означает ноль, 3 означает 17 (1 + 16)

Адрес bech32 состоит из двух частей, разделенных символом "1", например, bc1q9kdcd08adkhg35r4g6nwu8ae4nkmsgp9vy00gf.

Первая часть намеренно удобочитаема для человека, например. «bc» (биткоин) или «lnbc» (сеть Лайтнинг на Биткоине). Конкретный смысл символов «b», «c» и т. д., не имеет значения. Скорее, они там для того, чтобы люди могли понять: «Хорошо, если адрес начинается с bc, то он относится к Биткоину как к валюте». Однако кошельки будут искать наличие этих символов в качестве проверки достоверности, и они включаются в контрольную сумму.

1 - это просто разделитель без значения. И если вы посмотрите на 32 числа в таблице, "1" там отсутствует — так что этот символ в адресе просто пропускается.

Вторая часть адреса начинается с номера версии SegWit. Версия 0 представлена Q (bc1q…) — см. главу 3. Версия 1 — это то, что мы называем Taproot (см. главу 5), так как она представлена буквой «P» (bc1p…). Для SegWit версии 0 за номером версии следуют либо 20, либо 32 байта, что означает либо хэш открытого ключа, либо хэш скрипта соответственно. И теперь они разной длины, потому что SegWit использует хеш-функцию SHA-256 (32 байта), а не RIPEMD160 (20 байт).

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

Итак, новизна заключается в том, что теперь алфавит содержит 32 символа, но в остальном все очень похоже на base58. Мы снова видим: «ОК, вот адрес P2PK». В данном случае это платеж по хэшу открытого ключа свидетельства (P2WPKH), где свидетельство относится к SegWit, но идея та же. Существует короткий префикс, который сообщает как человеку, так и компьютеру, о какого типа адресе речь, а за ним следует хэш открытого ключа или скрипта.

Игра в дартс в тридцати двух измерениях

Однако лаконичность здесь не единственное преимущество. Другой — исправление ошибок или, по крайней мере, их обнаружение.

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

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

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

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

Идея заключается в том, что вы хотите, чтобы круги были как можно больше, чтобы облегчить задачу даже самому небрежному метателю дротиков, но вы не хотите тратить слишком много места. Точно так же мы не хотим, чтобы биткоин-адреса состояли из сотен символов. Математики любят такие задачи оптимизации.

В случае с bech32 вместо двумерной стены нужно как-то представить себе 32-мерную «стену» с 32-мерными гиперсферами. Вы нажимаете на клавиатуру, и где-то в этом 32-мерном пространстве вы немного отклоняетесь, но вы все еще внутри этой гиперсферы, как бы она ни выглядела. В этом случае ваш кошелек знает, где ошибка, и не позволяет вам отправить монеты в эфир.

Простите за каламбур, но ранние кошельки Ethereum не использовали обнаружение ошибок, потому что в их стандарте адреса отсутствовала контрольная сумма. Хотя EIP 55 ввел такую контрольную сумму в 2016 году, не все кошельки ее применяли. Даже в конце 2017 года люди теряли монеты из-за опечаток: https://bitcointalk.org/index.php?topic=2161699.0

Но... есть проблема

В 2019 году было обнаружено, что если адрес bech32 заканчивается на P, то если вы случайно добавите к нему один или несколько Q, он все равно будет соответствовать контрольной сумме, и вам не сообщат об опечатке. В свою очередь, ваше программное обеспечение будет думать, что все правильно, вы будете отправлять деньги на неправильный адрес, и их нельзя будет потратить, как объяснялось выше.

Хорошая новость заключается в том, что bech32 использовался только для SegWit, а адреса SegWit ограничены по формату — они должны быть длиной либо 20, либо 32 байта. Так что, к счастью, если вы добавите еще один Q к 20- или 32-байтовому адресу, тогда его длина будет некорректной. Ваш кошелек обнаружит это и откажется отправлять монеты. Аналогичное ограничение по размеру рассматривалось для Taproot, но благодаря решению, которое будет приведено ниже, оно не понадобилось. Гибкая длина упрощает будущие усовершенствования Taproot.

Введение Bech32m

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

Новый стандарт используется только для адресов Taproot и тех, что еще могут быть введены в будущем. Для SegWit ничего не меняется, потому что он уже защищен ограничением длины в 20 или 32 байта. На момент написания статьи большинство программ для кошельков поддерживали новый стандарт bech32m.

Как я научился не волноваться и полюбил квантовые компьютеры

Помимо прочего, считалось, что метод оплаты по хэшу публичного ключа (P2PKH) лучше защищен против квантовых атак, потому что вам не нужно сообщать свой открытый ключ. Недостатком было то, что хеш занимал больше места в блоках, но тогда это не было проблемой, потому что блоки были далеко не заполнены.

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

Проблема в том, что, несмотря на широкое использование P2PKH, существует от 5 до 10 миллионов BTC, для которых уже известен открытый ключ. Ирония заключается в том, что, поскольку так много BTC уже уязвимо для квантовой кражи, нет смысла пытаться защитить остальные. Даже если ваши монеты не будут украдены, они обесценятся из-за обвала цен.

(Не)вероятность таких квантовых проблем в ближайшем будущем, а также возможные контрмеры объясняются в двух выпусках подкаста Что сделал Биткойн — с физиком Степаном Снигиревым и математиком Эндрю Поэлстрой.

Свободного места в блоках сейчас намного меньше, поэтому отсутствие необходимости помещать хэши открытых ключей в блоки сэкономило бы пользователям деньги на комиссии. Вот почему в новом софтфорке Taproot (см. часть 5) биткоин-адреса снова имеют формат P2PK(см. тут, и тут). Обратите внимание, что использование адресов Taproot не является обязательным, поэтому, если вы не согласны с приведенным выше рассуждением, вы можете просто отказаться от использования Taproot.

Поддержите проект!

Шлите ваши сатоши, используя эту LNURL ссылку с сообщением "НАДО"/"NADO"

Используя страничку,просто пользователю @c3p0rs через @lntxbot, либо [email protected] если ваш кошелёк поддерживает LN адреса.