На GitHub проекта Ethereum появились ответы на частные вопросы по Шардингу сети. С опорой на эту статью мы расскажем основные моменты масштабирования Эфириума.
Читайте в статье
- Шардинг Эфириума простыми словами
- Углубленный уровень
- Тривиальные, но безрезультатные способы масштабирования
- Почему масштабируемость — проблема, о которой все говорят?
- Простые, но неполные способы
- Почему отклоняются другие стратегии
- Как Plasma, каналы состояний и другие технологии уровня 2 вписываются в триллему?
- Основная идея шардинга
- Базовый дизайн
- Открытые вопросы шардинга Эфириум
- Сообщение между шардами
- Парадокс «Поезд-и-Гостиница»
- Можно ли передавать состояние криптографическим способом?
Самыми простыми словами, шардинг заставляет транзакции делиться на «осколки» (на английском shard). Каждый узел в сети обрабатывает не весь блок, а его составляющие. Это позволяет обрабатывать транзакции быстрее и масштабировать сеть.
Термин взят из работ с базами данных, которые распределено хранят информацию (например на основе того, из какой вы страны, ваши данные могут быть расположены в ближайшем к вам дата-центре). Для Эфириум последние спецификации и точная модель еще разрабатываются.
Осколки не будут константной. Протокол имеет встроенный процесс балансировки нагрузки, который перемещает объекты между шардами (осколками):
- если шард становится слишком большим или требует слишком много газа, его можно разделить пополам;
- если два осколка становятся слишком маленькими и часто сообщаются друг с другом, их можно комбинировать;
- если все осколки становятся слишком маленькими, один осколок может быть удален, а его содержимое перемещено в другие осколки и т. д.
Углубленный уровень
Если вы не слишком подкованы в теме, вот заранее несколько определений:
Нода, узел — это компьютер в сети с клиентом блокчейна,
Состояние — это весь блокчейн на последний момент времени, текущее состояние блокчейна должно синхронизироваться между нодами.
История — упорядоченный список всех транзакций, которые произошли после генезиса. В простой модели «настоящее состояние» должно быть детерминированной функцией состояния генезиса и истории.
Функция перехода состояния — функция, которая принимает состояние, применяет транзакцию и выводит новое состояние. При этом вычисление может включать добавление и вычитание остатков на счетах, указанных в транзакции, проверку цифровых подписей и код контракта.
Дерево Меркла — криптографическая структура хеш-дерева, которая может хранить большой объем данных. В Ethereum набор транзакций каждого блока, а также состояние хранится в дереве Merkle, где корни привязаны к блоку.
Тривиальные, но безрезультатные способы масштабирования
Существуют три основные категории «простых решений».
- Отказаться от масштабирования отдельных блокчейнов и вместо этого предположить, что пользователи будут использовать множество разных «альткоинов». Это значительно увеличивает пропускную способность, но ограничивает уровень безопасности: увеличение сети на N уменьшает безопасность на N. Следовательно, это нежизнеспособно для незначительных значений N.
- Просто увеличить размер блока. В некоторых ситуациях является правильным выбором, поскольку размеры блоков могут быть ограничены политикой, а не техническими соображениями. Но такой подход неизбежно имеет свои пределы: если зайти слишком далеко, то узлы, работающие на пользовательском оборудовании, будут отказывать. Тогда сеть начнет полагаться исключительно на небольшое количество суперкомпьютеров, что может привести к риску централизации.
- «Слияние майнинга» — это техника, в которой есть много цепей, но все сети имеют одну и ту же мощность добычи (или, в PoS, долю). В настоящее время Namecoin работает так с блокчейном BTC. Если все майнеры участвуют, это теоретически может увеличить пропускную способность в N раз без ущерба для безопасности. Однако тут возникают проблемы.
- Решение увеличивает вычислительную нагрузку на каждый майнер в коэффициенте N. Поэтому на самом деле это решение является просто скрытой формой увеличения размера блока.
- Также цепи не связаны по-настоящему: требуется лишь небольшое количество экономических стимулов, чтобы убедить майнеров отказаться или поставить под угрозу одну конкретную цепь.
- Если только несколько пулов участвуют в каждом слиянии блокчейнов, тогда существует неизбежный риск централизации.
Почему масштабируемость — проблема, о которой все говорят?
Касательно масштабируемости есть трилемма. Она звучит так: система на блокчейне может иметь только два из следующих трех свойств:
- децентрализация (система может работать в сценарии, где каждый участник имеет доступ только к ресурсам O(c), то есть к обычным ноутбукам или виртуальным серверам),
- масштабируемость (возможность обработки транзакций O(n)>O (c)),
- безопасность (защита от злоумышленников с использованием ресурсов O (n)).
O — сложность. В остальной части статьи мы продолжим использовать c, чтобы обозначать размер вычислительных ресурсов (включая вычисления, пропускную способность и память), доступных каждому узлу, и n как размер экосистемы в абстрактном смысле. Транзакционная нагрузка, размер состояния и рыночная капитализация криптовалюты все пропорциональны n.
Некоторые утверждают, что по закону Меткалфа (ценность сети равна количеству пользователей в квадрате) рыночная капитализация криптовалюты должна быть пропорциональна n в степени 2, а не n. По Бутерину, это не так.
Простые, но неполные способы
Многие предложения по шардам (например, недавнее применение подобных идей в Zilliqa, а также подход Merklix tree1, предложенный для биткоинов) предполагают:
- либо только шард-транзакции,
- либо только шард-состояние.
Эти усилия приводят к повышению эффективности, но сталкиваются с фундаментальной проблемой: они решают только одно из двух узких мест. Мы хотим обрабатывать более 10 000 транзакций в секунду, без ноды равной суперкомпьютеру или без ноды, которой приходится качать терабайт данных состояния.
Для этого требуются изменения на уровне P2P (от пользователя к пользователю), поскольку широковещательные каналы не масштабируются, так как для каждого узла требуется загрузка и повторная передача O(n) данных (для каждой транзакции, которая отправляется), тогда как в нашем критерии децентрализации предполагается, что каждый узел имеет доступ только к O(c) ресурсам.
Почему отклоняются другие стратегии
Стратегии на основе каналов (сеть Lightning, Raiden и т. l.) могут масштабировать количество транзакций с постоянным коэффициентом, но не могут масштабировать хранилище состояние. Плюс, они используются с ограничениями и допущениями, в частности, подвержены DDos-атакам. Масштабирование через шардинг и масштабирование оффчейн через каналы, возможно, дополняют друг друга.
То же справедливо сказать про решение Bitcoin-NG.
Существуют подходы, которые используют передовую криптографию, такую как Mimblewimble и стратегии на основе ZK-SNARK. Они решают одну задачу — начальная полная синхронизация узлов. Вместо того, чтобы проверять всю историю из генезиса, узлы могут проверить криптографическое доказательство того, что текущее состояние справедливо следует из истории.
Но ни одно из решений не делает ничего, чтобы нивелировать рост размера состояния или пределы обработки онлайн-транзакций.
Как Plasma, каналы состояний и другие технологии уровня 2 вписываются в триллему?
В случае большой атаки на подцепи Plasma, все пользователи дочерних цепей должны будут вернуться обратно в корневую цепь.
- Если у Plasma есть пользователи O(n), для этого потребуются O(n) транзакций и, следовательно, O(n/c) время для обработки всех выводов.
- Если задержки на вывод фиксированы до некоторого D, то, как только N > C*D, в блокчейне будет недостаточно места для обработки всех выводов вовремя.
Поэтому система будет небезопасной.
Плазму следует рассматривать как увеличение масштабируемости только на определенную константу.
Если задержки выводов будут гибкими и смогут автоматически расширяться, это будет небезопасно. Например, если идет много выводов, это означает, что по мере увеличения N увеличивается время. Это продолжительное время можно использовать для атаки на средства, и поэтому уровень «безопасности» системы все уменьшается.
Плазма направлена на решение других проблем.
Каналы состояния имеют схожие свойства, хотя и с различными компромиссами между универсальностью и скоростью. Другие технологии уровня 2 включают интерактивную проверку исполнения TrueBit и Raiden.
Доказательство доли с введением Каспера также улучшило бы масштабирование —оно более децентрализуемо, не требует мощного компьютера.
Шардинг отличается от каналов состояния и Плазмы тем, что периодически псевдослучайно назначаются нотариусы, которые голосуют касательно правильности сопоставлений (термин сопоставление известен также как коллация). Если сопоставлено правильно, это принимается в основную цепочку после проверки голосов. Осуществляется через заключение контракта на основном блокчейне. В фазе 5 (см. Дорожную карту Шардинга Эфириума) шарды связаны с основной цепью, так что если какой-либо шард или основная цепь недействительны, вся сеть недействительна.
Существуют и другие различия между названными механизмами. Но главное, что и Плазма, и каналы состояния могут не поддерживать связь с блокчейном неопределенное время. А шарды связаны с блокчейном через консенсус в протоколе.
Основная идея шардинга
Мы разбиваем состояние и историю на разделы K=O(n / c), которые называем «осколки», или «шарды».
Например, шардинг-схема Ethereum может поместить все адреса, начиная с 0x00 в один шард, все адреса, начинающиеся с 0x01, в другой шард и так далее.
В простейшей форме шардинга каждый осколок также имеет свою собственную историю транзакций, а эффект транзакций в некотором осколке k ограничен состоянием осколка k.
Простой пример — блокчейн с несколькими активами. Есть K осколков, каждый из них хранит балансы и обрабатывает транзакции, связанные с одним активом.
В более продвинутых формах шардинга используется какая-либо форма взаимодействия между шардами, когда транзакции в одной части могут инициировать события в других частях.
Базовый дизайн
Существуют узлы, которые называются инициаторами (proposers).
- Они соглашаются с k-шардами (в зависимости от протокола, пропозеры либо выбирают k, либо случайно назначают k),
- и создают сопоставления (коллации), таким образом, они действуют как collator (инструмент для сопоставления).
- узлы могут быть и пропозерами, и коллаторами одновременно — пролакторами.
Для сопоставления используется короткое сообщение в заголовке.
Соединенные шарды образуют цепочку точно так же, как блоки в традиционном блокчейне.
Также существуют нотариусы (notaries), которые загружают шарды и проверяют коллации. Затем они могут голосовать за доступность данных при сопоставлении (при отсутствии EVM, с EVM они могут также выступать в роли исполнителя и голосовать за достоверность данных).
Комитет (committee) тоже может проверить голоса нотариусов и решить, включать ли заголовок в основную цепь, тем самым создавая перекрестную ссылку на сортировку в осколке.
Структура сейчас рассматривается такая:
Протокол может разделить валидаторов на три группы с разными стимулами:
- пролаторы (только строят цепь сопоставлений без обращения к состоянию)
- норатирусы (проверяют, доступны ли данные)
- исполнители (берут цепь сопоставлений, выполняют транзакции, вычисляют состояние).
«Основная цепочка», загруженная всеми, все еще существует, но роль этой главной цепи ограничена хранением заголовков коллаций для всех шардов.
«Каноническая цепь» для шарда k — самая длинная цепь с подтвержденным сопоставлением, все заголовки которой находятся внутри канонической основной цепи.
В настоящее время существует несколько «уровней» узлов, которые могут существовать в такой системе:
- Суперполный узел — полностью загружает каждое сопоставление каждого шарда, а также основную цепь, полностью проверяет все.
- Узел верхнего уровня — обрабатывает все основные блоки цепи, предоставляет доступ ко всем шардам через «легкий клиент».
- «Одношардовый узел» (Single-shard node) — выступает в качестве узла верхнего уровня, но также полностью загружает и проверяет каждое сопоставление на каком-то определенном шарде.
- Легкий узел — загружает и проверяет только заголовки блоков только основных блоков.
Открытые вопросы шардинга Эфириум
Атаки с применением однократного шарда — если атакующий
- представляет большинство нотариусов или пролакторов в одном шарде,
- либо препятствует тому, чтобы какие-либо сопоставления получали достаточное количество подписей,
- или отправляет недостоверные сопоставления.
Выполнение состояния транзакции — атаки с использованием однократного шарда обычно предотвращаются с помощью случайной выборки, но такие схемы также затрудняют вычисление корня состояния. Нельзя получить обновленную информацию о состоянии для каждого шарда. Поэтому мы не можем гарантировать, что легкие клиенты могут получат точную информацию о состоянии. Как это сделать?
Обнаружение мошенничества — если сделано недопустимое сопоставление или состояние, как можно надежно информировать узлы (включая легкие клиенты) об этом? Так, чтобы они могли обнаружить мошенничество и отклонить сопоставление, если оно действительно нарушает правила.
Перекрестная связь с шардами — вышеупомянутая конструкция не поддерживает перекрестную связь. Как добавить безопасную перекрестную связь?
Суперквадратичный шардинг — в частном случае, когда n> c^2, <…>требуется более двух уровней связи между транзакциями и заголовками блоков верхнего уровня (т. е. нужны «шарды шардов»). Какой самый простой и лучший способ сделать это?
Эффект транзакции может зависеть от событий, которые раньше были в других шардах. Пример с переводом денег:
деньги переводятся с шарда I на шард J. Тогда сначала создается дебетовая транзакция, которая уничтожает монеты в I, а затем создается кредитная транзакция, которая создает монеты в шарде J. Отмечается история предыдущей транзакции, что доказывает, что монеты получены законно. Это делается в квитанции.
Модели безопасности для сети Эфириум сейчас обсуждаются.
Сообщение между шардами
Самый простой сценарий: очень много приложений, которые сами по себе не имеют большого количества пользователей и которые редко взаимодействуют друг с другом. В этом случае приложения могут работать на отдельных шардах и использовать связь через квитанции.
Шаги выглядят следующим образом (подходит для примера выше из предыдущего раздела):
- Отправьте транзакцию через шард М, который 1) вычитает из остатка А 100 монет и 2) создает квитанцию. Квитанция — это объект, который не сохраняется в состоянии напрямую, но факт, что квитанция была сгенерирована, может быть проверен с помощью доказательства Merkle.
- Подождите, пока первая транзакция будет добавлена.
- Отправьте транзакцию на шард N вместе с подтверждением Merkle для квитанции из пункта 1. При правильном раскладе, транзакция увеличивает баланс B на 100 монет и сохраняет это в состоянии.
- Опционально, транзакция из пункта 3 также сохраняет квитанцию, которая затем может быть использована для выполнения дальнейших действий на шарде М.
В более сложных формах шардинга транзакции могут иметь эффекты, которые распространяются по нескольким шардам, а также могут синхронно запрашивать данные из состояний множества «осколков».
Парадокс «Поезд-и-Гостиница»
Предположим, что кто-то хочет купить билет на поезд и зарезервировать отель, и хочет убедиться, что операция атомарна.
Атомарность = неделимость.
Либо оба бронирования завершены успешно, либо ни одно не делается. Если заказ на билеты и на бронирование в отеле в одном шарде, это легко: создать транзакцию, которая проходит с этими оговорками. Если какое-то бронирование не удается завершить, деньги возвращаются.
Однако, если они находятся на разных шардах, это не так просто. Даже без децентрализации это проблема.
Только с асинхронными сообщениями самое простое решение — сначала зарезервировать поезд, а затем зарезервировать отель, после чего успешность операции подтвердят две стороны.
Механизм опирается на соображения безопасности: перекрестные сообщения из одного шарда могут быть включены в другой в течение определенного фиксированного периода времени.
С синхронными транзакциями проблема решается проще. Но создание решения для шардинга, способного совершать атомарные синхронные транзакции между шардами, — нетривиальная задача.
Другое решение заключается в том, что сами контракты могут перемещаться по шардам.
Можно ли передавать состояние криптографическим способом?
Имеется в виду, можно ли как-то закодировать всю сеть, чтобы каждый раз не нужно было передавать все состояние блокчейна и перезагружать его.
Кратко говоря, нет. Потому что изменения состояния тоже нужно передавать.