Программы

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

Ключевые моменты

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

Написание программ Solana

Программы Solana преимущественно пишутся на языке программирования Rust, с двумя распространенными подходами к разработке:

  • Anchor: Фреймворк, разработанный для разработки программ Solana. Он обеспечивает более быстрый и простой способ написания программ, используя макросы Rust для уменьшения шаблонного кода. Для начинающих рекомендуется начать с фреймворка Anchor.

  • Нативный Rust: Этот подход включает написание программ Solana на Rust без использования каких-либо фреймворков. Он предлагает больше гибкости, но сопряжен с повышенной сложностью.

Обновление программ Solana

Чтобы узнать больше о развертывании и обновлении программ, см. страницу о развертывании программ.

Программы могут быть напрямую изменены аккаунтом, назначенным как "полномочие на обновление", которым обычно является аккаунт, изначально развернувший программу. Если полномочие на обновление отозвано и установлено в None, программа становится неизменяемой и больше не может быть обновлена.

Проверяемые программы

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

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

  • Поиск проверенных программ: Чтобы быстро проверить наличие верифицированных программ, пользователи могут искать адрес программы на Solana Explorer. Пример проверенной программы можно посмотреть здесь.

  • Инструменты верификации: Solana Verifiable Build CLI от Ellipsis Labs позволяет пользователям самостоятельно проверять программы в блокчейне на соответствие опубликованному исходному коду.

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

Berkeley Packet Filter (BPF)

Solana использует LLVM (Low Level Virtual Machine) для компиляции программ в ELF (Executable and Linkable Format) файлы. Эти файлы содержат пользовательскую версию eBPF байткода от Solana, называемую "Solana Bytecode Format" (sBPF). ELF-файл содержит бинарный код программы и хранится в блокчейне в исполняемом аккаунте при развёртывании программы.

Встроенные программы

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

Каждая программа сама принадлежит другой программе, которая является её загрузчиком. В настоящее время существует пять программ-загрузчиков:

ЗагрузчикID программыПримечанияСсылка на инструкции
nativeNativeLoader1111111111111111111111111111111Владеет остальными четырьмя загрузчиками
v1BPFLoader1111111111111111111111111111111111Инструкции управления отключены, но программы всё ещё выполняются
v2BPFLoader2111111111111111111111111111111111Инструкции управления отключены, но программы всё ещё выполняютсяИнструкции
v3BPFLoaderUpgradeab1e11111111111111111111111Постепенно выводится из эксплуатацииИнструкции
v4LoaderV411111111111111111111111111111111111Ожидается, что v4 станет стандартным загрузчикомИнструкции

Эти загрузчики необходимы для создания и управления пользовательскими программами:

  • Развертывание новой программы или буфера
  • Закрытие программы или буфера
  • Повторное развертывание / обновление существующей программы
  • Передача прав управления программой
  • Финализация программы

Loader-v3 и loader-v4 поддерживают модификации программ после их первоначального развертывания. Разрешение на это регулируется правами доступа к программе, поскольку владение аккаунтом каждой программы принадлежит загрузчику.

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

Программа 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
}

Псевдокод проверки подписи:

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

Программа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
}

Псевдокод проверки восстановления:

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

ПрограммаID программыОписаниеИнструкции
Программа Secp256r1Secp256r1SigVerify1111111111111111111111111Проверяет до 8 подписей secp256r1. Принимает подпись, публичный ключ и сообщение. Возвращает ошибку при неудаче.Instructions

Программа 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
}

Псевдокод проверки подписи:

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
}

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

Основные программы

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

ПрограммаID программыОписаниеИнструкции
Системная программа11111111111111111111111111111111Создание новых аккаунтов, выделение данных аккаунта, назначение аккаунтов владеющим программам, перевод lamport с аккаунтов, принадлежащих системной программе, и оплата комиссий за транзакции.SystemInstruction
Программа голосованияVote111111111111111111111111111111111111111Создание и управление аккаунтами, которые отслеживают состояние голосования validator и вознаграждения.VoteInstruction
Программа стейкингаStake11111111111111111111111111111111111111Создание и управление аккаунтами, представляющими стейк и вознаграждения за делегирование validator.StakeInstruction
Программа конфигурацииConfig1111111111111111111111111111111111111Добавление данных конфигурации в цепочку, за которыми следует список публичных ключей, которым разрешено их изменять. В отличие от других программ, программа конфигурации не определяет отдельных инструкций. У нее есть только одна неявная инструкция: "store". Ее instruction data - это набор ключей, которые контролируют доступ к аккаунту и данным в нем.ConfigInstruction
Программа бюджета вычисленийComputeBudget111111111111111111111111111111Установка лимитов вычислительных единиц и цен для транзакций, позволяющая пользователям контролировать вычислительные ресурсы и приоритетные комиссии.ComputeBudgetInstruction
Программа таблиц поиска адресовAddressLookupTab1e1111111111111111111111111Управление таблицами поиска адресов, которые позволяют транзакциям ссылаться на большее количество аккаунтов, чем могло бы поместиться в список аккаунтов транзакции.ProgramInstruction
Программа ZK ElGamal ProofZkE1Gama1Proof11111111111111111111111111111Обеспечивает верификацию доказательств с нулевым разглашением для данных, зашифрованных по методу ElGamal.

Is this page helpful?