Back to Blog

Solana для начинающих 01: Освойте основные концепции Solana за одно прочтение

June 7, 2024
8 min read

Введение

В 2024 году Solana совершила впечатляющий рывок: общая стоимость заблокированных в ней активов (TVL) выросла с одного миллиарда долларов США в начале года до почти пяти миллиардов, что сделало её четвертым по величине публичным блокчейном.

По сравнению с Ethereum, Solana предлагает пользователям более качественный опыт за счет более высокой скорости и меньших затрат. Механизм консенсуса, основанный на Proof of History (доказательстве истории), и модель асинхронной обработки транзакций обеспечивают разработчикам высокую пропускную способность транзакций и низкую задержку, что делает Solana предпочтительной платформой для самых разных децентрализованных приложений.

Команда BlockSec подготовила специальную серию статей «Solana: Просто о сложном» (Solana Simplified), в которой рассматриваются базовые концепции Solana, практические руководства по анализу транзакций и инструкции по написанию смарт-контрактов для Solana.

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

eBPF: краеугольный камень исполнения транзакций в Solana

Для написания и исполнения смарт-контрактов блокчейнам обычно требуются язык программирования и тьюринг-полная вычислительная среда.

Смарт-контракты в Ethereum обычно пишутся на высокоуровневом языке под названием Solidity. Компилятор преобразует их в байт-код, который затем исполняется в Виртуальной машине Ethereum (EVM). Вместо создания совершенно новой виртуальной среды и языка, Solana решила полностью использовать существующие передовые технологии. Виртуальная машина eBPF (extended Berkeley Packet Filter), изначально спроектированная для расширения функций ядра Linux, была выбрана Solana в качестве базовой среды исполнения.

Так какие же преимущества предлагает eBPF по сравнению с EVM?

В отличие от EVM, ограниченной интерпретируемым исполнением, eBPF поддерживает компиляцию «на лету» (Just-In-Time, JIT), что позволяет преобразовывать байт-код в машинные инструкции, которые процессор может выполнять напрямую. Такая возможность значительно повышает эффективность программ.

Кроме того, eBPF обладает эффективным набором инструкций и зрелой инфраструктурой. Разработчики могут создавать смарт-контракты с использованием языка Rust. Используя бэкенд eBPF компиляторной инфраструктуры LLVM, программы на Rust могут напрямую компилироваться в байт-код eBPF.

Модель аккаунтов Solana

Структура аккаунтов Solana

Данные в Solana хранятся в виде аккаунтов. Как показано ниже, все данные в Solana можно представить как огромную базу данных типа «ключ-значение». Ключами в этой базе являются адреса аккаунтов. Для «кошельков» (т. е. аккаунтов, непосредственно контролируемых пользователями Solana с помощью пар открытых и закрытых ключей) этими адресами являются открытые ключи, сгенерированные с помощью системы цифровой подписи Ed25519. Значения в базе данных состоят из специфических деталей каждого аккаунта, включая баланс и другую соответствующую информацию.

Solana использует структуру под названием AccountInfo для описания аккаунта:

AccountInfo для каждого аккаунта содержит четыре поля. Вот пояснение для каждого из них:

  • Поле Data (Данные): В этом поле хранятся данные, относящиеся к аккаунту. Если аккаунт является программой (т. е. смарт-контрактом), в нем хранится байт-код eBPF. В противном случае формат данных обычно определяется создателем аккаунта.

  • Поле Executable (Исполняемый): Это поле используется для указания того, является ли аккаунт программой. Важно отметить, что, в отличие от Ethereum, программы в Solana можно обновлять.

  • Поле Lamports (Лампорты): Это поле записывает баланс токенов Solana в аккаунте. Лампорты — это, по сути, наименьшая единица токена SOL (1 SOL = 1 миллиард лампортов).

  • Поле Owner (Владелец): Это поле указывает владельца аккаунта. В Solana каждый аккаунт имеет «владельца». Например, владельцем всех «кошельковых» аккаунтов является Системная программа (System Program) — специальный аккаунт в сети Solana, отвечающий за такие функции, как создание аккаунтов. Владелец аккаунта — единственный, кто может изменять данные аккаунта и списывать лампорты с его баланса (однако любой может увеличить количество лампортов, переведя средства на этот аккаунт).

Предопределенные аккаунты Solana

В Solana есть набор предопределенных исполняемых программ, известных как Native Programs (родные программы), которые развернуты по фиксированным адресам. По мере обновления сети Solana эти предопределенные программы также могут обновляться. Они служат API и библиотечными функциями, предлагая определенные функциональные возможности внутри сети Solana.

Среди родных программ той, с которой разработчики взаимодействуют чаще всего, является System Program. Системная программа предоставляет разработчикам набор инструкций, каждая из которых выполняет независимую задачу. Например, разработчики могут использовать инструкцию CreateAccount для создания новых аккаунтов или инструкцию Transfer для перевода лампортов на другие аккаунты.

Другой распространенной родной программой является BPF Loader. Она является владельцем всех остальных программных аккаунтов и отвечает за развертывание, обновление и исполнение пользовательских программ. Когда «кошельковому» аккаунту нужно обновить программу, которую он развернул, это делается путем делегирования полномочий программе BPF Loader, так как только владелец программы имеет прямые права на изменение данных.

Помимо родных программ, Solana также предлагает набор аккаунтов, известных как Sysvars (системные переменные). Эти аккаунты предоставляют программам в Solana информацию и глобальные переменные, связанные с текущим состоянием сети Solana, такие как текущее время и хеш последнего блока.

Арендная плата за аккаунт (Rent)

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

Любая транзакция, которая пытается уменьшить баланс аккаунта ниже суммы аренды, завершится неудачей, если только она не уменьшит баланс ровно до нуля. Снижение баланса до нуля означает, что аренда аккаунта была «возвращена», и по завершении транзакции Solana удалит данные соответствующего аккаунта в процессе сборки мусора.

🧐 Просмотр аккаунтов Solana в Solana Explorer

Чтобы лучше понять вышеупомянутые концепции, мы использовали проект «Hello World» от Solana для развертывания программного аккаунта, который можно просмотреть с помощью обозревателя блокчейна Solana — Solscan.

Как показано на изображении выше, мы видим, что аккаунт помечен как «Program» (Программа). Часть лампортов была списана с баланса отправителя в качестве арендной платы за этот аккаунт, поэтому поле 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 проверяет, является ли делегирующий аккаунт тем самым, который изначально развернул программу. Поскольку владельцем программного аккаунта уже установлен 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-байтового адреса, этот адрес помещается в «Компактный массив адресов аккаунтов» сообщения транзакции, а данное поле хранит только индекс типа u8, указывающий на адрес в этом массиве.

Аналогично первому полю, второе поле хранит индексы адресов аккаунтов — Compact Array of Account Address Indexes. Этот массив определяет все аккаунты, участвующие в данной инструкции.

Последнее поле — это массив байтов, содержащий дополнительные данные, необходимые программе для обработки инструкции, такие как аргументы функции.

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

🧐 Просмотр транзакций Solana в Solana Explorer

Мы используем другой обозреватель Solana, чтобы просмотреть транзакцию, которая создала программный аккаунт ранее. В разделе «Overview» вы можете увидеть подпись транзакции Solana, хеш недавнего блока и другую информацию:

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

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

Заключение

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

Читайте другие статьи из этой серии: