Skip to content

Latest commit

 

History

History
133 lines (87 loc) · 15.3 KB

File metadata and controls

133 lines (87 loc) · 15.3 KB

Intro

Автор: Павел Найданов 🕵️‍♂️

Если ты совсем новичок в блокчейн разработке, я предлагаю разобраться с самого начала и прочитать статью Прити Касиредди "How does Ethereum work?". Однако и разработчику со стажем это может быть полезным. Я уверен он сможет найти интересные вещи для себя в этой статье.🙃

Ethereum

Ethereum - это сеть, где каждый участник сети хранит копию состояния единственного канонического компьютера(называемого виртуальной машиной Ethereum или EVM). Любой участник сети может транслировать запрос этому компьютеру на выполнение произвольных вычислений.

Запросы на вычисление называются транзакциями. Запись всех транзакций и текущего состояния EVM сохраняется в блокчейне, который, в свою очередь согласовывается всеми участниками сети.

Подробнее про ethereum можно прочитать тут.

Подробнее про анатомию транзакций можно прочитать тут.

Account based model

Мы знаем, что Ethereum в отличие от Bitcoin поддерживает стратегию аккаунтов.

Аккаунты нужны для хранения балансов пользователей. Аккаунты и балансы аккаунтов хранятся в большой таблице в EVM. Они являются частью общего состояния EVM.

Сущность аккаунт содержит следующие поля:

  1. Баланс. Количество эфира в Wei.
  2. Nonce. Счетчик транзакций этого аккаунта.
  3. Storage root. Также известен как хэш хранилища.
  4. Code hash. Этот хэш ссылается на code аккаунта на виртуальной машине. По сути, это 256-битный хэш корня «дерева Меркла Патрисии», кодирующего содержимое хранилища аккаунт.

В природе EVM аккаунты делятся на два типа:

  1. Внешний EOA(Externally Owned Account)
  2. Смарт-контракт

Оба этих типа аккаунтов могут не только получать, хранить и отправлять эфиры, но и взаимодействовать с другими смарт-контрактами.

Ключевое отличие аккаунтов типа "EOA" и "смарт-контракт" заключается в следующем:

  1. Адрес EOA создается на основе приватного ключа пользователя. Адрес контракта создается на основе адреса деплоера, байт-кода и nonce.
  2. Поля code hash и storage root заполняются только для аккаунта типа "смарт-контракт". Для EOA аккаунтов эти поля пустые.

Подробнее про аккаунты можно почитать тут.

EVM

Ethereum Virtual Machine — это глобальный виртуальный компьютер, состояние которого хранит (и с которым согласовывается) каждый участник сети Ethereum. Любой участник может запросить выполнение произвольного кода в EVM.

С точки зрения opcodes, EVM - это полная по Тьюрингу стековая машина, отвечающая за выполнение кода смарт-контрактов.

Смарт-контракт — это набор инструкций. Каждая инструкция представляет собой код операций(со своей удобной мнемоникой, своего рода текстовым представлением присвоенных им значений от 0 до 255). Когда EVM выполняет смарт-контракт, она последовательно считывает и выполняет каждую инструкцию.

Упрощенная архитектура EVM

Упрощенно можно представить внутреннее устройство EVM схемой ниже. Забегая вперед скажем, что объекты на схеме EVM code и Storage это не что иное, как то на что ссылаются code hash и storage аккаунта. Я говорил про них в разделе выше, где рассказывал про аккаунты.

// Простая stack-based архитектура EVM

На схеме выше мы видим две крупных области:

  • Machine state(volatile). Эта область содержит непостоянные объекты, которые будут созданы в рамках контекста вызова. Под контекстом вызова можно понимать исполнение любого набора инструкций, полученных из байт-кода смарт-контракта.
  • World state(persistent). Эта область содержит объекты, которые не зависят от контекста вызова.

Machine state включает:

  • PC(Program counter). Решает, какую инструкцию из области code EVM должна прочитать следующей. PC обычно увеличивается на один байт, чтобы указать на следующую инструкцию. За исключением всего нескольких команд. Я имею ввиду команды JUMP, JUMPI.
  • Stack. Список инструкций смарт-контракта. Максимально может включать 1024 инструкции. Размер инструкции равен 32-м байтам. Для каждого вызова в рамках контекста вызова создается один Stack. Он уничтожается, когда контекст вызова завершается.
  • Memory. Также как и Stack создается в начале вызова в рамках контекста и очищается по окончанию.

World state включает:

  • Code. Это область где хранятся инструкции. Код - это байты данных, прочитанные, интерпретированные и выполненные EVM во время исполнения смарт-контракта. Код в этой области неизменяем. Это показано аббревиатурой ROM(Read-only memory)
  • Storage. Хранилище отвечает за хранение состояния блокчейна. По сути, это мапа(сопоставление) 32-байтовых слотов с 32-байтовыми значениями. Хранилище постоянно для смарт-контракта. Любое значение записанное кодом смарт-контракта сохраняется после окончания вызова. Каждый контракт имеет собственное хранилище и не может читать или изменять хранилище из другого контракта

Для более простого понимания можно провести следующие аналогии. Stack имеет ограничение на хранение 1024-х инструкций. Используется stack больше для передачи значений функциям function(arg,arg2) и выполнение функций. Из-за ограничений stack сложные комбинации opcodes используют память контракта(memory) для извлечения или передачи данных. Однако память непостоянна(когда выполнение вызова функции закончится, память очистится) и подходит для хранения объявленных переменных. Чтобы хранить данные неограниченное время и сделать их доступными для выполнения в следующих вызовах нужно использовать storage. По сути это общедоступная база данных. Можно даже считывать значения извне без необходимости отправлять транзакции. Однако запись в хранилище - это одна из самых дорогостоящих операций.

Итог:

  • Stack. Хранение аргументов функции. Плюс операции выполнения.
  • Memory. Краткосрочное хранение объявленных переменных в рамках контекста одного вызова функции.
  • Storage. Долгосрочное хранение данных в рамках жизни блокчейна. Данные доступны в рамках любых контекстов вызова функции и для считывания извне.

Можно на все это посмотреть со стороны официальной реализации Ethereum протокола на go:

  1. Opcodes
  2. Stack
  3. Memory

Выполнение инструкций

Помним, что EVM - стековая машина. Стек здесь играет ключевую роль. На схеме ниже показано выполнение некоторого набора инструкций.

Этот алгоритм можно описать следующим образом:

  1. В рамках контекста вызова создаются следующие объекты machine state: memory, stack, program counter.
  2. Program counter получает команду на инициализацию исполнения инструкций.
  3. Из EVM code берутся инструкции и разбиваются на операции(opcodes).
  4. Каждая операция попадает в stack.
  5. Операции попавшие в stack начинают выполняться.
  6. Выполнение каждой операции может задействовать storage или memory.

Важно! В этой схеме мы опускаем проверку gas. Каждый opcode стоит несколько единиц gas. Gas помогает поддерживать безопасность сети Ethereum. Расчет gas выходит за рамки этой схемы.

Ключевые вещи

Solidity код преобразуется → Байт-код → Opcodes

Аккаунты бывают двух типов: EOA и смарт-контракты. Только смарт-контракты имеют код.

Понимание, как работает EVM. Под каждый контекст вызова создается Memory и Stack. При этом EVM code неизменяем. Storage постоянен, но может быть изменен.

Для тех, кто верит в себя

Есть блог пользователя под ником noxx, который подготовил серию статей на тему углубленного изучения EVM. Это немножко галопом по Европе, потому что материала много и он не простой. Советую читать разработчикам с опытом.

  1. EVM Deep Dives: The Path to Shadowy Super Coder 💻 - Part 1
  2. EVM Deep Dives: The Path to Shadowy Super Coder 💻 - Part 2
  3. EVM Deep Dives: The Path to Shadowy Super Coder 💻 - Part 3
  4. EVM Deep Dives: The Path to Shadowy Super Coder 💻 - Part 4
  5. EVM Deep Dives: The Path to Shadowy Super Coder 💻 - Part 5
  6. EVM Deep Dives: The Path to Shadowy Super Coder 💻 - Part 6

Нашелся добрый человек по имени Тёма. Он сделал перевод статей под лозунгом "EVM для задротов".

  1. EVM для задротов
  2. EVM для задротов 2
  3. EVM для задротов 3
  4. EVM для задротов 4
  5. EVM для задротов 5
  6. EVM для задротов 6

Links

  1. Ethereum virtual machine
  2. About the EVM
  3. Интересный сборник иллюстраций