Межпрограммные вызовы (CPI)
Кросс-Программный вызов (CPI) относится к случаю, когда одна программа вызывает инструкции другой программы. Этот механизм позволяет совместимости программ Solana.
Инструкции можно рассматривать как конечные точки API, которые программа выдает в сеть, а CPI - как внутренний вызов одного API другим API.
Межпрограммное обращение
Когда программа инициирует межпрограммное обращение (CPI) к другой программе:
- Привилегии подписывающего лица из начальной транзакции, вызывающей вызывающую программу (A), распространяются на вызывающую программу (B).
- Вызывающая программа (B) может выполнять дальнейшие CPI для других программ, вплоть до максимальной глубины 4 (например, B->C, C->D).
- Программы могут "подписываться" от имени PDA, полученного по идентификатору программы.
Время выполнения программы Solana определяет константу под названием max_invoke_stack_height, которая устанавливается на значение 5. Она представляет собой максимальную высоту стека вызовов программных инструкций. Высота стека начинается с 1 для инструкций транзакции и увеличивается на 1 каждый раз, когда программа вызывает другую инструкцию. Эта настройка эффективно ограничивает глубину вызова для CPI до 4.
Ключевые точки #
-
CPI позволяют использовать инструкции программы Solana для непосредственного вызова инструкций на другой программе .
-
Привилегии сигнала из программы вызывающего абонента распространяются на программу callee.
-
При создании CPI программы могут "подписываться" от имени PDA на основе собственного ID программы.
-
Программа callee может сделать дополнительные CPI для других программ, вплоть до максимальной глубины 4.
Как написать CPI #
Написание инструкции для CPI происходит по той же схеме, что и создание инструкции для добавления в транзакцию. Внутри каждая инструкция CPI должна содержать следующую информацию:
- Program address: Указывает вызываемую программу.
- Accounts: Перечисляет все учетные записи, с которых инструкция считывает или на которые записывает данные, включая другие программы
- Instruction Data: Указывает, какую инструкцию программы следует вызвать, а также любые дополнительные данные, требуемые инструкцией (аргументы функции).
В зависимости от программы, к которой вы обращаетесь, могут быть доступны контейнеры с вспомогательными функциями для создания инструкции. Затем программы выполняют CPI, используя одну из следующих функций из контейнера solana_program:
invoke
- используется, когда нет подписчиков PDAinvoke_signed
- используется, когда программа вызывающего абонента должна подписаться с PDA полученным от идентификатора программы
Основной CPI #
Функция invoke используется при создании CPI, для которого не требуются подписывающие устройства PDA. При создании CPI подписи, предоставленные программе-вызывателю, автоматически распространяются на программу-получателя.
pub fn invoke(
instruction: &Instruction,
account_infos: &[AccountInfo<'_>]
) -> Result<(), ProgramError>
Вот пример программы [Playana Playground](https://beta.solpg.io/github. om/ZYJLiu/doc-examples/tree/main/cpi-invoke)
, в результате чего CPI использует функцию invoke
для вызова инструкции по передаче
на Системной программе. Вы также можете обратиться к Базовому руководству по CPI
для получения более подробной информации.
CPI с PDA подписчик #
Функция invoke используется при создании CPI, для которого не требуются подписывающие устройства PDA. Семена, используемые для получения PDA подписывающего лица, передаются в функцию invoke_signed как signer_seeds.
Для получения подробной информации о том, как выводятся PDA, вы можете обратиться к странице "Производные адреса программ".
pub fn invoke_signed(
instruction: &Instruction,
account_infos: &[AccountInfo<'_>],
signers_seeds: &[&[&[u8]]]
) -> Result<(), ProgramError>
Время выполнения использует привилегии, предоставленные вызывающей программе, чтобы определить, какие привилегии могут быть предоставлены вызываемой. Привилегии в данном контексте относятся к подписывающим и записывающим учетным записям. Например, если инструкция, которую обрабатывает вызывающая программа, содержит учетную запись с возможностью подписи или записи, то вызывающая программа может вызвать инструкцию, которая также содержит эту учетную запись с возможностью подписи и/или записи.
Хотя у PDA нет закрытых ключей, они все равно могут выступать в качестве подписывающего лица в инструкции через CPI. Чтобы убедиться, что PDA получен из вызывающей программы, семена, использованные для генерации PDA, должны быть включены в качестве signers_seeds.
Когда CPI обрабатывается, среда выполнения Solana внутренне вызывает create_program_address, используя signers_seeds и program_id вызывающей программы. Если найден действительный PDA, адрес добавляется в качестве действительного подписанта.
Вот пример программы на Solana Playground, которая создает CPI с помощью функции invoke_signed для вызова инструкции передачи в системной программе с PDA подписантом. Вы также можете обратиться к Базовому руководству по CPIfor) для получения более подробной информации.