Введение
В 2024 году Solana стремительно вышла на первый план: её Total Value Locked (TVL) вырос с одного миллиарда долларов США в начале года почти до пяти миллиардов, что сделало её четвёртым по величине публичным блокчейном.
По сравнению с Ethereum, Solana предлагает пользователям превосходный опыт благодаря более высокой скорости и меньшим затратам. Механизм консенсуса на основе Proof of History и асинхронная модель обработки транзакций обеспечивают разработчикам высокую пропускную способность транзакций и низкую задержку, что делает её привлекательной платформой для всевозможных децентрализованных приложений.
BlockSec специально подготовил серию «Solana Simplified», охватывающую базовые концепции Solana, практические руководства по анализу транзакций Solana и туториалы по написанию смарт-контрактов для Solana.
Являясь первой статьёй в этой серии, данный материал подробно рассмотрит ключевые концепции сети Solana, включая механизмы её работы, модель аккаунтов и транзакции, закладывая основу для написания корректных и эффективных смарт-контрактов в Solana.
eBPF: Краеугольный камень выполнения транзакций в Solana
Для написания и выполнения смарт-контрактов блокчейны, как правило, требуют языка программирования и полной по Тьюрингу вычислительной среды.
Смарт-контракты на Ethereum обычно пишутся на высокоуровневом языке под названием Solidity. Компилятор переводит их в байткод, который затем выполняется в Ethereum Virtual Machine (EVM). Вместо того чтобы разрабатывать абсолютно новую виртуальную среду и язык, Solana решила в полной мере использовать существующие передовые технологии. Виртуальная машина eBPF (extended Berkeley Packet Filter), изначально разработанная для расширения функциональности ядра Linux, была выбрана Solana в качестве базовой среды выполнения.
Так в чём же преимущества eBPF перед EVM?
В отличие от EVM, ограниченной интерпретируемым выполнением, eBPF поддерживает JIT-компиляцию (Just-In-Time), что позволяет ей транслировать байткод в машинные инструкции, которые процессор может выполнять напрямую. Такая возможность существенно повышает эффективность программ.
Кроме того, eBPF отличается эффективным набором инструкций и зрелой инфраструктурой. Разработчики могут создавать смарт-контракты на языке Rust. Используя бэкенд eBPF компиляторного фреймворка LLVM, программы на Rust можно напрямую компилировать в байткод eBPF.
Модель аккаунтов Solana
Структура аккаунта Solana
Данные хранятся в форме аккаунтов в Solana. Как показано ниже, все данные внутри Solana можно представить как огромную базу данных типа «ключ-значение». Ключами в этой базе данных являются адреса аккаунтов. Для «кошельковых» аккаунтов (то есть аккаунтов, которыми пользователи Solana управляют напрямую через пары публичный-приватный ключ) эти адреса представляют собой публичные ключи, сгенерированные с использованием системы подписи Ed25519. Значения в базе данных содержат конкретные сведения о каждом аккаунте, включая баланс и другую соответствующую информацию.
Solana использует следующую структуру, известную как AccountInfo, для описания аккаунта.
AccountInfo каждого аккаунта содержит четыре поля. Вот объяснение каждого из них:
-
Поле
Data: это поле хранит данные, связанные с аккаунтом. Если аккаунт является программой (то есть смарт-контрактом), в нём хранится байткод eBPF. В противном случае формат данных, как правило, определяется создателем аккаунта. -
Поле
Executable: это поле используется для указания того, является ли аккаунт программой. Важно отметить, что, в отличие от Ethereum, программы в Solana можно обновлять. -
Поле
Lamports: это поле фиксирует баланс токенов Solana на аккаунте. Lamports — это фактически наименьшая единица токена SOL (1 SOL = 1 миллиард Lamports). -
Поле
Owner: это поле указывает владельца аккаунта. В Solana каждый аккаунт имеет «Владельца». Например, владельцем всех «кошельковых» аккаунтов является System Program — специальный аккаунт в сети Solana, отвечающий за такие функции, как создание аккаунтов. Владелец аккаунта — единственный, кто может изменять данные аккаунта и списывать Lamports с баланса (однако любой желающий может увеличить количество Lamports, переведя средства на аккаунт).
Предопределённые аккаунты Solana
В Solana существует набор предопределённых исполняемых программ, известных как Native Programs, которые развёрнуты по фиксированным адресам. По мере обновления сети Solana эти предопределённые программы также могут обновляться. Они служат в качестве API и библиотечных функций, предоставляя специфическую функциональность внутри сети Solana.
Среди Native Programs той, с которой разработчики взаимодействуют чаще всего, является System Program. System Program предоставляет разработчикам набор инструкций, каждая из которых выполняет самостоятельную задачу. Например, разработчики могут использовать инструкцию CreateAccount для создания новых аккаунтов или инструкцию Transfer для перевода Lamports на другие аккаунты.
Ещё одна распространённая Native Programs — программа BPF Loader. Она является владельцем всех остальных программных аккаунтов и отвечает за развёртывание, обновление и выполнение пользовательских программ. Когда «кошельковому» аккаунту необходимо обновить развёрнутую им программу, это фактически осуществляется путём делегирования программе BPF Loader, поскольку только владелец программы имеет непосредственные полномочия на изменение данных.
В дополнение к Native Programs Solana также предлагает набор аккаунтов, известных как Sysvars. Эти аккаунты предоставляют программам на Solana информацию и глобальные переменные, связанные с текущим состоянием сети Solana, например, текущие часы и хэш последнего блока.
Аренда аккаунта
В блокчейне Solana каждый аккаунт должен поддерживать определённое количество Lamports в качестве минимального баланса, известного как рента. В отличие от ренты в реальной жизни, рента в Solana может быть возвращена. Чтобы данные в аккаунте были доступны в цепочке, аккаунт должен содержать соответствующее количество Lamports. Размер ренты зависит от объёма данных, занимаемых аккаунтом.
Любая транзакция, которая пытается снизить баланс аккаунта ниже суммы ренты, завершится неудачей, если только она не снижает баланс ровно до нуля. Снижение баланса до нуля означает, что рента аккаунта была возвращена, и по завершении транзакции Solana очистит данные соответствующего аккаунта в процессе сборки мусора.
🧐 Просмотр аккаунтов Solana в обозревателях Solana
Чтобы лучше понять вышеупомянутые концепции, мы использовали проект «Hello World» для Solana, чтобы развернуть программный аккаунт, который можно просмотреть с помощью обозревателя блокчейна Solana — Solscan.

Как показано на изображении выше, мы сначала можем увидеть, что аккаунт помечен как «Program». Часть Lamports была списана с баланса отправителя в качестве ренты для этого аккаунта, поэтому поле SOL Balance не пустое. Более того, поскольку созданный нами аккаунт является программой, его поле Executable установлено в значение Yes.
Возможно, вас озадачит то, что поле Executable Data хранит адрес, а не программу eBPF. Как упоминалось ранее, Solana допускает обновления программ, и это фактически реализовано через паттерн «прокси». Поскольку прямые изменения программного аккаунта изначально не разрешены, Solana создаёт отдельный аккаунт данных для хранения программы eBPF, тогда как поле Data в программном аккаунте хранит только адрес этого аккаунта данных.
Всякий раз, когда требуется обновление программы, нужно изменить только поле Data аккаунта данных. Просматривая аккаунт данных через Solscan, мы можем обнаружить, что он помечен как «Program Executable Data Account», а его поле Data хранит саму программу.

Поле Owner в разделе «More Info» — это BPF Loader, что соответствует сказанному ранее.
Кто-то может заметить, что последнее поле раздела «Overview» — это Upgrade Authority, которого нет в AccountInfo. Что это означает?
Как упоминалось ранее, «кошельковый» аккаунт делегирует обновления программ BPF Loader. Перед обновлением BPF Loader проверяет, является ли делегирующий аккаунтом, который изначально развернул программу. Поскольку Owner программного аккаунта уже установлен как BPF Loader, в нём нет места для хранения этой информации. Поэтому Solana помещает её в поле Data аккаунта данных. Вот почему в разделе «Overview» присутствует поле Upgrade Authority — это фактически адрес кошелька, развернувшего программу.
На изображении ниже показана взаимосвязь между программным аккаунтом и аккаунтом данных. Обратите внимание, что поле Data аккаунта данных содержит как адрес кошелька, так и код eBPF.

Транзакции и инструкции в Solana
В Solana пользователи выполняют программы, отправляя транзакции. Уникальной особенностью Solana является её способность выполнять эти транзакции параллельно, что является ключевой причиной её молниеносной скорости транзакций. Теперь давайте подробнее рассмотрим, как транзакции устроены в Solana.
Транзакция Solana состоит из подписей и сообщения. Транзакция может включать несколько подписей. Сообщение транзакции состоит из четырёх частей, как показано ниже.

Header и Compact Array of Account Addresses определяют все аккаунты, участвующие в транзакции, и их характеристики в ходе транзакции, включая то, является ли аккаунт подписантом и доступен ли он для записи во время выполнения. Располагая этой информацией, Solana может проверять подписи, предоставленные аккаунтами-подписантами, и обрабатывать транзакции параллельно, при условии что эти транзакции не включают аккаунты, выполняющие запись в одно и то же состояние.
Recent Blockhash служит меткой времени для транзакции. Если хэш блока транзакции на 150 блоков старше последнего хэша блока, транзакция считается просроченной и не будет выполнена.
Compact Array of Instructions является наиболее важной частью транзакции, содержащей одну или несколько инструкций. Инструкция по существу запускает выполнение процедуры, предоставляемой программным аккаунтом. Каждая инструкция состоит из трёх полей, как показано ниже.

Первое поле, Program ID Index, указывает получателя инструкции, то есть программу в цепочке, которой необходимо обработать инструкцию. Вместо хранения 32-байтного адреса этот адрес помещается в Compact Array of Account Addresses сообщения транзакции, а поле хранит лишь индекс типа u8, указывающий на адрес в массиве.
Аналогично первому полю, второе поле хранит индексы адресов аккаунтов, известные как Compact Array of Account Address Indexes. Этот массив определяет все аккаунты, участвующие в данной инструкции.
Последнее поле представляет собой массив байтов, содержащий дополнительные данные, необходимые программе для обработки инструкции, такие как аргументы функции.
Важно отметить, что Solana обрабатывает все инструкции в транзакции в заданном порядке и гарантирует атомарное выполнение транзакции. Это означает, что транзакция либо полностью завершается с успешной обработкой всех инструкций, либо полностью завершается неудачей. Не может возникнуть ситуации, когда одни инструкции обработаны, а другие — нет.
🧐 Просмотр транзакций Solana в обозревателях Solana
Мы используем другой обозреватель Solana, чтобы просмотреть транзакцию, которая создала упомянутый ранее программный аккаунт. В разделе Overview можно увидеть подпись транзакции Solana, последний хэш блока и другую информацию:

В разделе Account Input перечислены все аккаунты, участвующие в текущей транзакции, вместе с их характеристиками в транзакции. Мы можем видеть, что помимо адресов отправителя и программного аккаунта в неё также включены два аккаунта Native Programs и Sysvar.

Поскольку это простая транзакция создания программы, она содержит только две инструкции. Получателем первой инструкции является System Program, отвечающая за создание программного аккаунта. Получателем второй инструкции является BPF Loader, который создаёт аккаунт данных для хранения развёрнутого кода eBPF и записывает его адрес в поле Data программного аккаунта.

Заключение
Смарт-контракты на Solana разрабатываются на Rust и выполняются на виртуальной машине eBPF. Solana следует модели аккаунтов, в которой аккаунты в цепочке должны поддерживать достаточный уровень ренты, чтобы избежать удаления данных. Транзакция состоит из одной или нескольких инструкций, определяющих все необходимые аккаунты, что обеспечивает параллельную обработку, повышает пропускную способность и снижает задержку отклика. Все эти особенности в совокупности способствовали стремительному развитию Solana, сделав её одним из наиболее популярных блокчейнов.



