October 3, 2022

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

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

Фото автора

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

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

Часть вторая: Использование ресурсов

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

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

Что мы можем с этим поделать?

Время синхронизации и AssumeUTXO

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

В этой главе будут рассмотрены некоторые постепенно добавленные (в протокол) способы ускорения синхронизации. Сначала она была улучшена за счет подхода Headers First, когда первым делом синхронизируются заголовки, и это гарантирует, что новые биткоин-узлы не будут тратить время на проверку (потенциально) более коротких цепочек. Одно из нескольких недавних улучшений, касающихся времени синхронизации, называется Assume Valid (предполагать валидность) — это установка по умолчанию, которая позволяет узлам пропускать проверку подписи старых транзакций, вместо этого полагаясь на то, что процесс разработки Bitcoin Core — в сочетании с ресурсоемким характером майнинга — обеспечивает надежную версию истории транзакций.

Также будет дано пояснение, как предположения безопасности, лежащие в основе презумпции валидности, могут быть расширены, чтобы обеспечить потенциальное будущее обновление AssumeUTXO (буквально, "предполагать UTXO"), чтобы предложить новым пользователям Bitcoin Core быстрое решение для ускорения работы в сети Биткоина путем синхронизации самых последних блоков в первую очередь, и проверки исторических блоков в фоновом режиме позже.

Помимо сопровождающего эту главу эпизода подкаста Bitcoin, Explained, вы также можете послушать эпизод The Chaincode Podcast с автором AssumeUTXO Джеймсом О'Бейрном, в котором рассматриваются те же темы, что и в этой главе.

Скачивание блокчейна

Когда вы запускаете свой биткоин-узел, он находит другие узлы и подключается к ним, как мы объясняли в главе 2. Затем он переходит к загрузке блокчейна.

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

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

По факту процесс был немного сложнее. Когда узел получал блок, который не находился напрямую на вершине цепочки, он, как выразился Сатоши в комментарии к исходному коду, «перенаправлял его в область хранения». Оттуда его можно было позже присоединить к концу цепи. Эти блоки назывались orphan blocks(сиротскими блоками), этот термин часто путают с stale blocks(устаревшими блоками).

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

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

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

Помимо атак увязания узлов в тупиковых ветках с блоками низкой сложности, существует также опасность eclipse атак (буквально, затмения), которые мы рассмотрим в главе 7.

Контрольные точки

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

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

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

Последняя контрольная точка была добавлена в конце 2014 года. Избавиться от потребности в контрольных точках удалось различными способами, включая введение nMinimumChainWork в 2016 году. Этот параметр указывает, сколько доказанной работы должна продемонстрировать любая цепочка заголовков, прежде чем получит право на рассмотрение. Но чтобы такое работало, узлы должны быть менее близорукими; им нужно сперва разглядеть, куда ведет данная цепочка блоков, прежде чем тратить много компьютерной мощности на ее изучение. И тут на помощь приходит Headers First.

Headers First

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

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

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

Assume Valid

Assume Valid — это хэш блока, закодированный в программном обеспечении. Точнее, это хэш блока непосредственно перед последним крупным релизом. Многие разработчики Bitcoin Core публично проверяют этот хэш, кто угодно может увидеть этот хэш на GitHub, и самостоятельно проверить, корректен ли он.

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

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

Что значит не проверять подписи для блоков перед хэшем Assume Valid? Это означает, что если кто-то украл монету, т.е. потратил UTXO с недействительной подписью, ваша нода этого не заметит. Но если кто-то создал монету из воздуха, ваша нода все равно ее увидит.

Именно здесь прозрачность исходного кода становится важным фактором. Если когда-нибудь произойдет кража монет, которую разработчики Bitcoin Core захотят скрыть, они смогут обмануть только новые узлы. Во-первых, разработчикам придется создать блок, который ворует монеты с использованием недействительной подписи. Такой блок будет считаться недействительным всеми существующими узлами. Затем они могли бы взять этот недействительный блок или его потомка, и использовать его хэш в качестве Assume Valid.

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

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

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

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

Но что, если разработчики, майнеры и все существующие пользователи сговорятся, чтобы обмануть новых пользователей? Такой заговор кажется невозможным тайно координировать. Но если вы беспокоитесь, что мир настроен против вас, будьте уверены, что вы можете отключить функцию Assume Valid, запустив свой узел с -assumevalid=0. Тогда ваша нода заметит недопустимый воровской блок, вы сами увидите его хэш в исходном коде и сможете выскочить на улицу, протестуя против этой ситуации.

Здесь важно понимать, что разработчики могли уже вступить в сговор против вас и внедрить в код что-то плохое — мы поговорим об этом подробнее в главе 9. Разработчики также могут установить бэкдор, который даст им доступ к вашим закрытым ключам. Собственно, это и произошло с альткоином под названием Lucky7Coin. Хэш Assume Valid, с другой стороны, очень хорошо виден, и для его проверки требуется очень мало навыков, как объяснялось выше. Вот почему разработчики Bitcoin Core считают, что эта функция защищена от злоупотреблений.

Assume Valid присутствует в Bitcoin Core с версии 0.14 (2017 г.), теперь же появилось новое предложение: AssumeUTXO.

AssumeUTXO

В начале 2019 года выходец из Chaincode Labs Джеймс О’Бейрн представил предложение AssumeUTXO, которое позволит пользователям быстрее закончить синхронизацию. Как упоминалось ранее в этой главе, набор UTXO — это набор монет, который существует прямо сейчас. Каждый раз, когда вы отправляете кому-то деньги, это создает UTXO и уничтожает UTXO, с которого вы их отправили. Это похоже на то, как будто у вас есть банковский счет, который закрывается, когда вы его используете, и вы открываете новый банковский счет для сдачи.

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

Из-за ошибки, или из-за большой доброжелательности Сатоши, узлы на самом деле не обрабатывают таким образом генезис-блок, поэтому самые из когда-либо созданных 50 BTC не могут быть потрачены.

https://en.bitcoin.it/wiki/Genesis_block

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

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

С Assume Valid узел по-прежнему выполнял построение набора UTXO и повторял все транзакции; он просто не проверял подписи. Теперь, с AssumeUTXO, он вообще пропускает воспроизведение транзакций или, точнее, откладывает это. Вместо этого он берет набор UTXO на высоте блока, соответствующей снимку, а затем обрабатывает все последующие блоки для воссоздания текущего набора UTXO.

Имеет ли значение прошлое?

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

Предположим, что вы новый пользователь. Первое, что вы хотите сделать, это получить монеты. Вы хотите быть уверены, что эти монеты позже будут приняты другими. И вы можете хотеть убедиться, что существует ограничение в 21 миллион BTC. Нужно ли вам проверять исторические блоки, чтобы понять это?

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

Однако, чтобы знать, примут ли в будущем другие монеты, которые вы получили, вам нужно узнать, что человек, который отправил вам монеты, не создал их из воздуха и не украл. Это отсылает нас к вопросу о том, сможет ли злонамеренный разработчик избежать наказания за это. Давайте посмотрим, как это можно сравнить с манипулированием Assume Valid.

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

Но там, где в приведенном выше примере с Assume Valid разработчикам пришлось бы сразу создавать недопустимый блок, прежде чем делать новый релиз ПО, здесь это не обязательно. Новые или украденные монеты будут существовать в вашем наборе UTXO, даже не будучи в блоке. Таким образом, майнеры и существующие операторы узлов изначально не обнаружат нестыковку, потому что вокруг не будет недопустимых блоков.

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

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

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

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

Один из способов предотвратить эту атаку — включить в каждый блок хэш текущего моментального снимка UTXO. Это будет софтфорк (см. главу 12). Таким образом, каждый узел будет проверять снимок, и его не нужно будет включать в программное обеспечение узла.

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

Вероятно, должно состояться много обсуждений, прежде чем подобный софт-форк произойдёт. На момент написания статьи AssumeUTXO все еще находился в разработке. Узлы уже могут создавать снимки своего набора UTXO, но код для загрузки и применения снимка все еще находится на рассмотрении.

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

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

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