Одной из проблем Ethereum является то, что по умолчанию увеличивается размер и сложность любого блокчейн-протокола со временем. Это происходит в двух местах:
Для Ethereum, чтобы сохраниться в долгосрочной перспективе, нам нужна сильная контр-давление против обоих этих тенденций, постепенно уменьшая сложность и нагрузку. Но в то же время нам нужно сохранить одно из ключевых свойств, которые делают блокчейны великими: их постоянство. Вы можете поместить NFT, любовное письмо в транзакцию calldata или смарт-контракт, содержащий миллион долларов, на цепочку, зайти в пещеру на десять лет и обнаружить, что оно все еще там, ждет вас, чтобы прочитать и взаимодействовать с ним. Чтобы децентрализованные приложения чувствовали себя комфортно, полностью удаление их ключей обновления, им нужно быть уверенными, что их зависимости не будут обновляться таким образом, чтобы сломать их - особенно L1 сам по себе.
Очистка, дорожная карта 2023 года.
Находясь на грани между этими двумя потребностями и минимизируя или обращая вспять нагромождение, сложность и упадок, сохраняя при этом непрерывность, абсолютно возможно, если мы приложим усилия к этому. Живые организмы могут сделать это: в то время как большинство стареют со временем, нескольким счастливчикам не. Даже социальные системы могут иметь крайне долговечное. В нескольких случаях Ethereum уже продемонстрировал успехи: доказательство работы ушло, оператор SELFDESTRUCT в основном исчез, и узлы цепочки маяка уже хранят старые данные только до шести месяцев. Разработка этого пути для Ethereum более обобщенным способом и движение к итоговому результату, который будет стабильным в долгосрочной перспективе, является главным вызовом долгосрочной масштабируемости Ethereum, технической устойчивости и даже безопасности.
На момент написания этого текста, для полной синхронизации узла Ethereum требуется примерно 1,1 терабайтадискового пространства дляисполнительный клиент, плюс еще несколько сотен гигабайт для клиента консенсуса. Подавляющее большинство из них — история: данные об исторических блоках, транзакциях и квитанциях, основной массе которых много лет. Это означает, что размер узла продолжает увеличиваться на сотни гигабайт каждый год, даже если лимит газа не увеличивается вовсе.
Ключевая упрощающая особенность проблемы хранения истории заключается в том, что каждый блок указывает на предыдущий блок через хэш-ссылку (идругой структуры) достаточно иметь консенсус в настоящем, чтобы иметь консенсус в истории. Пока сеть имеет консенсус относительно последнего блока, любой исторический блок или транзакция или состояние (баланс счета, номер операции, код, хранилище) могут быть предоставлены любым одиночным участником вместе с доказательством Меркля, и доказательство позволяет любому другому лицу проверить его правильность. В то время как консенсус представляет собой модель доверия N/2-of-N, история представляет собой Модель доверия 1 из N.
Это открывает множество вариантов для того, как мы можем хранить историю. Один из естественных вариантов - использование сети, где каждый узел хранит только небольшой процент данных. Так работают торрент-сети уже десятилетия: в то время как сеть в целом хранит и распространяет миллионы файлов, каждый участник хранит и распространяет лишь небольшую их часть. Возможно, неожиданно, такой подход даже не обязательно снижает надежность данных. Если, сделав запуск узла более доступным, мы сможем создать сеть из 100 000 узлов, где каждый узел хранит случайные 10% истории, тогда каждый фрагмент данных будет реплицирован 10 000 раз - точно такой же коэффициент репликации, как и в сети из 10 000 узлов, где каждый узел хранит все.
Сегодня Ethereum уже начал отходить от модели, в которой все узлы хранят всю историю навсегда. Блоки консенсуса (т.е. части, связанные с консенсусом по доле) хранятся только в течение ~6 месяцев. Блобы хранятся только в течение ~18 дней.EIP-4444 Целью является введение годичного срока хранения исторических блоков и квитанций. Долгосрочная цель состоит в том, чтобы иметь согласованный период (который может составлять ~18 дней), в течение которого каждый узел отвечает за хранение всего, а затем создать одноранговую сеть, состоящую из узлов Ethereum, хранящих старые данные распределенным образом.
Коды стирания могут быть использованы для повышения устойчивости при сохранении того же самого коэффициента репликации. Фактически, блобы уже поставляются с кодированием стирания для поддержки выборки доступности данных. Самым простым решением может быть повторное использование этого кодирования стирания и также помещение данных выполнения и блоков согласования в блобы.
Основной оставшейся работой является создание и интеграция конкретного распределенного решения для хранения истории - по крайней мере, истории исполнения, но в конечном итоге также согласования и блобов. Самые простые решения для этого - (i) просто ввести существующую библиотеку torrent и (ii) собственное решение Ethereum, называемое gate.сеть Portal. Как только любой из них будет введен, мы сможем включить EIP-4444. Сам EIP-4444 не требует хардфорка, хотя и требует новой версии сетевого протокола. По этой причине имеет смысл включить его для всех клиентов одновременно, потому что в противном случае существует риск сбоев в работе клиентов из-за подключения к другим узлам, ожидающим загрузки полной истории, но не получившим ее.
Основной компромисс заключается в том, насколько мы стараемся сделать «древние» исторические данные доступными. Самым простым решением было бы просто прекратить хранение древней истории завтра и полагаться на существующие архивные узлы и различных централизованных поставщиков для репликации. Это просто, но это ослабляет позицию Ethereum как места для создания постоянных записей. Более сложный, но безопасный путь - сначала разработать и интегрировать торрентную сеть для хранения истории в распределенном виде. Здесь есть два аспекта «насколько мы стараемся»:
"Максимально параноидальный подход для (1) будет включать в себя"доказательство хранения: на самом деле требует, чтобы каждый валидатор Proof of Stake хранил некоторый процент истории, и регулярно криптографически проверял, что они это делают. Более умеренный подход заключается в том, чтобы установить добровольный стандарт того, какой процент истории хранит каждый клиент.
Для (2) базовая реализация включает в себя просто работу, которая уже проделана сегодня: Portal уже хранит файлы ERA, содержащие всю историю Ethereum. Более тщательная реализация будет включать в себя фактическое подключение к процессу синхронизации, так что, если кто-то захочет синхронизировать узел, хранящий полную историю, или архивный узел, он сможет сделать это, даже если в сети нет других архивных узлов, синхронизируясь прямо из сети Portal.
Снижение требований к хранению истории, вероятно, даже важнее, чем отсутствие состояния, если мы хотим сделать запуск или создание узла крайне простым: из 1,1 ТБ, которые нужно иметь узлу, ~300 ГБ состояния, и оставшиеся ~800 ГБ - это история. Видение узла Ethereum, работающего на умных часах и занимающего всего несколько минут для настройки, становится реальностью только в том случае, если реализованы как отсутствие состояния, так и EIP-4444.
Ограничение хранения истории также делает его более жизнеспособным для более новых реализаций узлов Ethereum, которые поддерживают только последние версии протокола, что позволяет им быть намного проще. Например, множество строк кода можно безопасно удалить теперь, что все пустые слоты хранения, созданные во время атак DoS 2016 года, все еще.удалено. Теперь, когда переход на доказательство доли - это древняя история, клиенты могут безопасно удалить весь код, связанный с доказательством работы.
Даже если мы устраним необходимость для клиентов хранить историю, требования клиента к хранилищу будут продолжать расти, примерно на 50 ГБ в год, из-за продолжающегося роста состояния: остатков на счетах и одноразовых номеров, кода контракта и хранилища контрактов. Пользователи могут заплатить единовременную плату, чтобы навсегда возложить бремя на настоящих и будущих клиентов Ethereum.
Состояние намного сложнее “истечь”, чем история, потому что EVM фундаментально разработан с учётом предположения, что однажды созданный объект состояния всегда будет существовать и может быть прочитан любой транзакцией в любое время. Если мы внедрим бессостоятельность, можно утверждать, что, возможно, эта проблема не настолько плоха: только специализированный класс строителей блоков действительно нужно будет хранить состояние, а все другие узлы (даже список включенияПроизводство!) Может работать в состоянии отсутствия данных. Однако есть аргумент, что мы не хотим слишком полагаться на отсутствие данных, и в конечном итоге мы можем захотеть истекать состояние, чтобы сохранить децентрализацию Ethereum.
Сегодня, когда вы создаете новый объект состояния (что может произойти одним из трех способов: (i) отправка ETH на новый счет, (ii) создание нового счета с кодом, (iii) установка ранее не затронутого слота хранения), этот объект состояния остается в этом состоянии навсегда. Вместо этого мы хотим, чтобы объекты автоматически истекали со временем. Ключевая проблема заключается в том, чтобы сделать это таким образом, чтобы достигнуть трех целей:
Проблему легко решить, не удовлетворяя этим целям. Например, вы можете сделать так, чтобы каждый объект состояния также хранил счетчик для даты истечения срока действия (который может быть расширен путем сжигания ETH, что может происходить автоматически при чтении или записи) и иметь процесс, который циклически проходит по состоянию для удаления объектов состояния с истекшим сроком действия. Однако это приводит к дополнительным вычислительным ресурсам (и даже требованиям к хранилищу), и это определенно не удовлетворяет требованию удобства использования. Разработчикам тоже будет трудно рассуждать о крайних случаях, когда значения хранилища иногда сбрасываются до нуля. Если вы сделаете таймер истечения срока действия на уровне всего контракта, это технически облегчит жизнь разработчикам, но усложнит экономику: разработчикам придется думать о том, как «переложить» текущие расходы на хранение на своих пользователей.
Это проблемы, с которыми сообщество разработчиков Ethereum боролось многие годы, включая предложения, такие как «аренда блокчейн«и»регенезис“. В конечном итоге мы объединили лучшие части предложений и сошлись на двух категориях «известных наименее плохих решений»:
Предложения по частичному истечению срока действия всех работают по одному и тому же принципу. Мы разбиваем состояние на куски. Каждый постоянно хранит «карту верхнего уровня», в которой указано, какие куски пустые, а какие — непустые. Данные в каждом куске хранятся только в том случае, если эти данные недавно запрашивались. Существует механизм «воскрешения», с помощью которого, если кусок больше не хранится, любой может вернуть эти данные, предоставив доказательство того, что это были за данные.
Основные отличия между этими предложениями заключаются в: (i) том, как мы определяем «недавно», и (ii) том, как мы определяем «кусок». Одно конкретное предложение - EIP-7736, которая основывается на дизайне "стебель и лист" введено для деревьев Verkle (хотя совместим с любой формой отсутствия состояния, например, с бинарными деревьями). В этом дизайне заголовок, код и слоты хранения, смежные друг с другом, хранятся под одним и тем же «стеблем». Данные, хранящиеся под стеблем, могут быть не более 256 * 31 = 7,936 байт. Во многих случаях весь заголовок, код и множество ключевых слотов хранения учетной записи хранятся под одним и тем же стеблем. Если данные под определенным стеблем не считываются или не записываются в течение 6 месяцев, данные больше не хранятся, а вместо этого хранится только 32-байтовое подтверждение («заглушка») данных. Будущие транзакции, которые получают доступ к этим данным, должны будут «воскресить» данные с доказательством, которое будет проверяться по заглушке.
Существуют и другие способы реализации подобной идеи. Например, если уровень детализации учетной записи недостаточен, мы могли бы создать схему, в рамках которой каждая 1/232 часть дерева управляется подобным механизмом стебель-лист.
Это сложнее из-за стимулов: злоумышленник может заставить клиентов постоянно хранить очень большое количество состояния, поместив очень большое количество данных в одну поддерево и отправив одну транзакцию каждый год, чтобы «обновить дерево». Если сделать стоимость обновления пропорциональной (или длительность обновления обратно пропорциональной) размеру дерева, то кто-то может надругаться над другим пользователем, поместив очень большое количество данных в то же поддерево, что и он. Можно попытаться ограничить оба этих проблемы, сделав гранулярность динамической на основе размера поддерева: например, каждые последовательные 216 = 65536 объектов состояния могут быть рассмотрены как «группа». Однако эти идеи более сложные; подход на основе ствола прост и соответствует стимулам, потому что обычно все данные под стволом относятся к одному приложению или пользователю.
Что, если мы хотим избежать любого постоянного увеличения состояния вообще, даже 32-байтовых заглушек? Это сложная проблема из-за @vbuterin/state_size_management#Resurrection-conflicts">конфликты возрождения: что если объект состояния был удален, а затем выполнение EVM помещает другой объект состояния в точно такую же позицию, но затем кто-то, кому важен исходный объект состояния, возвращается и пытается восстановить его? С помощью частичного истечения срока действия состояния, «заглушка» предотвращает создание новых данных. С полным истечением срока действия состояния мы не можем позволить себе хранить даже заглушку.
Дизайн, основанный на периоде адреса, является наиболее известной идеей для решения этой проблемы. Вместо того, чтобы иметь одно дерево состояний, хранящее все состояние, у нас есть постоянно растущий список деревьев состояний, и любое состояние, которое читается или записывается, сохраняется в самом последнем дереве состояний. Новое пустое дерево состояний добавляется один раз за период (например, 1 год). Деревья старого состояния замерзли намертво. Ожидается, что полные узлы будут хранить только самые последние два дерева. Если объект состояния не был затронут в течение двух периодов и, таким образом, попадает в дерево с истекшим сроком действия, он все равно может быть прочитан или записан, но транзакция должна будет доказать доказательство Меркла для него - и как только это произойдет, копия снова будет сохранена в последнем дереве.
Ключевая идея того, чтобы сделать все это удобным для пользователей и разработчиков, заключается в концепции периодов адресов. Период адреса - это число, которое является частью адреса. Основное правило заключается в том, что адрес с периодом адреса N может быть прочитан или записан только во время или после периода N (т.е. когда список деревьев состояний достигает длины N). Если вы сохраняете новый объект состояния (например, новый контракт или новый баланс ERC20), убедитесь, что помещаете объект состояния в контракт, период адреса которого является либо N, либо N-1, тогда его можно сохранить немедленно, не предоставляя доказательств того, что там раньше ничего не было. Любые добавления или изменения состояния в старых периодах адресов, с другой стороны, требуют доказательства.
Этот дизайн сохраняет большую часть текущих свойств Ethereum, требует очень легких дополнительных вычислений, позволяет писать приложения почти так же, как они есть сегодня (ERC20 нужно будет переписать, чтобы гарантировать, что балансы адресов с периодом адреса N хранятся в дочернем контракте, который сам по себе имеет период адреса N), и решает проблему «пользователь уходит в пещеру на пять лет». Однако у него есть одна большая проблема: адреса должны быть расширены за пределы 20 байт, чтобы соответствовать адресным периодам.
Одно из предложений заключается в том, чтобы ввести новый формат адреса из 32 байт, который включает в себя номер версии, номер периода адреса и расширенный хэш.
0x01000000000157aE408398dF7E5f4552091A69125d5dFcb7B8C2659029395bdF
Красное - это номер версии. Четыре нуля, окрашенные в оранжевый цвет, предназначены для пустого пространства, которое в будущем может вместить номер шарда. Зеленое - это номер периода адреса. Синее - это 26-байтовый хеш.
Основной проблемой здесь является обратная совместимость. Существующие контракты разработаны вокруг адресов из 20 байтов и часто используют техники плотной упаковки байтов, которые явно предполагают, что адреса имеют ровно 20 байтов в длину.@ipsilon/address-space-extension-exploration">Один из способов решения этой проблемы заключается в использовании карты трансляции, где контракты старого стиля, взаимодействующие с адресами нового стиля, увидели бы 20-байтный хэш адреса нового стиля. Однако здесь имеются значительные сложности, связанные с обеспечением безопасности.
Другой подход идет в противоположном направлении: мы сразу запрещаем некоторый поддиапазон адресов размером 2128 (например, все адреса, начинающиеся с 0xffffffff), а затем используем этот диапазон для введения адресов с периодами адреса и хэшами из 14 байт.
0xfffffff000169125d5dFcb7B8C2659029395bdF
Основной жертвой, которую приносит этот подход, является то, что онсоздает риски безопасности для контрфактических адресов: адреса, которые управляют активами или разрешениями, но чей код еще не был опубликован на цепочке. Риск заключается в том, что кто-то создаст адрес, который утверждает, что имеет одну часть (еще не опубликованного) кода, но также имеет другую допустимую часть кода, которая хешируется в тот же адрес. Вычисление такого столкновения требует 280хеши сегодня; сокращение области адресов уменьшило бы это число до очень доступных 256 хеши.
Ключевая область риска - контрфактные адреса, которые не являются кошельками, принадлежащими одному владельцу, является относительно редким случаем сегодня, но, вероятно, станет более распространенным по мере перехода в многовариантный мир. Единственное решение - просто принять этот риск, но определить все общие случаи использования, где это может стать проблемой, и разработать эффективные обходные пути.
Я вижу четыре жизнеспособных пути для будущего:
Один важный момент заключается в том, что сложные вопросы, связанные с расширением и сжатием адресного пространства, в конечном итоге придется решить вне зависимости от того, будут ли когда-либо реализованы схемы истечения срока действия состояния, зависящие от изменений формата адреса. Сегодня это занимает примерно 280хешей для генерации коллизии адресов, вычислительная нагрузка, которая уже осуществима для чрезвычайно ресурсных актеров: GPU может обрабатывать около 227хэши, поэтому запуск на год может вычислить 252, поэтому все ~2^30 ГПУ в миреможет вычислить столкновение примерно за 1/4 года, а FPGA и ASIC могут ускорить это еще больше. В будущем такие атаки станут доступны для все большего количества людей. Следовательно, фактическая стоимость реализации полного истечения срока действия состояния может оказаться не такой высокой, как кажется, поскольку мы должны решить эту очень сложную проблему с адресом в любом случае.
Истечение срока действия потенциально упрощает переход от одного формата дерева состояний к другому, потому что нет необходимости в процедуре перехода: вы можете просто начать создавать новые деревья, используя новый формат, а затем сделать хардфорк для преобразования старых деревьев. Таким образом, несмотря на то, что истечение срока действия государства является сложным, оно имеет преимущества в упрощении других аспектов дорожной карты.
Одно из ключевых предпосылок безопасности, доступности и доверительная нейтральность это простота. Если протокол красив и прост, это снижает вероятность того, что в нем будут ошибки. Это увеличивает вероятность того, что новые разработчики смогут прийти и поработать с любой его частью. Скорее всего, это будет справедливо и легче защититься от особых интересов. К сожалению, протоколы, как и любая социальная система, по умолчанию со временем усложняются. Если мы не хотим, чтобы Ethereum ушел в черную дыру постоянно растущей сложности, нам нужно сделать одну из двух вещей: (i) прекратить вносить изменения и закостенять протокол, (ii) иметь возможность фактически удалять функции и уменьшать сложность. Также возможен промежуточный путь, заключающийся в меньшем количестве изменений в протоколе, а также при устранении хотя бы небольшой сложности с течением времени. В этом разделе мы поговорим о том, как мы можем уменьшить или устранить сложность.
Нет большого одиночного исправления, которое может уменьшить сложность протокола; врожденная природа проблемы заключается в том, что существует множество маленьких исправлений.
Один пример, который уже почти готов и может служить основой для обработки остальных, - это @vbuterin/selfdestruct">удаление операции SELFDESTRUCT. Операция SELFDESTRUCT была единственной операцией, которая могла изменять неограниченное количество ячеек хранилища в рамках одного блока, что требовало от клиентов реализации значительно большей сложности для предотвращения DoS-атак. Исходно эта операция была предназначена для возможности добровольной очистки состояния, позволяя уменьшать размер состояния со временем. На практике очень мало людей использовало ее. опкод был ослабленчтобы разрешить только самоуничтожающиеся аккаунты, созданные в той же транзакции в хардфорке Dencun. Это решает проблему DoS и позволяет существенно упростить код клиента. В будущем, вероятно, имеет смысл окончательно удалить операцию кода.
Некоторые ключевые примеры возможностей упрощения протокола, которые были выявлены до сих пор, включают следующее. Во-первых, некоторые примеры, которые находятся вне EVM; они относительно немногоинвазивны и, таким образом, легче достичь согласия и реализовать в более короткие сроки.
Теперь несколько примеров, которые находятся в EVM:
Основным компромиссом при таком упрощении функционала является (i) насколько мы упрощаем и насколько быстро, а также (ii) совместимость с предыдущими версиями. Значимость Ethereum как блокчейна заключается в том, что это платформа, на которой вы можете развернуть приложение и быть уверенным, что оно будет работать многие годы вперед. В то же время, возможно зайти слишком далеко в достижении этой идеи.перефразировать Уильяма Дженнингса Брайана, «распять Ethereum на кресте обратной совместимости». Если есть только два приложения во всей сети Ethereum, которые используют определенную функцию, и у одного из них нет пользователей в течение нескольких лет, а другой почти не используется и обеспечивает общую стоимость в $57, то мы просто должны удалить эту функцию и, при необходимости, возместить пострадавшим $57 из своего кармана.
Более широкая социальная проблема заключается в создании стандартизированного конвейера для внесения изменений, не нарушающих обратную совместимость, в случае неэкстренных ситуаций. Один из способов решения этой проблемы - изучение и расширение существующих прецедентов, таких как процесс SELFDESTRUCT. Конвейер выглядит примерно следующим образом:
Между шагом 1 и шагом 4 должно быть многолетнее конвейерное производство с ясной информацией о том, какие элементы находятся на каком шаге. На этом этапе существует компромисс между тем, насколько энергичным и быстрым является конвейер удаления функций по сравнению с более консервативным и направленным на развитие других областей протокола, но мы все еще далеки от Паретовского фронта.
Одним из основных наборов изменений, которые были предложены для EVM, является Формат объекта EVM (EOF). EOF вносит много изменений, таких как запрет наблюдения за газом, наблюдение за кодом (т. е. нет CODECOPY), разрешение только статических переходов. Цель - позволить EVM обновляться более сильным образом, сохраняя обратную совместимость (так как пред-EOF EVM все еще существует).
Это имеет преимущество в том, что создается естественный путь к добавлению новых функций EVM и поощрению миграции к более ограниченному EVM с более сильными гарантиями. У него есть недостаток в том, что он значительно увеличивает сложность протокола, если только мы не сможем найти способ в конечном итоге устареть и удалить старый EVM. Одним из основных вопросов является: какую роль играет EOF в предложениях по упрощению EVM, особенно если целью является уменьшение сложности EVM в целом?
Многие предложения по "улучшению" в остальной части плана также являются возможностями упрощения старых функций. Чтобы повторить некоторые примеры из вышеуказанного:
Более радикальная стратегия упрощения Ethereum заключается в том, чтобы оставить протокол без изменений, но переместить большую часть его из функций протокола в код контракта.
Самая экстремальная версия этого заключается в том, чтобы сделать Ethereum L1 "технически" только маяк цепи и ввести минимальную виртуальную машину (например.RISC-V, Каир, или что-то еще более минимальное, специализированное для доказательства систем), что позволяет любому другому создать свой собственный rollup. Затем EVM превратится в первый из этих rollups. Это иронично точно тот же результат, что и предложения по среде выполнения с 2019-20, хотя SNARK делают его значительно более жизнеспособным для фактической реализации.
Более умеренным подходом было бы сохранить отношение между цепочкой маяка и текущей средой выполнения Ethereum в нынешнем виде, но выполнить замену EVM на месте. Мы могли бы выбрать RISC-V, Cairo или другую виртуальную машину в качестве новой «официальной виртуальной машины Ethereum» и затем принудительно конвертировать все контракты EVM в код новой виртуальной машины, который интерпретирует логику исходного кода (путем компиляции или интерпретации). Теоретически, это даже может быть выполнено с версией EOF в качестве «целевой виртуальной машины».
Одной из проблем Ethereum является то, что по умолчанию увеличивается размер и сложность любого блокчейн-протокола со временем. Это происходит в двух местах:
Для Ethereum, чтобы сохраниться в долгосрочной перспективе, нам нужна сильная контр-давление против обоих этих тенденций, постепенно уменьшая сложность и нагрузку. Но в то же время нам нужно сохранить одно из ключевых свойств, которые делают блокчейны великими: их постоянство. Вы можете поместить NFT, любовное письмо в транзакцию calldata или смарт-контракт, содержащий миллион долларов, на цепочку, зайти в пещеру на десять лет и обнаружить, что оно все еще там, ждет вас, чтобы прочитать и взаимодействовать с ним. Чтобы децентрализованные приложения чувствовали себя комфортно, полностью удаление их ключей обновления, им нужно быть уверенными, что их зависимости не будут обновляться таким образом, чтобы сломать их - особенно L1 сам по себе.
Очистка, дорожная карта 2023 года.
Находясь на грани между этими двумя потребностями и минимизируя или обращая вспять нагромождение, сложность и упадок, сохраняя при этом непрерывность, абсолютно возможно, если мы приложим усилия к этому. Живые организмы могут сделать это: в то время как большинство стареют со временем, нескольким счастливчикам не. Даже социальные системы могут иметь крайне долговечное. В нескольких случаях Ethereum уже продемонстрировал успехи: доказательство работы ушло, оператор SELFDESTRUCT в основном исчез, и узлы цепочки маяка уже хранят старые данные только до шести месяцев. Разработка этого пути для Ethereum более обобщенным способом и движение к итоговому результату, который будет стабильным в долгосрочной перспективе, является главным вызовом долгосрочной масштабируемости Ethereum, технической устойчивости и даже безопасности.
На момент написания этого текста, для полной синхронизации узла Ethereum требуется примерно 1,1 терабайтадискового пространства дляисполнительный клиент, плюс еще несколько сотен гигабайт для клиента консенсуса. Подавляющее большинство из них — история: данные об исторических блоках, транзакциях и квитанциях, основной массе которых много лет. Это означает, что размер узла продолжает увеличиваться на сотни гигабайт каждый год, даже если лимит газа не увеличивается вовсе.
Ключевая упрощающая особенность проблемы хранения истории заключается в том, что каждый блок указывает на предыдущий блок через хэш-ссылку (идругой структуры) достаточно иметь консенсус в настоящем, чтобы иметь консенсус в истории. Пока сеть имеет консенсус относительно последнего блока, любой исторический блок или транзакция или состояние (баланс счета, номер операции, код, хранилище) могут быть предоставлены любым одиночным участником вместе с доказательством Меркля, и доказательство позволяет любому другому лицу проверить его правильность. В то время как консенсус представляет собой модель доверия N/2-of-N, история представляет собой Модель доверия 1 из N.
Это открывает множество вариантов для того, как мы можем хранить историю. Один из естественных вариантов - использование сети, где каждый узел хранит только небольшой процент данных. Так работают торрент-сети уже десятилетия: в то время как сеть в целом хранит и распространяет миллионы файлов, каждый участник хранит и распространяет лишь небольшую их часть. Возможно, неожиданно, такой подход даже не обязательно снижает надежность данных. Если, сделав запуск узла более доступным, мы сможем создать сеть из 100 000 узлов, где каждый узел хранит случайные 10% истории, тогда каждый фрагмент данных будет реплицирован 10 000 раз - точно такой же коэффициент репликации, как и в сети из 10 000 узлов, где каждый узел хранит все.
Сегодня Ethereum уже начал отходить от модели, в которой все узлы хранят всю историю навсегда. Блоки консенсуса (т.е. части, связанные с консенсусом по доле) хранятся только в течение ~6 месяцев. Блобы хранятся только в течение ~18 дней.EIP-4444 Целью является введение годичного срока хранения исторических блоков и квитанций. Долгосрочная цель состоит в том, чтобы иметь согласованный период (который может составлять ~18 дней), в течение которого каждый узел отвечает за хранение всего, а затем создать одноранговую сеть, состоящую из узлов Ethereum, хранящих старые данные распределенным образом.
Коды стирания могут быть использованы для повышения устойчивости при сохранении того же самого коэффициента репликации. Фактически, блобы уже поставляются с кодированием стирания для поддержки выборки доступности данных. Самым простым решением может быть повторное использование этого кодирования стирания и также помещение данных выполнения и блоков согласования в блобы.
Основной оставшейся работой является создание и интеграция конкретного распределенного решения для хранения истории - по крайней мере, истории исполнения, но в конечном итоге также согласования и блобов. Самые простые решения для этого - (i) просто ввести существующую библиотеку torrent и (ii) собственное решение Ethereum, называемое gate.сеть Portal. Как только любой из них будет введен, мы сможем включить EIP-4444. Сам EIP-4444 не требует хардфорка, хотя и требует новой версии сетевого протокола. По этой причине имеет смысл включить его для всех клиентов одновременно, потому что в противном случае существует риск сбоев в работе клиентов из-за подключения к другим узлам, ожидающим загрузки полной истории, но не получившим ее.
Основной компромисс заключается в том, насколько мы стараемся сделать «древние» исторические данные доступными. Самым простым решением было бы просто прекратить хранение древней истории завтра и полагаться на существующие архивные узлы и различных централизованных поставщиков для репликации. Это просто, но это ослабляет позицию Ethereum как места для создания постоянных записей. Более сложный, но безопасный путь - сначала разработать и интегрировать торрентную сеть для хранения истории в распределенном виде. Здесь есть два аспекта «насколько мы стараемся»:
"Максимально параноидальный подход для (1) будет включать в себя"доказательство хранения: на самом деле требует, чтобы каждый валидатор Proof of Stake хранил некоторый процент истории, и регулярно криптографически проверял, что они это делают. Более умеренный подход заключается в том, чтобы установить добровольный стандарт того, какой процент истории хранит каждый клиент.
Для (2) базовая реализация включает в себя просто работу, которая уже проделана сегодня: Portal уже хранит файлы ERA, содержащие всю историю Ethereum. Более тщательная реализация будет включать в себя фактическое подключение к процессу синхронизации, так что, если кто-то захочет синхронизировать узел, хранящий полную историю, или архивный узел, он сможет сделать это, даже если в сети нет других архивных узлов, синхронизируясь прямо из сети Portal.
Снижение требований к хранению истории, вероятно, даже важнее, чем отсутствие состояния, если мы хотим сделать запуск или создание узла крайне простым: из 1,1 ТБ, которые нужно иметь узлу, ~300 ГБ состояния, и оставшиеся ~800 ГБ - это история. Видение узла Ethereum, работающего на умных часах и занимающего всего несколько минут для настройки, становится реальностью только в том случае, если реализованы как отсутствие состояния, так и EIP-4444.
Ограничение хранения истории также делает его более жизнеспособным для более новых реализаций узлов Ethereum, которые поддерживают только последние версии протокола, что позволяет им быть намного проще. Например, множество строк кода можно безопасно удалить теперь, что все пустые слоты хранения, созданные во время атак DoS 2016 года, все еще.удалено. Теперь, когда переход на доказательство доли - это древняя история, клиенты могут безопасно удалить весь код, связанный с доказательством работы.
Даже если мы устраним необходимость для клиентов хранить историю, требования клиента к хранилищу будут продолжать расти, примерно на 50 ГБ в год, из-за продолжающегося роста состояния: остатков на счетах и одноразовых номеров, кода контракта и хранилища контрактов. Пользователи могут заплатить единовременную плату, чтобы навсегда возложить бремя на настоящих и будущих клиентов Ethereum.
Состояние намного сложнее “истечь”, чем история, потому что EVM фундаментально разработан с учётом предположения, что однажды созданный объект состояния всегда будет существовать и может быть прочитан любой транзакцией в любое время. Если мы внедрим бессостоятельность, можно утверждать, что, возможно, эта проблема не настолько плоха: только специализированный класс строителей блоков действительно нужно будет хранить состояние, а все другие узлы (даже список включенияПроизводство!) Может работать в состоянии отсутствия данных. Однако есть аргумент, что мы не хотим слишком полагаться на отсутствие данных, и в конечном итоге мы можем захотеть истекать состояние, чтобы сохранить децентрализацию Ethereum.
Сегодня, когда вы создаете новый объект состояния (что может произойти одним из трех способов: (i) отправка ETH на новый счет, (ii) создание нового счета с кодом, (iii) установка ранее не затронутого слота хранения), этот объект состояния остается в этом состоянии навсегда. Вместо этого мы хотим, чтобы объекты автоматически истекали со временем. Ключевая проблема заключается в том, чтобы сделать это таким образом, чтобы достигнуть трех целей:
Проблему легко решить, не удовлетворяя этим целям. Например, вы можете сделать так, чтобы каждый объект состояния также хранил счетчик для даты истечения срока действия (который может быть расширен путем сжигания ETH, что может происходить автоматически при чтении или записи) и иметь процесс, который циклически проходит по состоянию для удаления объектов состояния с истекшим сроком действия. Однако это приводит к дополнительным вычислительным ресурсам (и даже требованиям к хранилищу), и это определенно не удовлетворяет требованию удобства использования. Разработчикам тоже будет трудно рассуждать о крайних случаях, когда значения хранилища иногда сбрасываются до нуля. Если вы сделаете таймер истечения срока действия на уровне всего контракта, это технически облегчит жизнь разработчикам, но усложнит экономику: разработчикам придется думать о том, как «переложить» текущие расходы на хранение на своих пользователей.
Это проблемы, с которыми сообщество разработчиков Ethereum боролось многие годы, включая предложения, такие как «аренда блокчейн«и»регенезис“. В конечном итоге мы объединили лучшие части предложений и сошлись на двух категориях «известных наименее плохих решений»:
Предложения по частичному истечению срока действия всех работают по одному и тому же принципу. Мы разбиваем состояние на куски. Каждый постоянно хранит «карту верхнего уровня», в которой указано, какие куски пустые, а какие — непустые. Данные в каждом куске хранятся только в том случае, если эти данные недавно запрашивались. Существует механизм «воскрешения», с помощью которого, если кусок больше не хранится, любой может вернуть эти данные, предоставив доказательство того, что это были за данные.
Основные отличия между этими предложениями заключаются в: (i) том, как мы определяем «недавно», и (ii) том, как мы определяем «кусок». Одно конкретное предложение - EIP-7736, которая основывается на дизайне "стебель и лист" введено для деревьев Verkle (хотя совместим с любой формой отсутствия состояния, например, с бинарными деревьями). В этом дизайне заголовок, код и слоты хранения, смежные друг с другом, хранятся под одним и тем же «стеблем». Данные, хранящиеся под стеблем, могут быть не более 256 * 31 = 7,936 байт. Во многих случаях весь заголовок, код и множество ключевых слотов хранения учетной записи хранятся под одним и тем же стеблем. Если данные под определенным стеблем не считываются или не записываются в течение 6 месяцев, данные больше не хранятся, а вместо этого хранится только 32-байтовое подтверждение («заглушка») данных. Будущие транзакции, которые получают доступ к этим данным, должны будут «воскресить» данные с доказательством, которое будет проверяться по заглушке.
Существуют и другие способы реализации подобной идеи. Например, если уровень детализации учетной записи недостаточен, мы могли бы создать схему, в рамках которой каждая 1/232 часть дерева управляется подобным механизмом стебель-лист.
Это сложнее из-за стимулов: злоумышленник может заставить клиентов постоянно хранить очень большое количество состояния, поместив очень большое количество данных в одну поддерево и отправив одну транзакцию каждый год, чтобы «обновить дерево». Если сделать стоимость обновления пропорциональной (или длительность обновления обратно пропорциональной) размеру дерева, то кто-то может надругаться над другим пользователем, поместив очень большое количество данных в то же поддерево, что и он. Можно попытаться ограничить оба этих проблемы, сделав гранулярность динамической на основе размера поддерева: например, каждые последовательные 216 = 65536 объектов состояния могут быть рассмотрены как «группа». Однако эти идеи более сложные; подход на основе ствола прост и соответствует стимулам, потому что обычно все данные под стволом относятся к одному приложению или пользователю.
Что, если мы хотим избежать любого постоянного увеличения состояния вообще, даже 32-байтовых заглушек? Это сложная проблема из-за @vbuterin/state_size_management#Resurrection-conflicts">конфликты возрождения: что если объект состояния был удален, а затем выполнение EVM помещает другой объект состояния в точно такую же позицию, но затем кто-то, кому важен исходный объект состояния, возвращается и пытается восстановить его? С помощью частичного истечения срока действия состояния, «заглушка» предотвращает создание новых данных. С полным истечением срока действия состояния мы не можем позволить себе хранить даже заглушку.
Дизайн, основанный на периоде адреса, является наиболее известной идеей для решения этой проблемы. Вместо того, чтобы иметь одно дерево состояний, хранящее все состояние, у нас есть постоянно растущий список деревьев состояний, и любое состояние, которое читается или записывается, сохраняется в самом последнем дереве состояний. Новое пустое дерево состояний добавляется один раз за период (например, 1 год). Деревья старого состояния замерзли намертво. Ожидается, что полные узлы будут хранить только самые последние два дерева. Если объект состояния не был затронут в течение двух периодов и, таким образом, попадает в дерево с истекшим сроком действия, он все равно может быть прочитан или записан, но транзакция должна будет доказать доказательство Меркла для него - и как только это произойдет, копия снова будет сохранена в последнем дереве.
Ключевая идея того, чтобы сделать все это удобным для пользователей и разработчиков, заключается в концепции периодов адресов. Период адреса - это число, которое является частью адреса. Основное правило заключается в том, что адрес с периодом адреса N может быть прочитан или записан только во время или после периода N (т.е. когда список деревьев состояний достигает длины N). Если вы сохраняете новый объект состояния (например, новый контракт или новый баланс ERC20), убедитесь, что помещаете объект состояния в контракт, период адреса которого является либо N, либо N-1, тогда его можно сохранить немедленно, не предоставляя доказательств того, что там раньше ничего не было. Любые добавления или изменения состояния в старых периодах адресов, с другой стороны, требуют доказательства.
Этот дизайн сохраняет большую часть текущих свойств Ethereum, требует очень легких дополнительных вычислений, позволяет писать приложения почти так же, как они есть сегодня (ERC20 нужно будет переписать, чтобы гарантировать, что балансы адресов с периодом адреса N хранятся в дочернем контракте, который сам по себе имеет период адреса N), и решает проблему «пользователь уходит в пещеру на пять лет». Однако у него есть одна большая проблема: адреса должны быть расширены за пределы 20 байт, чтобы соответствовать адресным периодам.
Одно из предложений заключается в том, чтобы ввести новый формат адреса из 32 байт, который включает в себя номер версии, номер периода адреса и расширенный хэш.
0x01000000000157aE408398dF7E5f4552091A69125d5dFcb7B8C2659029395bdF
Красное - это номер версии. Четыре нуля, окрашенные в оранжевый цвет, предназначены для пустого пространства, которое в будущем может вместить номер шарда. Зеленое - это номер периода адреса. Синее - это 26-байтовый хеш.
Основной проблемой здесь является обратная совместимость. Существующие контракты разработаны вокруг адресов из 20 байтов и часто используют техники плотной упаковки байтов, которые явно предполагают, что адреса имеют ровно 20 байтов в длину.@ipsilon/address-space-extension-exploration">Один из способов решения этой проблемы заключается в использовании карты трансляции, где контракты старого стиля, взаимодействующие с адресами нового стиля, увидели бы 20-байтный хэш адреса нового стиля. Однако здесь имеются значительные сложности, связанные с обеспечением безопасности.
Другой подход идет в противоположном направлении: мы сразу запрещаем некоторый поддиапазон адресов размером 2128 (например, все адреса, начинающиеся с 0xffffffff), а затем используем этот диапазон для введения адресов с периодами адреса и хэшами из 14 байт.
0xfffffff000169125d5dFcb7B8C2659029395bdF
Основной жертвой, которую приносит этот подход, является то, что онсоздает риски безопасности для контрфактических адресов: адреса, которые управляют активами или разрешениями, но чей код еще не был опубликован на цепочке. Риск заключается в том, что кто-то создаст адрес, который утверждает, что имеет одну часть (еще не опубликованного) кода, но также имеет другую допустимую часть кода, которая хешируется в тот же адрес. Вычисление такого столкновения требует 280хеши сегодня; сокращение области адресов уменьшило бы это число до очень доступных 256 хеши.
Ключевая область риска - контрфактные адреса, которые не являются кошельками, принадлежащими одному владельцу, является относительно редким случаем сегодня, но, вероятно, станет более распространенным по мере перехода в многовариантный мир. Единственное решение - просто принять этот риск, но определить все общие случаи использования, где это может стать проблемой, и разработать эффективные обходные пути.
Я вижу четыре жизнеспособных пути для будущего:
Один важный момент заключается в том, что сложные вопросы, связанные с расширением и сжатием адресного пространства, в конечном итоге придется решить вне зависимости от того, будут ли когда-либо реализованы схемы истечения срока действия состояния, зависящие от изменений формата адреса. Сегодня это занимает примерно 280хешей для генерации коллизии адресов, вычислительная нагрузка, которая уже осуществима для чрезвычайно ресурсных актеров: GPU может обрабатывать около 227хэши, поэтому запуск на год может вычислить 252, поэтому все ~2^30 ГПУ в миреможет вычислить столкновение примерно за 1/4 года, а FPGA и ASIC могут ускорить это еще больше. В будущем такие атаки станут доступны для все большего количества людей. Следовательно, фактическая стоимость реализации полного истечения срока действия состояния может оказаться не такой высокой, как кажется, поскольку мы должны решить эту очень сложную проблему с адресом в любом случае.
Истечение срока действия потенциально упрощает переход от одного формата дерева состояний к другому, потому что нет необходимости в процедуре перехода: вы можете просто начать создавать новые деревья, используя новый формат, а затем сделать хардфорк для преобразования старых деревьев. Таким образом, несмотря на то, что истечение срока действия государства является сложным, оно имеет преимущества в упрощении других аспектов дорожной карты.
Одно из ключевых предпосылок безопасности, доступности и доверительная нейтральность это простота. Если протокол красив и прост, это снижает вероятность того, что в нем будут ошибки. Это увеличивает вероятность того, что новые разработчики смогут прийти и поработать с любой его частью. Скорее всего, это будет справедливо и легче защититься от особых интересов. К сожалению, протоколы, как и любая социальная система, по умолчанию со временем усложняются. Если мы не хотим, чтобы Ethereum ушел в черную дыру постоянно растущей сложности, нам нужно сделать одну из двух вещей: (i) прекратить вносить изменения и закостенять протокол, (ii) иметь возможность фактически удалять функции и уменьшать сложность. Также возможен промежуточный путь, заключающийся в меньшем количестве изменений в протоколе, а также при устранении хотя бы небольшой сложности с течением времени. В этом разделе мы поговорим о том, как мы можем уменьшить или устранить сложность.
Нет большого одиночного исправления, которое может уменьшить сложность протокола; врожденная природа проблемы заключается в том, что существует множество маленьких исправлений.
Один пример, который уже почти готов и может служить основой для обработки остальных, - это @vbuterin/selfdestruct">удаление операции SELFDESTRUCT. Операция SELFDESTRUCT была единственной операцией, которая могла изменять неограниченное количество ячеек хранилища в рамках одного блока, что требовало от клиентов реализации значительно большей сложности для предотвращения DoS-атак. Исходно эта операция была предназначена для возможности добровольной очистки состояния, позволяя уменьшать размер состояния со временем. На практике очень мало людей использовало ее. опкод был ослабленчтобы разрешить только самоуничтожающиеся аккаунты, созданные в той же транзакции в хардфорке Dencun. Это решает проблему DoS и позволяет существенно упростить код клиента. В будущем, вероятно, имеет смысл окончательно удалить операцию кода.
Некоторые ключевые примеры возможностей упрощения протокола, которые были выявлены до сих пор, включают следующее. Во-первых, некоторые примеры, которые находятся вне EVM; они относительно немногоинвазивны и, таким образом, легче достичь согласия и реализовать в более короткие сроки.
Теперь несколько примеров, которые находятся в EVM:
Основным компромиссом при таком упрощении функционала является (i) насколько мы упрощаем и насколько быстро, а также (ii) совместимость с предыдущими версиями. Значимость Ethereum как блокчейна заключается в том, что это платформа, на которой вы можете развернуть приложение и быть уверенным, что оно будет работать многие годы вперед. В то же время, возможно зайти слишком далеко в достижении этой идеи.перефразировать Уильяма Дженнингса Брайана, «распять Ethereum на кресте обратной совместимости». Если есть только два приложения во всей сети Ethereum, которые используют определенную функцию, и у одного из них нет пользователей в течение нескольких лет, а другой почти не используется и обеспечивает общую стоимость в $57, то мы просто должны удалить эту функцию и, при необходимости, возместить пострадавшим $57 из своего кармана.
Более широкая социальная проблема заключается в создании стандартизированного конвейера для внесения изменений, не нарушающих обратную совместимость, в случае неэкстренных ситуаций. Один из способов решения этой проблемы - изучение и расширение существующих прецедентов, таких как процесс SELFDESTRUCT. Конвейер выглядит примерно следующим образом:
Между шагом 1 и шагом 4 должно быть многолетнее конвейерное производство с ясной информацией о том, какие элементы находятся на каком шаге. На этом этапе существует компромисс между тем, насколько энергичным и быстрым является конвейер удаления функций по сравнению с более консервативным и направленным на развитие других областей протокола, но мы все еще далеки от Паретовского фронта.
Одним из основных наборов изменений, которые были предложены для EVM, является Формат объекта EVM (EOF). EOF вносит много изменений, таких как запрет наблюдения за газом, наблюдение за кодом (т. е. нет CODECOPY), разрешение только статических переходов. Цель - позволить EVM обновляться более сильным образом, сохраняя обратную совместимость (так как пред-EOF EVM все еще существует).
Это имеет преимущество в том, что создается естественный путь к добавлению новых функций EVM и поощрению миграции к более ограниченному EVM с более сильными гарантиями. У него есть недостаток в том, что он значительно увеличивает сложность протокола, если только мы не сможем найти способ в конечном итоге устареть и удалить старый EVM. Одним из основных вопросов является: какую роль играет EOF в предложениях по упрощению EVM, особенно если целью является уменьшение сложности EVM в целом?
Многие предложения по "улучшению" в остальной части плана также являются возможностями упрощения старых функций. Чтобы повторить некоторые примеры из вышеуказанного:
Более радикальная стратегия упрощения Ethereum заключается в том, чтобы оставить протокол без изменений, но переместить большую часть его из функций протокола в код контракта.
Самая экстремальная версия этого заключается в том, чтобы сделать Ethereum L1 "технически" только маяк цепи и ввести минимальную виртуальную машину (например.RISC-V, Каир, или что-то еще более минимальное, специализированное для доказательства систем), что позволяет любому другому создать свой собственный rollup. Затем EVM превратится в первый из этих rollups. Это иронично точно тот же результат, что и предложения по среде выполнения с 2019-20, хотя SNARK делают его значительно более жизнеспособным для фактической реализации.
Более умеренным подходом было бы сохранить отношение между цепочкой маяка и текущей средой выполнения Ethereum в нынешнем виде, но выполнить замену EVM на месте. Мы могли бы выбрать RISC-V, Cairo или другую виртуальную машину в качестве новой «официальной виртуальной машины Ethereum» и затем принудительно конвертировать все контракты EVM в код новой виртуальной машины, который интерпретирует логику исходного кода (путем компиляции или интерпретации). Теоретически, это даже может быть выполнено с версией EOF в качестве «целевой виртуальной машины».