EVM-функционал на Solana: введение
Марина Гурьева, CEO Neon Labs, рассказала про особенности запуска EVM в сети Solana на EVM-Compatible Meetup в Тбилиси. Мы сделали краткий конспект, из которого можно узнать: чем отличаются Solana и Ethereum; как происходят транзакции в Solana пошагово; как запустить Ethereum dApp на Solana; как работает Neon EVM. Приятного чтения! ✨
О Neon Labs
Neon Labs занимается разработкой Neon EVM c декабря 2020 года. Перед Neon стоит нетривиальная задача — портировать EVM на Solana. Планируем запуститься на майннете Solana в конце ноября или в начале декабря. В Solana Devnet эта версия работает с апреля, проводим тестирования dApp с Ethereum — деплоим их в наше решение. В докладе расскажу, как именно мы решили «поженить» Solana и Ethereum.
Чем отличаются блокчейны

Представим две галактики. Одна из них знакома нам, мы в ней прямо сейчас находимся. А вторая — находится в 100 млн световых лет от созвездия Рыбы, она устроена и выглядит совсем иначе. Наглядно видно, что галактики бывают разными. Точно так же различаются и блокчейн-системы: Solana и Ethereum — кардинально разные. Они отличаются и архитектурно, и с точки зрения технической реализации. На Solana, например, доступно параллельное выполнение транзакций, но при этом существуют ограничения на количество инструкций в рамках одной транзакции — чего нет в Ethereum.
Из чего состоит Solana

На слайде классическая программа Solana. Существует два типа аккаунтов: data account и program account. Они отличаются флагом, который позволяет маркировать программы. Программы — это те программы, с которыми вы имели дело, если занимались когда-то операционными системами.
Структура программы достаточно простая:
- адрес (у адреса есть Program Derived Address, который не имеет ключей и выбирается в пределах эллиптической кривой и отдается под управление программы);
- лампорты (lamports, единицы измерения внутри Solana);
- rent epoch (время списания лампортов). Нужно держать достаточное количество лампортов, чтобы Solana не удалила случайно программу;
- владелец;
- data (родной машиной для Solana является Berkley Packer Filter (BPF), поэтому там содержится BPF bytecode);
- флаг, маркирующий программу.
Это базовая структура. Программный код EVM, де-факто, представляет собой смарт-контракт на Solana. То есть — это нативный смарт-контракт для Solana и может быть запущен на ней.
Как выглядит программа в Neon EVM

Из каких элементов состоит Neon EVM:
- программа: Neon EVM
- владелец программы: Neon DAO, которое начнет работать после запуска в майннете;
- BPF bytecode data + Ethereum Virtual Machine. EVM позволит добиться выполнения контрактов Ethereum, которые попали в Solana;
- выставлен флаг на то, что это — программа;
- три типа аккаунтов: простой аккаунт соответствует аккаунту пользователя в Ethereum (в поле «данные» собрана информация про аккаунты, релевантная с точки зрения аккаунта: address, nonce, balance etc.); Neon contract соответствует смарт-контрактам Ethereum (данные, релевантные любому смарт-контракту Ethereum — EVM bytecode);
- Neon contract data — данные, которые ассоциируются с предыдущим контрактом.
Как проходят транзакции Neon внутри Solana

NEON EVM — смарт-контракт на Solana и имеет дело поэтому с транзакциями этой сети в первую очередь. Наша задача сформировалась таким образом: получив на входе «эфироподобную» NEON-транзакцию каким-то образом превратить ее в «солановскую» транзакцию.
Транзакция NEON, запакованная в транзакцию Solana:
- стандартная структура транзакции Solana: заголовок, account list, program index, data, подписи и так далее.
- Для Solana поле «account list» — критичное поле, поскольку параллелизация выполнения возможна только при блокировке аккаунтов, задействованных в той или иной транзакции. То есть, Solana блокирует аккаунты, которые в этом списке указаны и дальше может выполнять параллельно вычисления для тех аккаунтов, которых нет в списке.
- Есть программный индекс (program index), который указывает на NEON EVM.
- data — «эфироподобная» транзакция с nonce, gasPrice, gasLimit, value etc.
Как запустить Ethereum dApp на Solana

- Допустим, контракт уже задеплоен и это, например, Uniswap.
- Пользователь приходит в Neon через привычный ему инструмент, например, Metamask.
- Он запускает транзакцию через Metamask, де-факто, транзакцию Neon.
- Эта транзакция после подписи отправляется не на ноду Solana, а на специальный сервер Neon proxy с Neon RPC endpoint.
- После этого она выходит «упакованная» в транзакцию Solana и попадает на Solana RPC endpoint.
- Дальше идет вызов на Neon EVM-программу.
Как включить все аккаунты в транзакцию Solana

Как известно, в Ethereum нет такого свойства. Поэтому задача Neon Proxy эмулировать выполнение транзакции, чтобы достать список аккаунтов, вовлеченных в выполнение транзакции. Когда транзакция Neon попадает в прокси, идет ончейн-вызов на EVM и происходит эмуляция для доступа к данным о задействованных аккаунтах. Далее транзакция посылается на Solana RPC endpoint.
Как происходит параллельное выполнение

Никакой дополнительно магии нет — на ноды Solana поступают транзакции Solana и каждая «солановская» нода вызывает Neon EVM смарт-контракт. Собственно, это стандартный для Solana способ экзекуции транзакции в параллели. Происходит проверка на блокировку аккаунтов, и если множество блокируемых аккаунтов не совпадает, то транзакции выполняются в параллели.
Как выполнить длинные транзакции Ethereum в Solana

У Solana есть ограничение, с точки зрения имплементации EVM, — на количество инструкций в рамках одной транзакции. Поэтому длинные Ethereum-транзакции просто не помещаются в одну транзакцию Solana.
Нам пришлось применить итеративное выполнение — делать бэк транзакций и выполнять их шаг за шагом, чтобы финализировать одну транзакцию Neon.
- Neon Proxy эмулирует и запускает транзакцию.
- Она, в виде «солановской» транзакции попадает на ноды Solana, запускается Neon EVM. Читаются аккаунты.
- Сохраняется EVM state в специальном аккаунте Neon state, который нам тоже пришлось специально создать
- Посылается receipt, что транзакция Neon не завершена. Это критично, потому что, когда прокси получается такой receipt он запускает продолжение транзакции.
- Восстанавливается EVM state из аккаунта Neon state. Совершаются новые действия и снова идет сохранения.
- Итерации продолжаются до тех пор, пока транзакция не будет выполнена полностью.
- Последняя часть транзакции важна потому, что измененные аккаунты сохраняются в Solana state.
- Совершается разблокировка заблокированных аккаунтов.
- Посылается Receipt с информацией об успешном или неуспешном выполнении транзакции.
Как обеспечить атомарность больших транзакций в Solana

В этом случае атомарность обеспечивается стандартными средствами Solana — особенности сети позволяют фейлить транзакции, у которых есть наложение с точки зрения заблокированных аккаунтов.
Все, что я сказала выше — мы уже реализовали. Но в идеальном мире нам хотелось бы выполнять в параллели «эфироподобные» транзакции с одними теми же контрактами Solana. Например, контрактами ERC20, которые поддерживаются USDT, USDC и т.д., они часто используются. В том методе, который я описала, нам нужно их заблокировать, поэтому все ERC20-транзакции будут выполняться не в параллели, а друг за другом.

Мы придумали способ под названием Optimistic Parallel Execution. Он красив с точки зрения реализации и позволяет сделать экзекуцию контрактов параллельной, даже при обращении к одним и тем же контрактам.
- Когда у параметра появляются значения, сохраняются параметры, на каком шаге они появились.
- Дальше проверяется, произошло ли изменение того или иного значения параметра на каком-то шаге или нет.
- И в случае, если есть изменение значения на каком-то шаге какого-то параметра, то идет возврат за шаг до того, когда первый раз был прочитан этот параметр. То есть, по изменению мы понимаем, что в параллели была реализована транзакция, которая изменила параметр. То есть так транзакция, которая находится на исполнении, должна быть выполнена еще раз с того момента, когда параметр был впервые зафиксирован.
- Промежуточные изменения записываются в Neon state и запись происходит в Solana state на последнем шаге.
