Состояние Ethereum (Ethereum state) — это снимок всех аккаунтов и их хранилища в текущий момент: балансы, nonce, код смарт-контрактов и значения в их storage–слотах. Каждый новый блок обновляет это состояние, а в заголовок блока попадает один хеш — state root, который служит компактным «отпечатком» всей системы.
Ethereum использует account-based модель, Merkle Patricia Trie и дерево storage для каждого контракта. Всё это вместе делает состояние проверяемым и воспроизводимым для любого узла сети.
Account-based модель: какие бывают аккаунты
В Ethereum есть два типа аккаунтов (см. Ethereum и EVM):
- EOA (Externally Owned Account)
Обычный пользовательский аккаунт:
- управляется приватным ключом;
- не содержит кода;
- может отправлять транзакции и владеть ETH/токенами.
- Контрактный аккаунт (contract account)
Адрес, за которым:
- закреплён байткод смарт-контракта;
- хранится собственное хранилище (storage);
- код выполняется при входящих вызовах.
Логически у любого аккаунта есть одно и то же базовое представление, включающее:
- nonce — счётчик транзакций/созданных контрактов;
- balance — баланс в wei;
- storageRoot — корень дерева хранилища для контракта;
- codeHash — хеш кода (пустой для EOA).
Что такое состояние Ethereum на уровне узла
Для полного узла состояние — это:
- дерево аккаунтов (account trie), включающее все адреса и их данные;
- для каждого контрактного аккаунта — собственное дерево хранилища (storage trie);
- дополнительная информация, связанная с блоками и логами (но именно account trie определяет глобальное «state» сети).
После применения всех транзакций блока клиент:
- выполняет код через EVM;
- обновляет балансы, nonce, storage-слоты;
- пересчитывает корень дерева аккаунтов;
- записывает полученный state root в заголовок блока.
Этот хеш — единственный элемент в заголовке, который «подписывает» всё состояние сети на данный момент.
Merkle Patricia Trie для аккаунтов
Для компактного и проверяемого хранения состояния в Ethereum используется Merkle Patricia Trie (см. также Merkle Patricia Trie).
Идея:
- все аккаунты (по адресам) организованы в дерево, ключом служит 20-байтовый адрес;
- в узлах хранятся RLP-кодированные данные аккаунта (balance, nonce, storageRoot, codeHash);
- на каждом уровне вычисляются хеши, пока сверху не получится один корень — state root.
Свойства Merkle Patricia Trie:
- узел может доказать, что конкретный аккаунт с определёнными данными действительно входит в состояние, предъявив Merkle-доказательство;
- лёгкие клиенты и сторонние сервисы могут проверять данные без хранения полного состояния, ориентируясь на state root из заголовков блоков.
Хранилище контрактов и storage-слоты
У каждого контрактного аккаунта есть отдельное дерево хранилища:
- storage trie строится по тем же принципам Merkle Patricia Trie;
- ключом выступает индекс слота (256-битное значение);
- значение — данные слота (256-битное слово).
На уровне EVM storage — это отображение slot → 32 байта. То, как именно значения переменных попадают в слоты, определяется компилятором языка (см. Storage layout в Solidity и шпаргалка по storage layout).
Для смарт-контрактов это означает:
- каждая запись sstore(slot, value) меняет локальное дерево storage;
- хеш корня этого дерева (storageRoot) хранится в аккаунте контракта;
- при изменении хотя бы одного слота меняется и storageRoot, а затем и общий state root.
State root в заголовке блока
В заголовке каждого блока есть поле stateRoot:
- это Merkle-корень дерева аккаунтов после применения всех транзакций блока;
- любой узел, имея:
- предыдущее состояние,
- список транзакций,
- правила EVM,
может вычислить новое состояние и убедиться, что его корень совпадает с заявленным stateRoot.
Зачем это нужно:
- детерминируемость — все честные узлы приходят к одному и тому же state root при одинаковых входных данных;
- проверяемость — можно строить Merkle-доказательства существования аккаунта или значения в storage без полного состояния;
- базис для L2 и мостов — rollup’ы и кросс-чейн протоколы часто ссылаются на state root (или его аналог) как на источник истины (см. обзор L2-роллапов и решения data availability).
Как транзакции изменяют состояние
Каждая транзакция в Ethereum:
- считывает текущее состояние:
- баланс отправителя;
- код и storage целевых контрактов;
- выполняется в EVM:
- обновляются балансы (переводы, комиссии);
- изменяются storage-слоты смарт-контрактов;
- пишутся события (events) в лог;
- в конце узел фиксирует новое состояние и пересчитывает state root.
Если транзакция невалидна (out-of-gas, revert), состояние откатывается к прежнему состоянию, и state root не меняется.
Роль состояния для L2, клиентов и аналитики
Понимание структуры состояния важно не только для валидаторов:
- Лёгкие клиенты
Могут синхронизироваться по заголовкам и получать доказательства по отдельным аккаунтам, не храня весь state.
- L2-решения и мосты
При дизайне rollup’ов, мостов и протоколов с cross-chain логикой нужно учитывать:
- модель состояния на L1;
- способы получения и проверки state root и отдельных веток Merkle-дерева.
- Аналитика и индексаторы
Сервисы типа block-explorer’ов и аналитических панелей читают состояние напрямую из storage-слотов и деревьев, строя свои индексы поверх Merkle-структур.
- Account abstraction и кошельки нового поколения
Новые модели аккаунтов (см. account abstraction) по-прежнему строятся на той же базе — состояние сети описывается набором аккаунтов и их storage.
