Межпрограммные вызовы (CPI)

Кросс-Программный вызов (CPI) относится к случаю, когда одна программа вызывает инструкции другой программы. Этот механизм позволяет совместимости программ Solana.

Инструкции можно рассматривать как конечные точки API, которые программа выдает в сеть, а CPI - как внутренний вызов одного API другим API.

Межпрограммное обращение

Когда программа инициирует межпрограммное обращение (CPI) к другой программе:

  • Привилегии подписывающего лица из начальной транзакции, вызывающей вызывающую программу (A), распространяются на вызывающую программу (B).
  • Вызывающая программа (B) может выполнять дальнейшие CPI для других программ, вплоть до максимальной глубины 4 (например, B->C, C->D).
  • Программы могут "подписываться" от имени PDA, полученного по идентификатору программы.
Info

Время выполнения программы 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 - используется, когда нет подписчиков PDA
  • invoke_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) для получения более подробной информации.