Как узел выполняет смарт-контракт в EVM и обновляет блокчейн с результатом выполнения контракта

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

Вот как я это понимаю.

Контракт компилируется в байт-код. Он развернут в цепочке. Когда пользователь вызывает этот адрес контракта для запуска функции. Узел загружает контракт в EVM в виде байт-кода. Запустите запрос, сделанный пользователем. Все происходит в EVM. Так как после выполнения на узле. Записывает ли узел новые данные в блокчейн?

Например, мой контракт имеет пустой массив.

Одна из вызываемых функций добавит запись в массив.

Новый массив содержит 1 запись и должен вернуться в цепочку. Извлекает ли узел данные из EVM, чтобы перекомпилировать и перезаписать их? Я сомневаюсь, что это так работает, поскольку EVM служит для запуска кода в виртуальной среде.

Мое лучшее предположение состоит в том, что EVM на самом деле является программой для запуска байт-кода, а затем перезаписывает новый контент в блокчейне.

Теперь, почему этот вопрос?

Я пытаюсь повторить процесс с JVM или виртуальной машиной V8 в NodeJS.

Вместо того, чтобы использовать Solidity, я компилирую Javascript в байт-код. Так что это будет похоже на мой смарт-контракт. И это работает. Я могу загрузить Javascript в виртуальную машину, вызвать функции и получить ответ.

Теперь весь этот код остается в ВМ. И вот тут я не уверен, что буду делать дальше.

В моем примере, где вызов добавляет запись в массив. Я хочу записать этот новый массив обратно в блокчейн, и я не уверен в подходе. Создает ли узел Ethereum мост между EVM и блокчейном? Или узел использует EVM и взаимодействует только с EVM, который, в свою очередь, взаимодействует с блокчейном?

Ответы (2)

В Ethereum каждый контракт имеет хранилище ключей и значений, в котором используется Patricia Trie . Корень дерева хранения сохраняется в состоянии контракта вместе с байт-кодом, балансом и одноразовым номером.

На высоком уровне язык Solidity определяет, как различные типы сопоставляются с хранилищем , поэтому во время выполнения при изменении переменной вычисляются правильные ключи.

На низком уровне EVM предоставляет примитивы для модификации этого хранилища: SSTORE(ключ, значение) и SLOAD(ключ). Где ключ и значение ровно 32 байта. Код операции SSTORE обновляет корень хранилища.

Когда транзакция завершается без возврата, окончательный корень хранилища записывается в состоянии контракта. Если транзакция возвращается, предыдущий корень хранилища восстанавливается до состояния контракта.

Можете ли вы объяснить, как EVM загружает состояние контракта (наверное, байт-код в блокчейне?) в EVM. Я бы сделал это так, чтобы получить байт-код по адресу контракта. создайте контекст с ним в виртуальной машине и выполните транзакцию. И, наконец, извлеките новое состояние из виртуальной машины и запишите его обратно в байт-код адреса контракта в блокчейне. Спасибо за ваш ответ.
@MadeInDreams Байт-код неизменяем, поэтому вам не нужно писать в ответ. В контракте из-за его размера используется Patricia Trie.
Таким образом, Patricia Trie — это своего рода память о контракте, и она хранится в блокчейне. Узел получает транзакцию, содержащую, как я полагаю, байт-кодированную инструкцию, которая отправляется в EVM для выполнения по контракту. Я ищу недостающее звено. Так же как и блокчейн, который каждый узел загружается в EVM. И узел просто вводит запрос и возвращает результат.
@MadeInDreams Состояние мира не хранится в блокчейне, в каждом блоке хранится только последний корень (состояние мира также является патрисией). Но его можно реконструировать, обрабатывая каждую транзакцию. Если узел хочет выполнить транзакцию, он должен иметь состояние мира. Мировое состояние — это сопоставление адреса с некоторыми параметрами: баланс, байт-код, корень хранилища, одноразовый номер (байт-код и корень хранилища пусты для неконтракта). Для выполнения контракта он будет считывать из состояния мира байт-код и корень хранилища, создавать с ними экземпляр EVM и выполнять вызов.
Спасибо, это то, что мне было интересно!

Каждая контрактная учетная запись имеет постоянное хранилище. EVM загружает и выполняет код контракта при вызове функции контракта. При выполнении кода EVM считывает или записывает значение хранилища контракта.

Ну как бы мне этого добиться? Загружает ли EVM всю цепочку блоков при загрузке?