НОВОЕ: Helius приобретает Light Protocol
Модель программирования Solana
Блог/Основы

Модель программирования Solana: введение в разработку на Solana

Developer Experience Engineer0xIchigo в X0xIchigo в LinkedIn0xIchigo на GitHub
Чтение: 24 мин

О чём эта статья?

Подход Solana к децентрализованным вычислениям основан на простом принципе: всё хранится в собственной области памяти, которая называется аккаунтом. Solana работает как глобальное хранилище ключей и значений, где публичные ключи служат уникальными идентификаторами соответствующих аккаунтов. Аккаунты — основа Solana, поскольку они хранят состояние: от программ до балансов токенов. Транзакции обновляют аккаунты и отражают изменения состояния.

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

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

Что такое кластеры Solana?

В основе архитектуры Solana лежат кластеры — набор валидаторов, которые совместно обрабатывают транзакции и поддерживают единый реестр. В Solana есть несколько отдельных кластеров, каждый из которых служит определённой цели:

  • Localhost: локальный кластер для разработки, доступный через порт 8899 по умолчанию. Интерфейс командной строки Solana (CLI) включает встроенный тестовый валидатор, который можно настроить под потребности конкретного разработчика без аирдропов и ограничений частоты запросов
  • Devnet: безопасная песочница для тестирования и экспериментов в Solana
  • Testnet: среда, в которой ключевые участники разработки Solana тестируют новые обновления и функции перед их выпуском в основной сети. Разработчики также используют её для тестирования производительности
  • Mainnet Beta: действующий общедоступный кластер, где выполняются реальные транзакции. Это «настоящая» Solana, в которой ежедневно взаимодействуют пользователи, разработчики, держатели токенов и валидаторы

Каждый кластер работает независимо и ничего не знает о других кластерах. Транзакции, отправленные в неверный кластер, отклоняются для сохранения целостности каждой рабочей среды.

Представьте кластер как монолитную кучу данных. В информатике куча — это область памяти, где данные можно динамически сохранять и изменять. Однако важно отметить, что кластеры не используют структуру данных «куча» буквально. Эта аналогия помогает понять, что кластеры состоят из различных областей памяти, которые можно выделять и освобождать по мере необходимости. Представление кластера как динамической кучи важно для понимания того, как данные управляются, используются и защищаются в сети.

Эту монолитную кучу данных также можно представить как цифровой склад. Данные здесь похожи на коробки на полках: у каждой есть уникальная маркировка и определённые правила перемещения и изменения содержимого. Так формируется безопасная и упорядоченная система, в которой разрешены только авторизованные перемещения и изменения.

Смарт-контрактам, которые в Solana называются программами, выделяется собственная управляемая часть склада, или кучи. Программа может читать данные из любой части этого склада, но для изменения содержимого области, которой она не владеет, ей нужны определённые разрешения. Единственное действие, разрешённое без ограничений, — перевод лампортов, нативной криптовалюты Solana, в любую область склада.

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

Что такое аккаунты?

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

В Solana есть три типа аккаунтов:

  • Аккаунты, хранящие данные
  • Аккаунты, хранящие исполняемые программы
  • Аккаунты, хранящие нативные программы

По своим возможностям эти типы аккаунтов также делятся на:

  • Исполняемые аккаунты — аккаунты, способные выполнять код
  • Неисполняемые аккаунты — аккаунты для хранения данных без возможности выполнять код, поскольку они не содержат кода

На изображении выше приведено несколько примеров исполняемых и неисполняемых аккаунтов. Среди исполняемых аккаунтов Bubblegum — пример аккаунта программы. Это программа Metaplex для создания сжатых NFT и управления ими. Vote Program — пример аккаунта нативной программы. Она создаёт аккаунты, отслеживающие состояние голосования валидаторов и вознаграждения, и управляет ими. Различия между аккаунтами программ и нативных программ мы рассмотрим в разделе Что такое программы?. Пока важно понимать, что в Solana существуют разные типы исполняемых аккаунтов.

Кроме того, любой неисполняемый аккаунт можно отнести к аккаунтам данных. Примеры аккаунтов данных:

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

Структура аккаунтов определяется структурой AccountInfo:

Код
pub struct AccountInfo<'a> {
    pub key: &'a Pubkey,
    pub lamports: Rc>,
    pub data: Rc>,
    pub owner: &'a Pubkey,
    pub rent_epoch: Epoch,
    pub is_signer: bool,
    pub is_writable: bool,
    pub executable: bool,
}

Аккаунты идентифицируются по адресу (key), который представляет собой уникальный 32-байтовый публичный ключ.

Поле lamports содержит количество лампортов, принадлежащих аккаунту. Один лампорт равен одной миллиардной SOL — нативного токена Solana.

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

Поле owner содержит владельца аккаунта, представленного адресом аккаунта программы. Владение аккаунтами регулируется несколькими правилами:

  • Только владелец аккаунта может изменять его данные и выводить лампорты
  • Любой пользователь может внести лампорты на аккаунт
  • Владелец аккаунта может передать право владения новому владельцу при условии, что данные аккаунта обнулены

Поле is_signer содержит логическое значение, указывающее, подписал ли транзакцию владелец соответствующего аккаунта. Иными словами, оно сообщает участвующим в транзакции программам, является ли аккаунт подписантом. Статус подписанта означает, что аккаунт располагает закрытым ключом, соответствующим публичному ключу, и имеет право одобрить предложенную транзакцию.

Поле is_writable содержит логическое значение, указывающее, можно ли изменять данные аккаунта. Для параллельной обработки Solana позволяет указывать в транзакциях аккаунты только для чтения. Среда выполнения разрешает разным программам одновременно обращаться к аккаунтам только для чтения, а потенциальные конфликты записи в изменяемые аккаунты разрешает с помощью порядка обработки транзакций. Благодаря этому параллельно обрабатываются только неконфликтующие транзакции.

Поле executable содержит логическое значение, указывающее, может ли аккаунт обрабатывать инструкции. Да, это действительно означает, что программы хранятся в аккаунтах. Подробнее мы рассмотрим это в следующем разделе. Но сначала нужно разобраться с понятием аренды.

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

Аренда

Аренда — это стоимость хранения, необходимая для поддержания аккаунтов в Solana и их хранения в памяти валидаторов. Аренда начисляется по эпохам — единицам времени, определяемым слотами, в течение которых действует расписание лидеров. Аренда работает следующим образом:

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

Аренду для аккаунта определённого размера можно оценить через RPC-эндпоинт getMinimumBalanceForRentExemption. Test Drive упрощает расчёт, принимая длину данных аккаунта в usize. Для оценки минимального количества SOL, необходимого для освобождения аккаунта от аренды, также можно использовать подкоманду Solana CLI для расчёта аренды. Например, на момент написания статьи команда solana rent 20000 возвращает Rent-exempt minimum: 0.14009088 SOL.

Адреса в Solana

На самом деле в Solana есть два «типа» адресов. Для создания адресов Solana использует ed25519 — схему подписи EdDSA на основе SHA-512 (SHA-2) и эллиптической кривой Curve22519. В результате получаются 32-байтовые публичные ключи, которые служат основным форматом адреса. Их можно использовать напрямую, поскольку они не хешируются.

Чтобы адрес был действительным, он должен быть точкой на кривой ed25519. Однако не все адреса обязательно должны быть получены из этой кривой. Адреса, производные от программы (PDA), генерируются вне кривой. Поэтому у них нет соответствующего закрытого ключа и их нельзя использовать для подписания. PDA создаются через System Program и применяются, когда программам нужно управлять аккаунтами. Это лишь примечание, чтобы вы знали о разных типах адресов в Solana. PDA мы рассмотрим в одной из следующих статей.

Чем аккаунты Solana отличаются от аккаунтов Ethereum?

В Ethereum есть два основных типа аккаунтов: аккаунты с внешним владельцем (EOA) и аккаунты контрактов. EOA управляются закрытыми ключами, а аккаунты контрактов — кодом соответствующих контрактов и не могут самостоятельно инициировать транзакции.

EOA и аккаунты контрактов имеют одинаковую структуру:

  • Баланс — у каждого аккаунта есть баланс, измеряемый в Ether
  • Nonce — для EOA это количество транзакций, отправленных с аккаунта. Для контрактов — количество контрактов, созданных аккаунтом
  • Корень хранилища — 256-битный хеш корневого узла дерева Меркла — Патриции, в котором закодировано содержимое хранилища аккаунта
  • CodeHash — хеш кода контракта для виртуальной машины Ethereum (EVM). Он неизменяем: после создания контракта его код не меняется, хотя состояние может изменяться. Важно отметить, что существуют исключения для обновления контрактов в Ethereum, например использование шаблонов прокси, однако это выходит за рамки статьи. Для EOA это хеш пустой строки, поскольку EOA не содержат кода

Solana использует более унифицированную модель аккаунтов, где любой аккаунт потенциально может быть программой. Разделение кода и данных создаёт более эффективную и гибкую среду. Программы Solana не имеют состояния и взаимодействуют с различными аккаунтами данных без повторных развёртываний. Это особенно полезно для приложений децентрализованных финансов (DeFi), где пользователю нужно взаимодействовать с несколькими протоколами, не перемещая активы между разными программами. Модель программирования Ethereum, напротив, объединяет код и состояние в одной сущности. Это усложняет взаимодействие и может повышать затраты из-за газа, необходимого для изменения состояния.

Раньше аккаунты Solana должны были платить аренду и поддерживать минимальный баланс, чтобы оставаться активными. Так сеть со временем высвобождала неиспользуемые аккаунты или аккаунты с недостаточным балансом, сокращая разрастание состояния. После недавних обновлений в основной сети больше нет аккаунтов, которые платят аренду: все аккаунты должны быть освобождены от неё. Для сравнения, Ethereum управляет распределением ресурсов с помощью газа. В этой модели хранилище контракта существует бессрочно, если его явно не очистить. Подход Solana обеспечивает более предсказуемую структуру затрат на хранение состояния, тогда как расходы в Ethereum могут меняться и становиться чрезмерными в периоды перегрузки сети.

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

Что такое программы Solana?

Программы — это исполняемые аккаунты, принадлежащие BPF Loader. Их выполняет среда выполнения Solana, предназначенная для обработки транзакций и программной логики.

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

Программы в Solana могут:

  • Владеть дополнительными аккаунтами
  • Читать данные других аккаунтов или зачислять на них средства
  • Изменять данные принадлежащих им аккаунтов или списывать с них средства

Существует два типа программ:

  • Ончейн-программы — пользовательские программы, развёрнутые в Solana. Их может обновлять уполномоченный на обновление аккаунт, обычно тот, который развернул программу
  • Нативные программы — программы, встроенные в ядро Solana. Они предоставляют базовые функции, необходимые для работы валидаторов. Нативные программы можно обновлять только через общесетевые обновления программного обеспечения. Распространённые примеры: System Program, BPF Loader Program и Vote Program.

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

Solana Labs поддерживает избранную группу ончейн-программ, известную как библиотека программ Solana. Эта библиотека обеспечивает различные ончейн-операции, включая кредитование токенов и создание пулов стейкинга. Например, Associated Token Account Program задаёт стандарт и механизм связывания кошелька пользователя с его аккаунтами токенов. Кроме того, SPL постоянно развивается. Такие программы, как Token-2022, дополняют и расширяют возможности Token Program.

Программы для Solana обычно разрабатывают на Rust с помощью Anchor — структурированного фреймворка, который упрощает создание программ, сокращая шаблонный код и оптимизируя сериализацию и десериализацию. Хотя Rust предпочтителен, разработчики им не ограничены: можно использовать C, C++ и любой язык, ориентированный на BPF-бэкенд LLVM, то есть компонент LLVM, позволяющий компилировать программы в байт-код BPF. Недавние разработки Solang и Neon Labs позволили использовать Solidity для разработки программ.

Обычно программы разрабатывают и тестируют в Localhost и Devnet, прежде чем развёртывать в Testnet или Mainnet Beta. Разработчики могут развернуть программу через Solana CLI с помощью команды solana program deploy <path to program>. После компиляции в разделяемый объект ELF, содержащий байт-код BPF, программа загружается в выбранный кластер Solana. Развёрнутые программы находятся в аккаунтах с отметкой executable, а адрес аккаунта служит program_id.

Изначально программы в Solana развёртывались с аккаунтами, размер которых вдвое превышал размер программы. Обновление Solana 1.16 добавляет поддержку аккаунтов с изменяемым размером, повышая гибкость и эффективность распределения ресурсов для разработчиков. Теперь разработчик может развернуть программу в аккаунте меньшего размера и увеличить его позднее.

Как упоминалось выше, программы считаются не имеющими состояния, поскольку все данные, с которыми они взаимодействуют, хранятся в отдельных аккаунтах и передаются по ссылке. У каждой программы есть единая точка входа, где обрабатываются инструкции. Она принимает program_id, массив аккаунтов и данные инструкции в виде массива байтов. После вызова транзакцией программы выполняются средой выполнения Solana.

Что такое транзакции?

Транзакции — основа ончейн-активности. Через них вызываются программы и изменяется состояние. Транзакция в Solana — это набор инструкций, сообщающих валидаторам, какие действия выполнить, с какими аккаунтами и имеются ли необходимые разрешения.

Транзакция состоит из трёх основных частей:

  • Массив аккаунтов для чтения или записи
  • Одна или несколько инструкций
  • Одна или несколько подписей

Транзакции в Solana соответствуют структуре Transaction. Она предоставляет сведения, необходимые сети для обработки и проверки действий. Структура определяется следующим образом:

Код
pub struct Transaction {
    pub signatures: Vec,
    pub message: Message,
}

Поле signatures содержит набор подписей, соответствующих сериализованному Message. Каждая подпись связана с ключом аккаунта из списка account_keys объекта Message, начиная с плательщика комиссии. Плательщик комиссии — аккаунт, который оплачивает комиссию за обработку транзакции. Обычно это аккаунт, инициирующий транзакцию. Количество необходимых подписей равно num_required_signatures, определённому в MessageHeader сообщения.

Сам message представляет собой структуру типа Message. Она определяется так:

Код
pub struct Message {
    pub header: MessageHeader,
    pub account_keys: Vec,
    pub recent_blockhash: Hash,
    pub instructions: Vec,
}

Поле header сообщения содержит три беззнаковых 8-битных целых числа: количество необходимых подписей, то есть num_required_signatures, количество подписантов только для чтения и количество неподписантов только для чтения.

Поле account_keys содержит адреса всех аккаунтов, участвующих в транзакции. Сначала перечисляются аккаунты, запрашивающие доступ для чтения и записи, а затем аккаунты только для чтения.

recent_blockhash — это недавний хеш блока, содержащий 32-байтовый хеш SHA-256. Он нужен, чтобы указать, когда клиент в последний раз наблюдал реестр, и определяет срок действия недавних транзакций. Валидаторы отклоняют транзакции со старым хешем блока. Кроме того, недавний хеш блока помогает предотвращать дублирование транзакций, поскольку транзакция, полностью совпадающая с предыдущей, отклоняется. Если по какой-либо причине транзакцию нужно подписать задолго до отправки в сеть, вместо недавнего хеша блока можно использовать долговечный nonce транзакции, чтобы обеспечить её уникальность.

Поле instructions содержит одну или несколько структур CompiledInstruction, каждая из которых предписывает валидаторам сети определённое действие.

Инструкции

Инструкция — это директива для одного вызова программы Solana. Это наименьшая единица логики выполнения в программе и базовая операционная единица Solana. Программы интерпретируют переданные инструкцией данные и работают с указанными аккаунтами. Структура Instruction определяется так:

Код
pub struct Instruction {
    pub program_id: Pubkey,
    pub accounts: Vec,
    pub data: Vec,
}

Поле program_id указывает публичный ключ выполняемой программы. Это адрес программы, которая обработает инструкцию. Владелец аккаунта программы, обозначенного этим публичным ключом, определяет загрузчик, отвечающий за инициализацию и выполнение программы. После развёртывания загрузчик помечает ончейн-программы формата Solana Bytecode Format (SBF) как исполняемые. Среда выполнения Solana отклоняет транзакции, пытающиеся вызвать аккаунты без отметки об исполняемости.

Поле accounts перечисляет аккаунты, из которых инструкция может читать или в которые может записывать данные. Эти аккаунты должны передаваться как значения AccountMeta. Любой аккаунт, данные которого могут быть изменены инструкцией, необходимо пометить как доступный для записи, иначе транзакция завершится с ошибкой. Причина в том, что программы не могут записывать данные в аккаунты, которыми не владеют или для которых не имеют необходимых разрешений. Это относится и к изменению количества лампортов аккаунта: списание лампортов с аккаунта, не принадлежащего программе, приведёт к ошибке транзакции, тогда как добавлять лампорты можно на любой аккаунт. В поле accounts также можно указать аккаунты, данные которых программа не читает и не изменяет. Это позволяет влиять на планирование выполнения программ средой выполнения, но во всех остальных случаях такие аккаунты игнорируются.

data — это универсальный вектор беззнаковых 8-битных целых чисел, служащий входными данными для программы. Это поле критически важно, поскольку содержит закодированные инструкции, которые выполнит программа.

Solana не зависит от формата данных инструкций. Однако она имеет встроенную поддержку сериализации через bincode и borsh (Binary Object Representation Serializer for Hashing). Сериализация — это преобразование сложных структур данных в линейную последовательность байтов, которую можно передать или сохранить. При выборе способа кодирования данных следует учитывать затраты на декодирование, поскольку оно полностью выполняется в блокчейне. Сериализации Borsh часто отдают предпочтение перед bincode, поскольку она имеет стабильную спецификацию, реализацию на JavaScript и обычно более эффективна.

Программы используют вспомогательные функции для упрощения создания поддерживаемых инструкций. Например, System Program предоставляет вспомогательную функцию для создания инструкции SystemInstruction::Assign:

Код
pub fn assign(pubkey: &Pubkey, owner: &Pubkey) -> Instruction {
    let account_metas = vec![AccountMeta::new(*pubkey, true)];
    Instruction::new(
        system_program::id(),
        &SystemInstruction::Assign { owner: *owner },
        account_metas,
    )
}

Эта функция создаёт инструкцию, которая при обработке изменит владельца указанного аккаунта на нового предоставленного владельца.

Одна транзакция может содержать несколько инструкций, которые выполняются последовательно и атомарно в указанном порядке. Это означает, что либо успешно выполняются все инструкции, либо не выполняется ни одна. Поэтому порядок инструкций может быть критически важен. Программы нужно укреплять так, чтобы они безопасно обрабатывали любую возможную последовательность инструкций и предотвращали потенциальные эксплойты.

Например, при деинициализации программа может попытаться деинициализировать аккаунт, обнулив его баланс лампортов. При этом предполагается, что среда выполнения Solana удалит аккаунт. Это предположение верно между транзакциями, но неверно между инструкциями или межпрограммными вызовами, которые мы рассмотрим в будущей статье. Чтобы защититься от потенциального недостатка процесса деинициализации, программа должна явно обнулить данные аккаунта. Иначе злоумышленник может отправить следующую инструкцию и воспользоваться предполагаемым удалением, например повторно использовать аккаунт до завершения транзакции.

Что такое версионированные транзакции?

Транзакции Solana используют стандарты максимального размера передаваемого блока (MTU) для IPv6, чтобы гарантировать быструю и надёжную передачу данных по кластеру. Сетевой стек Solana использует консервативный размер MTU в 1280 байт. После выделения места под заголовки для данных пакета остаётся 1232 байта. Поэтому размер транзакций Solana ограничен этим значением.

Такое ограничение размера способствует ряду сетевых улучшений, но также ограничивает сложность операций, которые можно выполнить в одной транзакции. Поскольку каждый адрес аккаунта занимает 32 байта, транзакция может содержать до 35 аккаунтов без каких-либо инструкций. Это создаёт трудности для сценариев, где в одной транзакции требуется более 35 аккаунтов без подписи.

Для решения этой проблемы был представлен новый формат транзакций, поддерживающий несколько версий. Сейчас среда выполнения Solana поддерживает две версии транзакций:

  • legacy — исходный формат транзакций
  • 0 (версия 0) — новейший формат транзакций с поддержкой таблиц поиска адресов

Версия 0 была выпущена для поддержки таблиц поиска адресов (ALT). По сути, они хранят адреса аккаунтов в табличной структуре данных в блокчейне. Эти таблицы представляют собой отдельные аккаунты, которые хранят адреса других аккаунтов и позволяют ссылаться на них в транзакции с помощью однобайтового индекса u8. Это значительно уменьшает размер транзакции, поскольку для каждого включённого аккаунта требуется всего 1 байт вместо 32. ALT особенно полезны для сложных операций с большим количеством аккаунтов, часто встречающихся в приложениях DeFi.

Эта схема адаптирована из раздела Solana Cookbook о версионированных транзакциях

Термин «версионированные транзакции» описывает поддержку Solana как устаревшего формата транзакций, так и формата версии 0. Этот подход сохраняет компонуемость и одновременно позволяет использовать улучшения среды выполнения.

Структура версионированной транзакции

VersionedTransaction определяется следующим образом:

Код
pub struct VersionedTransaction {
    pub signatures: Vec,
    pub message: VersionedMessage,
}

Поле signatures представляет собой список подписей участников транзакции. Они подтверждают подлинность и обеспечивают целостность транзакции. message — это фактическое содержимое транзакции. Оно инкапсулировано типом VersionedMessage — тонкой обёрткой enum, которая обрабатывает как устаревшие сообщения, так и сообщения версии 0:

Код
pub enum VersionedMessage {
    Legacy(Message),
    V0(Message),
}

Версия сообщения определяется по первому биту в процессе сериализации. Если первый бит установлен, остальные 7 бит используются для определения сериализованной версии Message, начиная с версии 0. Если первый бит не установлен, все байты используются для кодирования устаревшего формата Message. Это связано с тем, что существуют две структуры Message с одинаковыми именами, но они находятся в разных модулях: legacy и v0.

Message представляет собой сжатый внутренний формат транзакции. Он используется для передачи по сети и обработки средой выполнения. Формат включает линейный список всех аккаунтов, используемых инструкциями транзакции, MessageHeader с описанием структуры массива аккаунтов, недавний хеш блока и компактное кодирование инструкций сообщения. Вот структура v0 Message:

Код
pub struct Message {
    pub header: MessageHeader,
    pub account_keys: Vec,
    pub recent_blockhash: Hash,
    pub instructions: Vec,
    pub address_table_lookups: Vec,
}

Различие между устаревшим сообщением и сообщением v0 заключается в наличии поля address_table_lookups.

Интеграция модели программирования с потоком транзакций Solana

Модель программирования Solana тесно интегрирована с системами аккаунтов и транзакций. Вот как связаны эти понятия:

  • Аккаунты как состояние — аккаунты Solana служат контейнерами состояния для программ. Модель программирования строится вокруг изменения данных в этих контейнерах в ответ на инструкции
  • Инструкции — программы определяют логику обработки инструкций, содержащихся в транзакции. Инструкции — это исполняемые компоненты, взаимодействующие с данными аккаунтов
  • Сериализация и обработка — при сериализации транзакции инструкции программы определяют изменения состояний аккаунтов. Процесс сериализации учитывает архитектуру программы независимо от того, использует ли она устаревший формат транзакций или формат версии 0
  • Атомарность — модель программирования Solana обеспечивает атомарную обработку инструкций. Программы должны быть спроектированы так, чтобы безопасно и эффективно обрабатывать параллельные транзакции
  • Масштабируемость — модель программирования Solana поддерживает масштабирование с помощью таких возможностей, как таблицы поиска адресов (ALT). Эти таблицы уменьшают размер транзакции и увеличивают количество аккаунтов, на которые она может ссылаться

Модель программирования Solana — это не только написание кода, но и понимание того, как этот код взаимодействует с более широкой экосистемой. Аккаунты играют в этой модели ключевую роль и служат основным средством хранения и изменения данных в сети. Транзакции обеспечивают ончейн-активность, сообщая валидаторам, какие данные необходимо создать, обновить или удалить. Глубокое понимание этих аспектов необходимо разработчикам для создания приложений, оптимизированных для высокой производительности и эффективного взаимодействия в экосистеме Solana.

Заключение

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

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

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

Если вы дочитали до этого места, анон, спасибо! Готовы погрузиться глубже? Присоединяйтесь к нашему Discord и начните программировать на Solana уже сегодня.

Дополнительные ресурсы и материалы

Подпишитесь на Helius

Следите за новостями разработки на Solana и получайте уведомления о наших публикациях

Увеличенное изображение