Хранение данных

Конфигурация блокчейна

Единый onchain-конфиг сети (`BlockchainConfig`) — устройство словаря параметров и типизированный/сырой доступ к нему, физическое место конфига внутри состояния мастерчейна и краткий обзор остальных номеров словаря.

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

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

Словарь параметров

У параметров конфигурации сети одна форма хранения: словарь «номер параметра → ячейка со значением». Структура BlockchainConfig состоит из двух полей: address — адрес конфигурационного контракта в мастерчейне, и params: тот же словарь, обёрнутый в BlockchainConfigParams и устроенный как Dict<u32, Cell>. Ключом в нём служит номер параметра, а значением выступает отдельная ячейка с его содержимым: в TL-B ячейка кладётся ссылкой, поэтому каждый параметр живёт в собственной ячейке, а не инлайном в листе словаря. Другой формы для «настроек сети» не существует: любой параметр конфигурации хранится именно так. Геттеры параметров вызываются прямо на BlockchainConfig, без обращения к вложенному полю.

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

Доступ к параметрам

Типизированный доступ

Знать заранее тип значения для конкретного номера не нужно: каждый известный параметр в tycho-types объявлен маркерным типом (ConfigParam0, ConfigParam1, … ConfigParam100), который задаёт номер параметра, тип его значения и способ чтения ячейки. Дженерик-методы получения, записи и проверки наличия параметра работают через эти маркерные типы. Чтение берёт сырой слайс по номеру и разбирает его по указанному типу. Запись собирает ячейку и кладёт её в словарь по тому же номеру. Реестр охватывает не подряд идущие номера, а конкретный набор: 0–25, 28, 29, 30, 31, 32–37, 43, 50, 100 — у параметров вне этого набора типизированного представления нет.

Поверх словаря есть 26 именованных геттеров, например get_elector_address или get_global_version, но они покрывают не все типизированные параметры. Такой геттер превращает отсутствие параметра в словаре в ошибку, а не в пустое значение. Геттеры предыдущего и следующего наборов валидаторов — исключение: для них отсутствие параметра законно. Часть геттеров устроена как пара с приоритетом: сначала читается один номер, а если он отсутствует, то читается другой. Так адрес минтера при отсутствии своего номера подменяется адресом конфигурационного контракта, а адрес сборщика комиссий подменяется адресом электора. «Временная» версия набора валидаторов, если она есть, всегда перекрывает постоянную. У этих сеттеров такого перехода на запасной номер нет: set_minter_address всегда пишет параметр 2, а set_fee_collector_address — параметр 3. У наборов валидаторов типизированных сеттеров нет вовсе: их меняет не узел, а выборный механизм состояния.

Сырой доступ

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

Где лежит конфиг

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

Узел получает конфиг только из уже загруженного состояния: метод, отдающий конфиг, читает поле config из дополнительного содержимого состояния и завершается ошибкой, если состояние не мастерчейновое. У хранилища узла нет отдельного API «прочитать параметр конфига»: чтобы узнать значение параметра, нужно загрузить состояние мастерчейна. Поправить конфиг локально нельзя: запрос на изменение параметра — это внешнее сообщение конфигурационному контракту, а не настройка узла.

Остальные параметры словаря

Оставшиеся номера словаря распределены по смысловым группам:

  • 0–4 и 31 — адреса системных контрактов мастерчейна: конфигурационного контракта, электора, минтера, сборщика комиссий, корня DNS и списка «фундаментальных» адресов.
  • 9, 10 и 11 — правила изменения самого конфига: какие параметры обязательны, какие критические, и регламент голосования за предложения.
  • 8, 19 и 12 — идентичность сети: минимальная поддерживаемая версия блоков с флагами возможностей протокола, глобальный идентификатор сети и описание каждой рабочей цепочки.
  • 5, 7, 14 и 50 — денежная часть: сжигание комиссий, целевые объёмы эмиссии дополнительных валют, награды за создание блоков и разовая эмиссия для L2.
  • 15–17 и 32–37 — валидаторская часть: правила выборов (длительность раунда, лимиты числа валидаторов, требования к стейку) и шесть слотов под сами наборы валидаторов, предыдущий, текущий и следующий, каждый в постоянной и временной версии.
  • 18, 20–25 и 43 — цены и лимиты исполнения: цена хранения данных аккаунта (один параметр, но с отдельными тарифами для мастерчейна и для рабочей цепочки внутри), газ, лимиты блока и цены пересылки сообщений (все три заданы парами «мастерчейн / прочие рабочие цепочки»), а также общий на всю сеть параметр предельных размеров.
  • 28 и 29 — тонкие настройки коллации (CollationConfig) и DAG-консенсуса (ConsensusConfig), одинаковые для всех валидаторов сети.
  • 100 — метки полномочий: кто вправе их ставить и какими дополнительными валютами они выражены.

Пополевое устройство этих структур — тема будущих статей доменов Collator, Consensus и Execution. Здесь фиксируется только то, за что отвечает каждый номер словаря.