Программы

На 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.

Программы-загрузчики

Каждая программа принадлежит другой программе — её загрузчику. Загрузчики используются для развертывания, повторного развертывания, обновления или закрытия программ. Они также используются для финализации программы и передачи полномочий программы.

Программы-загрузчики иногда называют «BPF-загрузчиками».

В настоящее время существует пять программ-загрузчиков, как показано в таблице ниже.

ЗагрузчикID программыПримечанияСсылка на инструкции
nativeNativeLoader1111111111111111111111111111111Управляющие инструкции отключены, но программы продолжают выполняться
v1BPFLoader1111111111111111111111111111111111Управляющие инструкции отключены, но программы продолжают выполняться
v2BPFLoader2111111111111111111111111111111111Управляющие инструкции отключены, но программы продолжают выполнятьсяИнструкции
v3BPFLoaderUpgradeab1e11111111111111111111111Программы могут быть обновлены после развертывания. Исполняемый файл программы хранится в отдельном аккаунте данных программыИнструкции
v4LoaderV411111111111111111111111111111111111В разработке (не выпущен)Инструкции

Программы, развернутые с использованием loader-v3 или loader-v4, могут быть изменяемыми после развертывания, если это предусмотрено полномочиями на обновление.

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

Предварительно скомпилированные программы

Помимо программ загрузчика, Solana предоставляет следующие предварительно скомпилированные программы.

Проверка подписи ed25519

Программа ed25519 используется для проверки одной или нескольких подписей ed25519.

ПрограммаID программыОписаниеИнструкции
Программа Ed25519Ed25519SigVerify111111111111111111111111111Проверяет подписи ed25519. Если какая-либо подпись не проходит проверку, возвращается ошибка.Инструкции

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

Ed25519SignatureOffsets
struct Ed25519SignatureOffsets {
signature_offset: u16, // offset to ed25519 signature of 64 bytes
signature_instruction_index: u16, // instruction index to find signature
public_key_offset: u16, // offset to public key of 32 bytes
public_key_instruction_index: u16, // instruction index to find public key
message_data_offset: u16, // offset to start of message data
message_data_size: u16, // size of message data
message_instruction_index: u16, // index of instruction data to get message data
}
Signature verification pseudocode
process_instruction() {
for i in 0..count {
// i'th index values referenced:
instructions = &transaction.message().instructions
instruction_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 программыОписаниеИнструкции
Программа Secp256k1KeccakSecp256k11111111111111111111111111111Проверяет операции восстановления открытого ключа secp256k1 (ecrecover).Инструкции

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

Secp256k1SignatureOffsets
struct Secp256k1SignatureOffsets {
secp_signature_offset: u16, // offset to [signature,recovery_id] of 64+1 bytes
secp_signature_instruction_index: u8, // instruction index to find signature
secp_pubkey_offset: u16, // offset to ethereum_address pubkey of 20 bytes
secp_pubkey_instruction_index: u8, // instruction index to find pubkey
secp_message_data_offset: u16, // offset to start of message data
secp_message_data_size: u16, // size of message data
secp_message_instruction_index: u8, // instruction index to find message data
}
Recovery verification pseudocode
process_instruction() {
for i in 0..count {
// i'th index values referenced:
instructions = &transaction.message().instructions
signature = 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 программыОписаниеИнструкции
Программа secp256r1Secp256r1SigVerify1111111111111111111111111Проверяет до 8 подписей secp256r1. Принимает подпись, открытый ключ и сообщение. Возвращает ошибку, если хотя бы одна проверка не удалась.Инструкции

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

Secp256r1SignatureOffsets
struct Secp256r1SignatureOffsets {
signature_offset: u16, // offset to compact secp256r1 signature of 64 bytes
signature_instruction_index: u16, // instruction index to find signature
public_key_offset: u16, // offset to compressed public key of 33 bytes
public_key_instruction_index: u16, // instruction index to find public key
message_data_offset: u16, // offset to start of message data
message_data_size: u16, // size of message data
message_instruction_index: u16, // index of instruction data to get message data
}

Низкие значения S применяются ко всем подписям, чтобы избежать случайной изменяемости подписи.

Signature verification psuedocode
process_instruction() {
if data.len() < SIGNATURE_OFFSETS_START {
return Error
}
num_signatures = data[0] as usize
if num_signatures == 0 || num_signatures > 8 {
return Error
}
expected_data_size = num_signatures * SIGNATURE_OFFSETS_SERIALIZED_SIZE + SIGNATURE_OFFSETS_START
if 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 ProofZkE1Gama1Proof11111111111111111111111111111Обеспечивает проверку доказательств с нулевым разглашением для данных, зашифрованных с использованием ElGamal

Is this page helpful?

Программы | Solana