Опубликован: 12.08.2019 | Доступ: свободный | Студентов: 415 / 113 | Длительность: 11:31:00
Лекция 4:

Сетевая архитектура платформы Биткоин

< Лекция 3 || Лекция 4 || Лекция 5 >
Аннотация: Данный раздел посвящен ключевой технологии для сети Биткоин - пиринговым сетям, подразумевающим равноправие всех участников. Рассматриваются роли, выполняемые различными нодами. Приводятся основные сведения относительно подключения ноды к сети. Описывается собственная широковещательная аварийная система сети Биткоин. Цель: Досконально разобрать все аспекты, касающиеся протоколов взаимодействия узлов в рамках сети Биткоин, определить возможные роли, выполняемые различными узлами в процессах обеспечения функционирования и безопасности криптоплатформы.

Классификация нод

Цель: Сформировать представление о сути и задачах, выполняемых различными узлами сети Биткоин.

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

Понятие "платформа Биткоин" относится к сети нод, работающих под управлением протокола Биткоин P2P. Кроме P2P-протоколов поддерживаются и другие протоколы, например, Stratum или BetterHash, использующиеся в майнинговых системах или мобильных кошельках. Для взаимодействия с базовой платформой дополнительные протоколы используют специальные шлюзы. В случае интеграции большого числа систем и протоколов мы можем говорить о расширенной сети Биткоин.

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

Полнофункциональная нода (см. Рисунок 4.1) одновременно работает как маршрутизатор, кошелек, устройство хранения и синхронизации распределенного реестра (полной версии), система майнинга.

Полнофункциональная нода

Рис. 4.1. Полнофункциональная нода

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

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

Часть узлов работает только с урезанным подмножеством реестра. Для проверки транзакций они прибегают к процедуре упрощенной проверке платежа (SPV, simplified payment verification). Поэтому они называются легкими или SPV-нодами. Фактически облегченная нода реализует ограниченный набор наиболее важных проверок, в отличие от полного узла сети.

SPV-нода не получает блоки целиком, как это происходит в случае полного узла. Ей доступны только заголовки блоков, имеющие существенно меньший размер (один заголовок = 80 байт). Заголовок содержит достаточно информации для того, чтобы подтвердить факт успешной валидации некоторой транзакции из данного блока. Техническая реализация использует свойства дерева Меркла, на основе которых можно определить наличие хеш-функции конкретной транзакции в сложной иерархической структуре, не имея при этом данных остальных транзакций блока. Как известно, в заголовке каждого блока имеется поле для хранения корня дерева Меркла. По сути это хеш всех вошедших в блок транзакций, рассчитанный по специальной древовидной схеме.

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

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

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

SPV-ноды особенно требовательны к надежности и стабильности сетевых соединений. Однако, технология облегченных кошельков часто используется даже в мобильных приложениях. Целый ряд популярных кошельков реализует механизм синхронизации с сетью Биткоин, в том числе: Bitcoin Wallet; Electrum; Bread Wallet.

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

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

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

Ниже показаны основные варианты сочетания ролей в абстрактной ноде сети Биткоин.

Полнофункциональная нода. Эталонный клиент Bitcoin Core. Выполняет все четыре роли.
Одиночный майнер, использующий полную версию блокчейна.
Полная нода. Поддерживает полную и актуальную копию блокчейна.
Легкий или SPV-кошелек (нода).
Легкий или SPV-кошелек (нода), подключаемый к сети через специализированный шлюз (например, по протоколу Stratum).
Майнер, работающий в составе майнинг-пула. Подключение к майнинг-серверу осуществляется через специализированный шлюз (например, по протоколам Stratum или BetterHash).

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

Подключение к сети

Цель: Сформировать представление о технических аспектах взаимодействия узлов сети Биткоин.

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

Определившись с узлом-контрагентом, нода устанавливает обычное TCP-соединение, как правило, через порт номер 8333. Как известно, для этого стеком протоколов TCP/IP предусмотрена процедура тройного рукопожатия (англ. handshake). В начале сессии нода путем передачи сообщения version доводит до контрагента основную идентификационную информацию, приведенную в таблице 4.1.

Таблица 4.1. Параметры процедуры открытия сессии между двумя нодами
Параметр Описание
PROTOCOL_VERSION Константа, идентифицирующая версию протокола peer-to-peer, воспринимаемая любым клиентом сети Биткоин
nLocalServices Список локальных сервисов, поддерживаемых нодой. Сейчас это только NODE_NETWORK
nTime Системное время
addrYou IP-адрес узла-контрагента
addrMe IP-адрес рассматриваемой ноды
subver Версия релиза программного обеспечения этой ноды, например, Satoshi-0.10.2
BestHeight Высота блокчейна ноды

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

PushMessage("version",PROTOCOL_VERSION,nLocalServices,nTime,addrYou,addrMe, nLocalHostNonce,FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector<string>()),nBestHeight,true);

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

Таким образом узлы идентифицируют друг друга в сети.

Но пока остался открытым вопрос - как новые ноды находят своих партнеров-соседей? В настоящее время используются два основных способа.

Первая стратегия заключается в использовании сервиса глобального поиска – DNS. В сети постоянно присутствует некоторое число DNS-серверов, поддерживающих список IP-адресов Биткоин-узлов. Большая часть из них работает под управлением модифицированной BIND (Berkeley Internet Name Domain) – самой распространенной реализации DNS-сервера. Такие серверы, отвечая на очередной запрос ноды, возвращают случайную выборку из поддерживаемого списка IP-адресов Биткоин-узлов. В программном обеспечении эталонного клиента Bitcoin Core прошиты адреса пяти различных DNS-серверов.

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

Большинство кошельков реализуют два способа ручной установки соединений:

В окне консоли отладки приложения (в большинстве кошельков соответствующая команда будет выглядеть следующим образом: addnode 93.10.154.77 add ).

В файле конфигурации приложения (новые узлы добавляются путем вставки в файл с расширением .conf строк вида: addnode=208.65.110.77: 8333 ).

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

После открытия одной или нескольких сессий, новая нода посылает сообщение addr с собственной идентификационной информацией (IP-адрес) своим соседям. Те, в свою очередь, ретранслируют полученное сообщение своему окружению. В результате достаточно быстро новая нода приобретет "хорошую известность" среди узлов сети Биткоин.

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

Любой узел в сети Биткоин не должен заниматься самоизоляцией, ограничивая список своих контактов некоторым числом доверенных нод (хотя чисто технически такая возможность имеется). Это не практично хотя бы из тех соображений, что мир постоянно меняется – ноды приходят и уходят и работать все время с одними и теми же просто не получится. Но самое главное – такая стратегия нарушает принцип децентрализации сети. А это уже очень серьезно. Поскольку под вопросом оказывается эффективность гаранта надежности и безопасности платформы Биткоин.

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

На самом деле нода хранит не только перечень всех известных ей на данный момент IP-адресов других узлов сети Биткоин. С каждым партнером из этого списка связывается определенных набор данных: дата и время последней активности узла в сети; число успешных соединений и др.

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

Полные ноды

Цель: Сформировать представление о сути и задачах, выполняемых полными нодами в сети Биткоин.

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

Известно несколько технических решений, реализующих функционал полной ноды платформы Биткоин. Однако, до сих пор самым распространенным является эталонный клиент Bitcoin Core, также известный как клиент Satoshi. На долю различных клонов этого приложения приходится более 90% всех клиентов узлов платформы.

Любая полная нода в момент активации работы стремится построить всю структуру данных блокчейна. Если такая нода только что была создана, ей доступен только генезис-блок под номером 0, прошитый в программном коде биткоин-клиента. Для синхронизации с платформой такой ноде придется скачать все подтвержденные блоки цепочки (на начало марта 2019 года их число составляло более 565 300 единиц, общим объемом более 241 GB).

Синхронизация полной ноды с платформой Биткоин начинается после отправки сообщения version, содержащего параметр BestHeight – высота локального блокчейна (количеств блоков) ноды. Получая аналогичные сообщения в ответ, нода может сравнить высоту локального блокчейна с числом блоков в реестрах, хранящихся на узлах соседей.

Узлы, хранящие локальные копии блокчейна, постоянно обмениваются сообщениями getblocks, включающими среди прочих параметров хеш верхнего блока имеющегося в их распоряжении реестра. Если одна из нод обнаруживает, что полученный хеш относится к блоку, лежащему ниже указателя на вершину, то у нее есть все основания считать, что узел-партнер хранит более короткую копию блокчейна, и обе версии реестров необходимо выровнять. Нода, обладающая более длинным блокчейном, способна определить, какие блоки отсутствуют у второго узла. Для первых пяти сотен таких блоков рассчитываются хеши и передаются нуждающемуся узлу посредством сообщения inv. После чего узел, синхронизирующий свою копию блокчейна, начинает запрашивать полную информацию блоков с помощью достаточного числа сообщений getdata. Полученные ранее хеши блоков используются в целях идентификации получаемых, в общем случае, по разным маршрутам (с разными задержками) данных.

Рассмотрим подробнее случай только что созданного узла, претендующего на роль полной ноды, но пока обладающего только генезис-блоком. После того как это выяснят другие узлы, в его адрес будет направлено сообщение inv, содержащее хеши очередных 500 блоков в цепочке. Затем начинается довольно сложная процедура скачивания первой части блокчейна. Нода формирует запросы на требуемые блоки и рассылает их максимально возможному числу активных узлов. Отдающие блоки узлы не должны быть перегружены подобными требованиями, поэтому нода динамически распределяет нагрузку между ними. Необходимо отслеживать сколько затребованных блоков передается в текущий момент по каждому из открытых каналов (их количество не должно превышать предельную величину MAX_BLOCKS_IN_TRANSIT _PER_PEER). Это означает, что новые блоки в целях выравнивая сетевого трафика будут запрашиваться только после получения переданных ранее. Параллельно с этим полученные нодой блоки формируют структуру локального блокчейна. Указанные действия итеративно повторяются до тех пор, пока локальная копия блокчейна новой ноды не сравняется по высоте с версиями реестров, хранимых окружающими узлами.

Подобные процессы синхронизации блокчейна совершенно естественны для полных нод, поскольку они не могут постоянно находиться в режиме онлайн. Весь вопрос в том насколько долго продлится отсутствие ноды в сети. Если недолго, для "починки" блокчейна понадобится скачать всего несколько блоков. А вот суточный простой выльется в недостачу примерно 150-ти блоков.

Предупреждения

Цель: Сформировать представление о сути и задачах, выполняемых широковещательной аварийной системой сети Биткоин.

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

Технически оповещения распространяются при помощи сообщения alert, предусматривающего несколько параметров:

  • ID – идентификатор, используемый для исключения дублирующих сообщений;
  • Expiration – время актуальности сообщения;
  • RelayUntil – время транслирования сообщения по сети;
  • MinVer, MaxVer - версии протокола Биткоин, релевантные для данного сообщения;
  • subVer - версия клиента, который должен принять сообщение;
  • Priority – приоритетность сообщения, в настоящее время не применяется.

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

В эталонном клиенте Bitcoin Core для настройки системы оповещения предусмотрен параметр командной строки alertnotify. С его помощью можно выбрать команду, которая будет выполнена в случае доставки аварийного предупреждения. Обычно – это отправка электронной почты владельцу узла.

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

Краткие итоги

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

Понятие "платформа Биткоин" относится к сети нод, работающих под управлением протокола Биткоин P2P. Кроме P2P-протоколов поддерживаются и другие протоколы, например, Stratum или BetterHash, использующиеся в майнинговых системах или мобильных кошельках.

Несмотря на одноранговый характер сети Биткоин (все узлы равноправны), ноды могут выполнять различные роли: полнофункциональная нода-эталонный клиент Bitcoin Core; SPV-нода; одиночный майнер, использующий полную версию блокчейна; полная нода (поддерживает полную и актуальную копию блокчейна); легкий или SPV-кошелек; Легкий или SPV-кошелек, подключаемый к сети через специализированный шлюз (например, по протоколу Stratum); майнер, работающий в составе майнинг-пула.

Прежде чем начать принимать от других нод транзакции и передавать им свои, узел должен найти в сети Интернет другие ноды и установить с ними каналы для информационного обмена в виде обычного TCP-соединения, как правило, через порт номер 8333. Для этого стеком протоколов TCP/IP предусмотрена процедура тройного рукопожатия.

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

< Лекция 3 || Лекция 4 || Лекция 5 >
Юрий Гоголев
Юрий Гоголев
Россия, Тула, ТулГУ, 2002
Дмитрий Горский
Дмитрий Горский
Россия, Ростов-на-Дону, РГЭУ РИНХ, 2006