Интерактивные объяснения исполнительного слоя
Исполнительный слой Ethereum —
понятно и прозрачно.
Обычно Ethereum преподают как чёрный ящик: с одной стороны — плотные спецификации, с другой — туториалы прикладного уровня, а между ними пусто. Whitebox живёт ровно в этом промежутке — по одному механизму за раз, каждый с живым виджетом, который можно разобрать на части. Написано практиком для инженеров, которые хотят по-настоящему понять, как всё работает под капотом.
Для кого
- Инженеров, которые читают код и рассуждают о системах
- Операторов узлов и инфраструктурщиков
- Будущих контрибьюторов в ядро / протокол
Не для
- «Любопытствующих к крипте» новичков
- Начинающих в Solidity / dApp
- Тех, кто хочет разговоров о цене
Вы могли бы изобрести Ethereum
Одна страница, одно непрерывное построение. Начнём с единственной общей таблицы, покажем в анимации единственный её изъян, исправим ровно его — и повторим, пока программируемый мировой компьютер на стейке не выпадет как единственное, чем эта таблица могла стать.
Открыть разбор →Исполнительный слой: объяснение
Вечнозелёный, упорядоченный путь по тому, как на самом деле работает исполнительный слой Ethereum. Написано один раз и надолго — это не конвейер контента.
- 01 Вы могли бы изобрести Ethereum Одна страница, одно непрерывное построение. Начнём с единственной общей таблицы, покажем в анимации единственный её изъян, исправим ровно его — и повторим, пока программируемый мировой компьютер на стейке не выпадет как единственное, чем эта таблица могла стать. Начните здесь
- 02 EVM: превращаем аккаунт в компьютер Глава 1 дала нам аккаунты и неподделываемые подписанные транзакции — но транзакция всё ещё могла делать только одну жёстко закодированную вещь: перемещать ценность. Эта глава выводит машину, которая позволяет аккаунту выполнять *любую* программу: стек, способ платить за вычисления и три места для хранения данных. Постройте её — и EVM появится сама собой. Start here
- 03 Как узел синхронизируется Вы устанавливаете новый клиент, а сеть работает уже годы. То, как узел наверстывает упущенное — и пять способов, которыми он мог бы это делать — это аккуратная маленькая деривация: начинаем с самого медленного и параноидального метода, а затем по делу зарабатываем каждое сокращение. Сеть и синхронизация
- 04 Состояние и trie: один хеш для всего мира EVM вычисляет над хранилищем — но где это хранилище на самом деле живёт, и как сеть незнакомцев соглашается, что оно побайтово идентично, не пересылая друг другу гигабайты? Эта глава выводит дерево Меркла-Патриции: структуру, которая сжимает всё мировое состояние в один 32-байтовый корень, который можно дёшево обновлять и против которого можно доказывать. Start here
- 05 Flat DB — чтение состояния за один прыжок Протокол говорит, что состояние — это trie. Он ни слова не говорит о том, как разложить это trie на диск и читать его миллиарды раз — и именно здесь клиенты негласно соревнуются. Flat DB от Nethermind, созданный Muhammad Amirul Ashraf, — это ответ с нуля. Устройство клиента
- 06 Как работает консенсус В кульминационной статье мы разобрали, почему Proof of Stake работает. Эта страница — механизм, который его запускает: как миллион валидаторов без единого лидера по очереди создают один блок каждые двенадцать секунд и соглашаются с результатом. Слоты, комитеты, эпохи, финальность, строители блоков и вся жизнь валидатора. Консенсус
- 07 EIP-1559: рынок комиссий, который сам себя оценивает До 1559 каждая транзакция вслепую участвовала в аукционе первой цены — переплати или застрянь. Выведем замену шаг за шагом: объявленная цена, термостат, который её выставляет, эластичные блоки для всплесков и сжигание, устраняющее последний плохой стимул. EIPs
- 08 EIP-4844: блобы — дешёвые данные для роллапов Роллапы обязаны публиковать свои данные на L1, чтобы кто угодно мог их проверить, — но как постоянная calldata это было разорительно дорого. Выведем блобы шаг за шагом: отдельная полоса для данных, коммитмент, чтобы её связать, отсечение через ~18 дней и собственный рынок комиссий. EIPs
- 09 EIP-4337: абстракция аккаунта без изменения протокола EOA негибки: один ключ, газ только в ETH, одно действие за раз. Абстракция аккаунта делает аккаунты программируемыми — и EIP-4337 добивается этого без единого изменения консенсуса, используя транзакцию более высокого уровня, отдельный мемпул, бандлеров и синглтон EntryPoint. EIPs
- 10 EIP-7702: даём вашему EOA суперспособности на месте Абстракция аккаунта (4337) создала смарт-аккаунты — но чтобы ими пользоваться, приходилось переезжать на новый адрес. EIP-7702 обновляет ваш существующий EOA прямо на месте: вы подписываете делегирование, ваш аккаунт указывает на контракт, и вызов выполняет код этого контракта от вашего имени — тот же адрес, тот же ключ. EIPs
- 11 EIP-2718: конверт, позволивший Ethereum добавлять типы транзакций У Ethereum был ровно один формат транзакции — RLP-список. Каждая новая функция (списки доступа, рынок комиссий 1559, блобы, set-code) требовала новой формы, и декодерам приходилось угадывать, какую из них они видят. EIP-2718 добавляет в начало каждой транзакции один байт типа, превращая один жёсткий формат в расширяемое, версионированное семейство. EIPs
- 12 EIP-155: привязываем подпись к своей цепочке Подпись Ethereum до EIP-155 говорила, кто подписал и что подписал — но никогда не говорила, для какой сети это было. Так что в точности одни и те же подписанные байты были валидны на каждой цепочке, разделяющей ваш адрес, и транзакцию можно было воспроизвести через форк вроде ETH/ETC. EIP-155 вплетает chainId в то, что вы подписываете, так что подпись оказывается заперта на одной цепочке. EIPs
- 13 EIP-4895: как забрать застейканный ETH без транзакции После The Merge 32 ETH валидатора и его награды жили на консенсус-слое без пути домой. Обычная транзакция не может их сдвинуть — нет EOA, нет ключа, нечего подписать на слое исполнения. EIP-4895 переворачивает поток: консенсус-слой сам вталкивает выводы в каждый блок, а EVM просто пополняет баланс. EIPs
- 14 EIP-3675: замена двигателя Ethereum на лету Proof of work защищал Ethereum, сжигая энергию — безопасность равнялась хешрейту. The Merge заменил этот двигатель на proof of stake, сохранив тот же самый EVM, аккаунты и историю. Хитрость в том, чтобы не запускать PoS «на месте». Сначала запустить его на отдельной beacon-цепочке, а затем передать штурвал при фиксированной сложности. EIPs
- 15 EIP-1153: черновик, который живёт ровно одну транзакцию Контрактам часто нужно передавать данные между вызовами внутри одной транзакции — блокировки от реентрантности, временные апрувы, флэш-бухгалтерия. Единственным общим изменяемым хранилищем было постоянное storage: ≈20 000 газа за слот, записанное на диск навсегда, хотя значение выбрасывается по окончании транзакции. EIP-1153 добавляет временное хранилище (transient storage) — та же идея, но исчезает в конце транзакции. EIPs
- 16 EIP-4788: учим EVM доверять beacon-цепочке После The Merge консенсус-слой хранит ровно те данные, которые нужны контрактам стейкинга и рестейкинга, — балансы валидаторов, статусы, слэшинги, — но EVM не видит из этого ничего, и проекты опирались на доверенные оракулы. EIP-4788 раскрывает корень родительского beacon-блока внутри EVM, так что контракт может проверить любой факт консенсуса доказательством Меркла — и без оракула. EIPs
- 17 EIP-2929 и 2930: цена доступа к состоянию по реальным затратам Чтение состояния — самая дорогая для диска операция узла, но EVM брала за неё фиксированную, слишком низкую цену — так что атакующий мог тронуть тысячи слотов почти бесплатно и поставить каждый узел на колени. Решение оценивает первое касание по реальной цене, а повторы делает дешёвыми; списки доступа позволяют транзакции заранее объявить, чего она коснётся. EIPs
- 18 EIP-7251: позволяем одному валидатору держать больше 32 ETH Стейк каждого валидатора был ограничен потолком в 32 ETH заработывающего баланса, так что крупному стейкеру приходилось запускать десятки или сотни отдельных валидаторов — раздувая набор валидаторов и нагрузку консенсус-слоя, и заставляя вознаграждения останавливаться в накоплении на отметке 32. EIP-7251 поднимает потолок до 2048 ETH и позволяет валидаторам консолидироваться. EIPs
- 19 EIP-7: DELEGATECALL — занимаем код, сохраняем свой контекст Контракты хотели переиспользовать логику общей библиотеки, не копируя её байткод в каждый из них. Но обычный CALL выполняет эту логику в собственном хранилище библиотеки — бесполезно для библиотеки, которая должна работать с вашими данными. DELEGATECALL выполняет заимствованный код в контексте вызывающего — и тем самым тихо изобрёл библиотеки, прокси и обновляемые контракты. EIPs
- 20 EIP-150: когда газ стал параметром безопасности В 2016 году атакующий обнаружил, что самые дорогие операции Ethereum — чтение хранилища, загрузка аккаунтов — были оценены намного ниже того, чего они реально стоили узлу. Несколько дешёвых транзакций могли поставить каждый узел на Земле на колени. EIP-150 переоценил их — и тем самым превратил газ из номинальной платы в линию обороны. EIPs
- 21 EIP-140: REVERT — дёшево проваливаться и объяснять почему До Byzantium контракт, столкнувшийся с плохим условием, имел только один грубый вариант — throw: он откатывал работу, но при этом сжигал весь газ вызывающего до последней капли и не возвращал никакого объяснения. REVERT сохраняет откат, возвращает газ и позволяет контракту вернуть ошибку. Каждый require("reason"), кастомная ошибка и try/catch, которые вы когда-либо писали, — потомки этого опкода. EIPs
- 22 EIP-1014: CREATE2 — знать адрес до того, как контракт существует Раньше адрес контракта выводился из nonce развёртывающего аккаунта — счётчика, меняющегося с каждым развёртыванием, так что предсказать, куда попадёт контракт, было невозможно. CREATE2 выводит адрес из развёртывающего, выбранной вами соли и самого кода: без nonce. Теперь можно вычислить адрес, пополнить его и раздать до того, как контракт вообще развёрнут. EIPs
- 23 EIP-1344: CHAINID — защита от повтора для подписей контрактов EIP-155 привязал транзакции к их сети. Но контракты всё чаще верифицируют собственные подписанные сообщения — безгазовые одобрения, мета-транзакции, офчейн-ордера — а у них не было никакой привязки к сети, поэтому подпись, действительная для контракта в одной сети, повторно проходила в другой. CHAINID открывает EVM доступ к id текущей сети, так что контракт может привязать свои подписи к сети, на которой он реально работает. EIPs
- 24 EIP-3529: закрываем лазейку газовых возвратов Раньше освобождение хранилища давало солидный газовый возврат — хорошая идея, которую начали эксплуатировать. Контракты копили возвраты как «газовые токены», а возвраты позволяли блоку выполнять почти вдвое больше реальной работы, чем предполагал его газовый лимит. EIP-3529 не отменяет возвраты — он их урезает и ограничивает, так что уборка состояния всё ещё немного окупается, но эксплойт умирает, а блоки остаются предсказуемыми для нового рынка комиссий. EIPs
- 25 EIP-3541: резервируем байт для будущего Как оставить место для добавления совершенно нового формата контрактов позже, если каждый возможный первый байт кода уже является валидным опкодом? Никак — если только не сделать один байт запретным намеренно. EIP-3541 запрещает деплой нового кода, начинающегося с 0xEF, превращая этот байт в зарезервированное пространство, на котором строятся более поздние апгрейды (EOF и делегирующий дескриптор EIP-7702). EIPs
- 26 EIP-3855: PUSH0 — опкод для числа, которое нужно всем Положить константу ноль на стек — одна из самых частых операций в коде EVM, и до 2023 года для неё не было отдельной инструкции. Компиляторы либо тратили лишний байт на PUSH1 0, либо прибегали к хаку. PUSH0 — однобайтовый опкод, который делает ровно одно дело, а поскольку ноль встречается повсюду, эта крошечная экономия накапливается в каждом контракте. EIPs
- 27 EIP-6780: обезвреживаем SELFDESTRUCT SELFDESTRUCT мог стереть код контракта и освободить его адрес — что позволяло переразвернуть другой контракт по тому же адресу («метаморфный» контракт) и превращало «контракт может просто исчезнуть» в головную боль для всего дизайна состояния Ethereum. Полное удаление опкода сломало бы существующее, поэтому EIP-6780 его ограничивает: он по-настоящему удаляет только если контракт был создан в той же транзакции. EIPs
- 28 EIP-196/197: доказательства с нулевым разглашением on-chain Верификация zk-SNARK означает вычисления спаривания на эллиптических кривых — тысячи операций над полем, которые, будучи записаны как EVM-байткод, стоили бы больше газа, чем вмещает целый блок. EIP-196 и 197 добавляют эту математику как нативные прекомпайлы, так что контракт может проверить доказательство за несколько дешёвых вызовов. Это тихий фундамент приватности on-chain и каждого validity-роллапа. EIPs
- 29 EIP-214: STATICCALL — вызов, который обещает ничего не трогать Контракты постоянно вызывают другие контракты просто ради чтения значения — цены, баланса, результата view-функции. Но обычный вызов позволяет вызываемому делать что угодно, включая изменение состояния или повторный вход в вас. STATICCALL — это вызов, для которого EVM гарантирует режим только для чтения: любая попытка изменить состояние внутри него откатывается. Маленькая гарантия, на которой незаметно держатся оракулы, view-функции и защита от reentrancy. EIPs
- 30 Altair: sync-комитеты, или как телефон верифицирует Ethereum Proof of stake защищён сотнями тысяч валидаторов — прекрасно для безопасности, безнадёжно для лёгкого клиента, который не может отследить их всех. Altair добавляет sync-комитет: небольшую, ротирующуюся группу из 512 валидаторов, подписывающую каждый блок, — так клиент с ограниченными ресурсами проверяет одну агрегированную подпись вместо миллиона аттестаций. Именно это делает возможными лёгкие клиенты, не требующие доверия, — и мосты, построенные на них. EIPs
- 31 EIP-2028: снижение цены, сделавшее роллапы возможными Вся безопасность роллапа строится на публикации данных транзакций в L1, а такие данные оценивались в 68 газа за байт — так дорого, что это стало главной статьёй расходов любого L2 и не давало экономике роллапов сойтись. EIP-2028 снизил цену до 16. Именно это изменение, в 2019 году, открыло дверь в эпоху роллапов — дверь, которую позже расширили блобы. EIPs
- 32 EIP-7002: пусть выход валидатора инициирует владелец, а не оператор После Слияния только подписывающий ключ валидатора на консенсус-слое мог инициировать его выход — но человек, которому реально принадлежит стейк, часто держит не этот ключ, а учётные данные вывода (withdrawal credential) на слое исполнения. Так что стейкинг-пул не мог принудительно вывести недобросовестного оператора, и делегированный стейкинг держался на доверии. EIP-7002 позволяет держателю учётных данных вывода инициировать выход со слоя исполнения. EIPs
- 33 EIP-4399: PREVRANDAO — откуда берётся случайность в блокчейне EVM детерминирован — у него нет опкода «случайное число», потому что каждый узел обязан вычислить одинаковый результат. Контракты, которым нужна была случайность, злоупотребляли опкодом DIFFICULTY — слабым и подверженным манипуляциям майнеров, — который исчез после The Merge. EIP-4399 переиспользует этот опкод, чтобы раскрыть RANDAO beacon-цепочки, давая контрактам настоящий (хотя и смещаемый) маяк случайности. EIPs
- 34 EIP-2537: учим EVM собственным подписям консенсус-слоя Валидаторы Ethereum подписывают BLS12-381 — кривой, выбранной за агрегируемость подписей и высокую надёжность. Но EVM знала только старую, более слабую кривую bn128, так что контракт вообще не мог проверить подпись маячной цепочки. EIP-2537 добавляет нативные прекомпайлы BLS12-381, позволяя контрактам проверять собственные подписи консенсус-слоя — недостающее звено для мостов с минимизированным доверием. EIPs
- 35 EIP-6110: помещаем депозиты валидаторов в блок Чтобы стать валидатором, вы вносите депозит 32 ETH в контракт на слое исполнения — но консенсус-слой раньше узнавал об этом депозите, опрашивая и голосуя за состояние контракта: хрупкий танец «eth1-голосования», добавлявший ~12 часов до активации. EIP-6110 помещает депозиты прямо в блок, так что консенсус-слой их просто читает. EIPs
- 36 EIP-2200: цена хранилища, отложившая форк Запись одного и того же слота хранилища трижды в одной транзакции стоила полной цены трижды — хотя на диск попадает только итоговое значение. Учёт газа по чистому эффекту это исправил, но первая попытка (EIP-1283) сделала записи настолько дешёвыми, что вызов со стипендией в 2300 газа внезапно смог менять хранилище, вновь открыв реентрантность — и это отложило Constantinople. EIP-2200 переиздаёт идею с часовым. EIPs
- 37 EIP-3860: замер кода, который производит код Байткод рантайма контракта ограничен по размеру с 2016 года — но initcode, который его производит, не был ни ограничен, ни оплачен за O(n)-работу, которую каждый узел выполняет при его обработке. Подсуньте мегабайты initcode — и вся сеть просканирует их почти бесплатно. EIP-3860 ограничивает initcode и берёт плату за слово. EIPs
- 38 EIP-2935: храним хеши блоков в состоянии Опкод BLOCKHASH видит только последние 256 блоков — около 51 минуты. Старше этого он возвращает ноль. Но L2, проверяющим (provers) и лёгким клиентам нужно заглядывать глубже, а клиентам без состояния нужны эти хеши прямо в состоянии, а не в специальном кеше заголовков. EIP-2935 помещает их в кольцевой буфер внутри системного контракта. EIPs
- 39 EIP-5656: опкод копирования памяти, которого у EVM никогда не было Копирование диапазона памяти — одна из самых базовых вещей, которые делает программа, — и всё же годами у EVM не было для этого инструкции. Контракты либо гоняли многословный цикл MLOAD/MSTORE, либо злоупотребляли identity-прекомпайлом как окольным memcpy. EIP-5656 наконец добавляет MCOPY: один опкод, одно копирование. EIPs
- 40 EIP-1052: снять отпечаток контракта одним опкодом Чтобы проверить, выполняет ли другой адрес именно тот байткод, который вы ожидаете, раньше приходилось копировать весь его код в память и хешировать его самостоятельно — операция O(размер кода) только ради 32-байтного отпечатка. EIP-1052 добавляет EXTCODEHASH, который возвращает этот хеш напрямую, за константное время. EIPs
- 41 EIP-145: даём 256-битной машине инструкцию сдвига У EVM с первого дня были AND, OR, XOR и NOT — но не было битового сдвига. Контракты имитировали сдвиг умножением и делением на степени двойки: дороже, громоздче и неспособно корректно сдвигать знаковые числа. EIP-145 добавляет нативные SHL, SHR и SAR. EIPs
- 42 EIP-3198 и EIP-7516: даём EVM читать собственный рынок комиссий EIP-1559 сделал базовую комиссию полноценной величиной протокола — вычисляемой каждый блок и сжигаемой. Но контракт не мог её прочитать: GASPRICE показывает только слитую воедино цену база+приоритет, которую заплатил отправитель. EIP-3198 добавляет BASEFEE; EIP-7516 делает то же самое для блобов. Два крошечных опкода, которые делают рынок комиссий читаемым прямо в цепочке. EIPs
- 43 EIP-7594: PeerDAS — данные блобов, не скачивая их целиком Блобы удешевили данные роллапов — но каждый узел всё ещё скачивал каждый блоб, и пропускную способность нельзя было растить. Выведем PeerDAS шаг за шагом: закодируем блоб, разрежем на колонки, оставим у себя срез и опросим остальное, пока отсутствие данных не станет почти невозможным. EIPs
- ·· Ещё разборы в работе Транзакции, газ и EVM, мемпул, сборка блоков, Engine API…