Программы
На Solana смарт-контракт называется программой. Программа — это не имеющий состояния аккаунт, который содержит исполняемый код. Этот код организован в функции, называемые инструкциями. Пользователи взаимодействуют с программой, отправляя транзакцию, содержащую одну или несколько инструкций. Транзакция может включать инструкции из нескольких программ.
Когда программа развёртывается, Solana использует LLVM для компиляции её в исполняемый и связываемый формат (ELF). ELF-файл содержит бинарный код программы в формате байткода Solana (sBPF) и сохраняется в блокчейне в исполняемом аккаунте.
sBPF — это кастомная версия байткода eBPF от Solana.
Написание программ
Большинство программ пишутся на языке Rust с использованием двух распространённых подходов к разработке:
- Anchor: Anchor — это фреймворк, разработанный для быстрой и простой разработки на Solana. Он использует макросы Rust, чтобы уменьшить количество шаблонного кода, что делает его отличным выбором для начинающих.
- Чистый Rust: Написание программ на Rust без использования каких-либо фреймворков. Этот подход предоставляет больше гибкости, но сопровождается увеличением сложности.
Обновление программ
Чтобы
изменить
существующую программу, аккаунт должен быть назначен как
уполномоченный на обновление.
(Обычно это тот же аккаунт, который изначально
развёртывал программу.) Если полномочия на
обновление отозваны и установлены на None, программа больше не может быть
обновлена.
Проверка программ
Solana поддерживает проверяемые сборки, которые позволяют пользователям проверить, соответствует ли код программы в блокчейне её публичному исходному коду. Фреймворк Anchor предоставляет встроенную поддержку для создания проверяемой сборки.
Чтобы проверить, является ли существующая программа проверенной, найдите её ID программы в Solana Explorer. Кроме того, вы можете использовать CLI-инструмент Ellipsis Labs Solana Verifiable Build CLI, чтобы независимо проверить программы в блокчейне.
Встроенные программы
Системная программа
Системная программа — это единственный аккаунт, который может создавать новые аккаунты. По умолчанию все новые аккаунты принадлежат Системной программе, хотя многим из них назначается новый владелец при создании. Системная программа выполняет следующие ключевые функции:
| Функция | Описание |
|---|---|
| Создание нового аккаунта | Только Системная программа может создавать новые аккаунты. |
| Выделение пространства | Устанавливает объем байтов для поля данных каждого аккаунта. |
| Назначение владельца программы | После создания аккаунта Системная программа может переназначить владельца программы на другой аккаунт программы. Таким образом, пользовательские программы получают владение новыми аккаунтами, созданными Системной программой. |
| Перевод SOL | Переводит лампорты (SOL) с системных аккаунтов на другие аккаунты. |
Адрес системной программы: 11111111111111111111111111111111.
Программы-загрузчики
Каждая программа принадлежит другой программе — её загрузчику. Загрузчики используются для развертывания, повторного развертывания, обновления или закрытия программ. Они также используются для финализации программы и передачи полномочий программы.
В настоящее время существует пять программ-загрузчиков, как показано в таблице ниже.
| Загрузчик | ID программы | Примечания | Ссылка на инструкции |
|---|---|---|---|
| native | NativeLoader1111111111111111111111111111111 | Управляющие инструкции отключены, но программы продолжают выполняться | — |
| v1 | BPFLoader1111111111111111111111111111111111 | Управляющие инструкции отключены, но программы продолжают выполняться | — |
| v2 | BPFLoader2111111111111111111111111111111111 | Управляющие инструкции отключены, но программы продолжают выполняться | Инструкции |
| v3 | BPFLoaderUpgradeab1e11111111111111111111111 | Программы могут быть обновлены после развертывания. Исполняемый файл программы хранится в отдельном аккаунте данных программы | Инструкции |
| v4 | LoaderV411111111111111111111111111111111111 | В разработке (не выпущен) | Инструкции |
Программы, развернутые с использованием loader-v3 или loader-v4, могут быть изменяемыми после развертывания, если это предусмотрено полномочиями на обновление.
При развертывании новой программы по умолчанию будет использоваться последняя версия загрузчика.
Предварительно скомпилированные программы
Помимо программ загрузчика, Solana предоставляет следующие предварительно скомпилированные программы.
Проверка подписи ed25519
Программа ed25519 используется для проверки одной или нескольких подписей ed25519.
| Программа | ID программы | Описание | Инструкции |
|---|---|---|---|
| Программа Ed25519 | Ed25519SigVerify111111111111111111111111111 | Проверяет подписи ed25519. Если какая-либо подпись не проходит проверку, возвращается ошибка. | Инструкции |
Программа ed25519 обрабатывает инструкцию. Первый u8 инструкции содержит
количество подписей, которые необходимо проверить, за которым следует один байт
для выравнивания. После этого для каждой подписи сериализуется следующая
структура.
struct Ed25519SignatureOffsets {signature_offset: u16, // offset to ed25519 signature of 64 bytessignature_instruction_index: u16, // instruction index to find signaturepublic_key_offset: u16, // offset to public key of 32 bytespublic_key_instruction_index: u16, // instruction index to find public keymessage_data_offset: u16, // offset to start of message datamessage_data_size: u16, // size of message datamessage_instruction_index: u16, // index of instruction data to get message data}
process_instruction() {for i in 0..count {// i'th index values referenced:instructions = &transaction.message().instructionsinstruction_index = ed25519_signature_instruction_index != u16::MAX ? ed25519_signature_instruction_index : current_instruction;signature = instructions[instruction_index].data[ed25519_signature_offset..ed25519_signature_offset + 64]instruction_index = ed25519_pubkey_instruction_index != u16::MAX ? ed25519_pubkey_instruction_index : current_instruction;pubkey = instructions[instruction_index].data[ed25519_pubkey_offset..ed25519_pubkey_offset + 32]instruction_index = ed25519_message_instruction_index != u16::MAX ? ed25519_message_instruction_index : current_instruction;message = instructions[instruction_index].data[ed25519_message_data_offset..ed25519_message_data_offset + ed25519_message_data_size]if pubkey.verify(signature, message) != Success {return Error}}return Success}
Проверка восстановления secp256k1
Программа secp256k1 используется для проверки операций восстановления открытого ключа secp256k1.
| Программа | ID программы | Описание | Инструкции |
|---|---|---|---|
| Программа Secp256k1 | KeccakSecp256k11111111111111111111111111111 | Проверяет операции восстановления открытого ключа secp256k1 (ecrecover). | Инструкции |
Программа secp256k1 обрабатывает инструкцию. Первый байт инструкции содержит количество открытых ключей, которые необходимо проверить. После этого для каждого открытого ключа создается следующая структура, затем сериализуется и добавляется в данные инструкции.
struct Secp256k1SignatureOffsets {secp_signature_offset: u16, // offset to [signature,recovery_id] of 64+1 bytessecp_signature_instruction_index: u8, // instruction index to find signaturesecp_pubkey_offset: u16, // offset to ethereum_address pubkey of 20 bytessecp_pubkey_instruction_index: u8, // instruction index to find pubkeysecp_message_data_offset: u16, // offset to start of message datasecp_message_data_size: u16, // size of message datasecp_message_instruction_index: u8, // instruction index to find message data}
process_instruction() {for i in 0..count {// i'th index values referenced:instructions = &transaction.message().instructionssignature = instructions[secp_signature_instruction_index].data[secp_signature_offset..secp_signature_offset + 64]recovery_id = instructions[secp_signature_instruction_index].data[secp_signature_offset + 64]ref_eth_pubkey = instructions[secp_pubkey_instruction_index].data[secp_pubkey_offset..secp_pubkey_offset + 20]message_hash = keccak256(instructions[secp_message_instruction_index].data[secp_message_data_offset..secp_message_data_offset + secp_message_data_size])pubkey = ecrecover(signature, recovery_id, message_hash)eth_pubkey = keccak256(pubkey[1..])[12..]if eth_pubkey != ref_eth_pubkey {return Error}}return Success}
Это позволяет пользователю указывать любые данные инструкции в транзакции для подписи и данных сообщения. Указав специальную переменную sysvar инструкций, можно также получать данные непосредственно из самой транзакции.
Стоимость транзакции будет рассчитываться как количество подписей для проверки, умноженное на множитель стоимости проверки подписи.
Программа secp256r1 используется для проверки до 8 подписей secp256r1.
| Программа | ID программы | Описание | Инструкции |
|---|---|---|---|
| Программа secp256r1 | Secp256r1SigVerify1111111111111111111111111 | Проверяет до 8 подписей secp256r1. Принимает подпись, открытый ключ и сообщение. Возвращает ошибку, если хотя бы одна проверка не удалась. | Инструкции |
Программа secp256r1 обрабатывает инструкцию. Первый u8 инструкции содержит
количество подписей, которые необходимо проверить, за которым следует один байт
для выравнивания. После этого для каждой подписи создаётся следующая структура,
затем сериализуется и добавляется в данные инструкции.
struct Secp256r1SignatureOffsets {signature_offset: u16, // offset to compact secp256r1 signature of 64 bytessignature_instruction_index: u16, // instruction index to find signaturepublic_key_offset: u16, // offset to compressed public key of 33 bytespublic_key_instruction_index: u16, // instruction index to find public keymessage_data_offset: u16, // offset to start of message datamessage_data_size: u16, // size of message datamessage_instruction_index: u16, // index of instruction data to get message data}
Низкие значения S применяются ко всем подписям, чтобы избежать случайной изменяемости подписи.
process_instruction() {if data.len() < SIGNATURE_OFFSETS_START {return Error}num_signatures = data[0] as usizeif num_signatures == 0 || num_signatures > 8 {return Error}expected_data_size = num_signatures * SIGNATURE_OFFSETS_SERIALIZED_SIZE + SIGNATURE_OFFSETS_STARTif data.len() < expected_data_size {return Error}for i in 0..num_signatures {offsets = parse_signature_offsets(data, i)signature = get_data_slice(data, instruction_datas, offsets.signature_instruction_index, offsets.signature_offset, SIGNATURE_SERIALIZED_SIZE)if s > half_curve_order {return Error}pubkey = get_data_slice(data, instruction_datas, offsets.public_key_instruction_index, offsets.public_key_offset, COMPRESSED_PUBKEY_SERIALIZED_SIZE)message = get_data_slice(data, instruction_datas, offsets.message_instruction_index, offsets.message_data_offset, offsets.message_data_size)if !verify_signature(signature, pubkey, message) {return Error}}return Success}
Основные программы
Программы в списке ниже обеспечивают основную функциональность сети.
| Программа | ID программы | Описание | Инструкции |
|---|---|---|---|
| Системная | 11111111111111111111111111111111 | Создание новых аккаунтов, выделение данных аккаунта, назначение аккаунтов программам-владельцам, перевод лампортов с аккаунтов, принадлежащих системной программе, и оплата комиссий за транзакции | SystemInstruction |
| Голосование | Vote111111111111111111111111111111111111111 | Создание и управление аккаунтами, отслеживающими состояние голосования валидаторов и вознаграждения | VoteInstruction |
| Ставка | Stake11111111111111111111111111111111111111 | Создание и управление аккаунтами, представляющими ставки и вознаграждения за делегирование валидаторам | StakeInstruction |
| Конфигурация | Config1111111111111111111111111111111111111 | Добавление конфигурационных данных в цепочку, за которым следует список открытых ключей, которым разрешено их изменять. В отличие от других программ, программа Config не определяет никаких отдельных инструкций. У неё есть только одна неявная инструкция: "store". Данные инструкции — это набор ключей, которые ограничивают доступ к аккаунту и данным, хранящимся в нём | ConfigInstruction |
| Бюджет вычислений | ComputeBudget111111111111111111111111111111 | Установка лимитов вычислительных единиц и цен для транзакций, позволяя пользователям контролировать вычислительные ресурсы и сборы за приоритет | ComputeBudgetInstruction |
| Таблица поиска адресов | AddressLookupTab1e1111111111111111111111111 | Управление таблицами поиска адресов, которые позволяют транзакциям ссылаться на большее количество аккаунтов, чем может поместиться в списке аккаунтов транзакции | ProgramInstruction |
| ZK ElGamal Proof | ZkE1Gama1Proof11111111111111111111111111111 | Обеспечивает проверку доказательств с нулевым разглашением для данных, зашифрованных с использованием ElGamal | — |
Is this page helpful?