Успехи в достижении целей технологии Utreexo

Аннотация. В этом материале получатель гранта 100x Group Келвин Ким рассматривает несколько потенциальных преимуществ решения Utreexo и степень реализации этих преимуществ. Келвин рассказывает о значительных успехах, достигнутых в последней версии Utreexo, а также объясняет, что разработчикам нужно проделать еще немало работы, прежде этой технологией смогут воспользоваться рядовые пользователи.

После выхода последней демо-версии в июле 2020 года мы говорили о том, что планируем внедрить аккумулятор Utreexo в btcd, существующую реализацию биткоина на языке Go. Я рад сообщить, что эта демо-версия Utreexo готовится к выпуску. В ней также появился новый облегченный режим «компактного узла» (Compact State Node, CSN).

В своей статье «ELI5: Utreexo – решение для масштабирования», опубликованной еще в апреле 2020 года, я писал о некоторых преимуществах, которые может обеспечить CSN, а именно:

  1. Это новый полный узел весом несколько килобайтов, в котором синхронизация данных происходит одинаково быстро на SDD и на HDD.
  2. Возможность распараллелить первоначальную загрузку блоков.
  3. Повышение безопасности в сети биткоина, так как консенсус не зависит от реализации базы данных (используемая в настоящее время база создана Google)
  4. Для подключения Utreexo к сети биткоина не нужны форки.

На текущем уровне разработки реализованы преимуществ 3 и 4. Преимущество 1 реализовано частично, так как уменьшение размера узла до нескольких килобайтов затрудняется данными, не относящимися к Utreexo. Преимущество 2 в настоящее время находится в стадии разработки.

Почему преимущество 3 важно

Повышение безопасности в сети биткоина, так как консенсус не зависит от реализации базы данных (используемая в настоящее время база создана Google).

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

В настоящее время самой большой внешней зависимостью является база данных, в которой хранится набор данных Unspent Transaction Output или набор данных [неизрасходованных выходов] UTXO и индексы блоков. База данных, которая используется в настоящее время, получена у Google и называется LevelDB. Отсутствие ошибок в LevelDB имеет критическое значение для безопасности сети биткоина. Ошибка в LevelDB может привести к двойному списанию или к образованию незапланированного форка. В 2013 году так и произошло: из-за ошибки в использовании Berkeley DB (предшественница LevelDB) в Bitcoin Core старые узлы Bitcoin Core не могли считать блок 225430, что привело к образованию незапланированного форка.

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

Реализация преимущества 3

Но зачем вообще нужна база данных? Дело в том, что набор данных UTXO (или UTXO-сет) состоит из более чем 60 миллионов UTXO (Unspent Transaction Outputs, нерастраченных выходов), и все они должны отслеживаться и быть быстро доступными, так как медленный доступ замедлит первоначальную загрузку блоков. В таких случаях, когда необходимо быстро получить доступ к большому количеству небольших данных, часто используется база данных.

Но в реализации CSN Utreexo база данных вообще не нужна. Вместо этого пользователь, который хочет потратить неизрасходованный биткоин, должен предоставить данные UTXO, а аккумулятор Utreexo — доказательство существования UTXO. Это избавляет нас от необходимости хранить набор данных UTXO в реализации CSN Utreexo. Так как нам не нужно хранить набор данных UTXO, мы можем удалить LevelDB из другой критически важной части консенсуса Bitcoin.

Вот как работает текущая проверка правильности (валидация) блока по сравнению с проверкой правильности блока в CSN Utreexo с точки зрения увеличения основной цепочки:

Текущая проверка подлинности блока

Проверка подлинности блока в CSN Utreexo

1. Проверка доказательства выполнения работы (proof of work)

1. Проверка доказательства выполнения работы (proof of work)

2. В отношении каждого входа: проверка существования соответствующего выхода в наборе данных UTXO (LevelDB)

2. Проверка подтверждения каждого UTXO в блоке в аккумуляторе и  проверка подлинности

3. Проверка подлинности скриптов и подписей по каждому входу

3. Проверка подлинности скриптов и подписей по каждому входу

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

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

Why Claim 4 is important

Почему преимущество 4 важно

Для подключения Utreexo к сети биткоина не нужны форки.

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

С другой стороны, если узел может просто включить новую функцию в формате opt-in (выбора), без форка, развернуть ее намного проще. Компактная передача блоков (BIP-152) — вот пример широко распространенной функции, не требующей форка. Узлы, которые выбирают функцию компактной передачи блоков, делают это по своему усмотрению, а поскольку эта функция является opt-in (т.е. необязательной), то для тех, кто не хочет ее использовать, ничего не меняется.

Реализация преимущества 4

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

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

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

Почему преимущество 1 важно

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

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

 Сейчас, когда биткоин-узлу попадаются в блоке данные UTXO, ему нужно извлечь эти данные UTXO, будь то с диска, или из кэша в памяти. Это одна из актуальных проблем в сети биткоина, особенно если у узла медленный диск. Для облегченных (т.н. «pruned», в которых удаляются старые блоки) узлов эта проблема стоит еще более остро, так как при удалении старых блоков кэшированные данные UTXO записываются на диск. Как следствие, облегченные узлы синхронизируются медленнее, чем необлегченные узлы, как заметил разработчик биткоина Питер Вюлле (Pieter Wuille) здесь.

Использование CSN Utreexo позволяет устранить это отставание, так как набор данных UTXO не нужно считывать с диска. Благодаря этому CSN Utreexo работает примерно одинаково с любым запоминающим устройство, будь то твердотельный накопитель (SSD) от NVMe или внешний жесткий диск (HDD).

Текущие успехи в реализации преимущества 1

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

Если сравнивать только размер данных chainstate с Bitcoin Core, ситуация выглядит так:

Как видим, размер chainstate в CSN Utreexo составляет всего 424 байта, и общий размер данных, которые получает узел, приходится округлять. Фактически, файл peers.json, используемый для переподключения к известным пирам при перезапуске, занял 205 килобайтов, что примерно в 483 раза больше размера данных chainstate.

Вот разница производительности облегченного узла в Bitcoin Core и CSN Utreexo при использовании твердотельного накопителя (SSD) NVMe и внешнего жесткого диска  (HDD).

Тест проводился методом направления проверяемого узла на другой локальный узел-мост Utreexo, который считывает данные с автономного твердотельного накопителя NVMe. В Bitcoin Core использовался параметр assumevalid для блока 1 864 000 в сети testnet3 по умолчанию. В CSN параметр assumevalid был реализован и применен к блоку 1 864 000. Тестирование проводилось до блока 1 906 000 в testnet3.

Использованное оборудование:

  • Процессор: AMD Ryzen 3600
  • Память: Samsung 32 Гб DDR4 2666 МГЦ
  • Локальный диск NVMe для обслуживания узла: 2TB Sandisk ULTRA M.2 NVMe
  • Диск NVMe для тестирования узла: 1TB HP SSD EX950 M.2
  • Внешний жесткий диск для тестирования узла: Western Digital WD10EZEX-22BN5A0 1TB 7200RPM

Поля данных, переданные узлу Bitcoin Core:

  • -prune=550
  • -connect=127.0.0.1
  • -disablewallet
  • -blocksonly 
  • -testnet

Запуск узла в Bitcoin Core на твердотельном накопителе NVMe занял 784 секунды, в то время как на жестком диске — 1066 секунд. Запуск узла в CSN Utreexo на твердотельном накопителе NVMe занял 1643 секунды, а на жестком диске — 1700 секунд.

Обратите внимание: текущая версия CSN Utreexo требует значительной оптимизации производительности. В настоящее время она работает медленнее, чем Bitcoin Core, так как мы образовали форк от btcd, узла, который намного медленнее Bitcoin Core. Мы готовим новый релиз и статью, где основное внимание будет уделено производительности.

Почему преимущество 2 важно

Возможность распараллелить первоначальную загрузку блоков

Чтобы избежать путаницы, в этой статье речь идет о распараллеливании на уровне цепочки. Это означает, что один узел одновременно проверяет правильность нескольких диапазонов блоков, например: 100 001~200 000 и 200 001~300 000. Мы не говорим о распараллеливании на уровне блоков, когда параллельно проверяются подписи транзакций в блоке (так как это уже реализовано и в btcd, и в Bitcoin Core).

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

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

Текущие успехи в реализации преимущества 2

Для проверки любого блока необходим набор данных UTXO предыдущего блока. Например, для проверки блока 501 нам нужен набор данных UTXO в блоке 500. Но для получения набора данных UTXO в блоке 500 нужен набор данных UTXO в блоке 499. Эта проблема зависимости от набора данных UTXO в предыдущем блоке тянется к генезис-блоку (в котором этот набор жестко закреплен). С этим и связана сложность распараллеливания на уровне цепочки.

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

Обратите внимание: пир может быть вредоносным и выдать ложное представление набора данных UTXO. Но это не меняет наше заявление о том, что этот метод повышает безопасность в сети, так как проверку цепочки от блока 499 до генезис-блока выполняют различные ядра процессора. Мы продолжаем проверку с блока 501 и далее, ведь иначе эти ядра все равно простаивали бы. Когда проверка цепочки от генезис-блока до блока 499 завершится, мы можем проверить блок, чтобы узнать, совпадают ли данные в последнем блоке и набор данных UTXO в блоке 500. Таким образом, жестко зафиксированные представления набора данных UTXO используются только в качестве подсказок для ускорения обработки, но при этом все равно проверяются.

Чтобы этот тип распараллеливания на уровне цепочки стал возможным, кодовая база должна поддерживать наличие нескольких активных баз данных chainstate. Главная проблема произвольного энного количества (или даже двух) баз данных chainstate заключается в необходимости отслеживать энное количество наборов данных UTXO. Поскольку для ускорения обработки набору данных UTXO нужна база данных и кэш набора данных UTXO на диске, это значительно повышает требования к оборудованию для эксплуатации узла. Но так как в CSN Utreexo устранена база данных для хранения наборов данных UTXO, это не проблема.

Версия для нескольких наборов данных chainstate (CChainState в ядре Bitcoin Core, тип Blockchain в btcd) уже находится в стадии реализации. В случае CSN Utreexo все гораздо проще, так как не нужно иметь базу данных для каждого набора chainstate. Это делает возможной реализацию любого энного количества наборов chainstate.

Мы все еще работаем над тем, как обрабатывать сообщения между пирами в сети по каждому набору chainstate. Мы пробуем различные методы (например, используем два диспетчера для первоначальной загрузки блоков; отслеживаем, какой набор chainstate запрашивал какие блоки и т. д.), но до завершения этой работы еще далеко.

Ограничения этой версии

В текущей версии отсутствует поддержка реорганизации цепочки и мемпулов. Поэтому узел работает в режиме «только блоки» и в случае реорганизации аварийно прекратит работу. Эти два аспекта еще не реализованы в библиотеке Utreexo, поэтому данная версия предназначена только для демонстрации. Этим релизом мы не поддерживаем мейннет биткоина, и его не следует использовать с реальными деньгами, так как технология все еще находится на ранней стадии разработки и содержит ошибки.

Что дальше?

Как упоминалось в пункте «Текущие успехи в реализации преимущества 1», мы продолжим оптимизировать производительность CSN Utreexo, а именно займемся ускорением как аккумулятора Utreexo, так и компонентов btcd. На данный момент нам известно о многих проблемах, устранение которых позволит ускорить CSN (это только вопрос реализации и тестирования).

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

Сейчас код аккумулятора Utreexo написан на языке Go. «Перевод» кода аккумулятора на Rust и C++ продолжается. Мы не знаем, сколько времени это займет, но основы уже готовы, и теперь работать над кодом можно параллельно. Словом, если вы хотите поучаствовать, обращайтесь, — работа всегда найдется.