Cross Program Invocation (CPI) — это когда одна программа вызывает инструкцию другой программы во время исполнения. CPI позволяют создавать композиционные решения: инструкции любой программы могут быть вызваны любой другой программой в сети.
Пример cross-program invocation
CPI без PDA-подписантов
Использование функции invoke, Anchor CpiContext, примеры на Native Rust, примеры CPI для перевода SOL.
CPI с PDA-подписантами
Использование invoke_signed с seeds для подписанта, Anchor CpiContext с PDA, примеры подписания PDA на Native Rust.
Выполнение CPI и привилегии
11 шагов выполнения CPI, правила расширения привилегий, реентерабельность, валидация аккаунтов.
Модель стоимости CPI и синхронизация данных
Формула стоимости CPI, затраты на сериализацию, синхронизация данных аккаунта, подписание PDA, возврат данных.
Основные факты
- Две функции:
invoke(без подписи PDA) иinvoke_signed(с подписью PDA). - Расширение привилегий: Привилегии аккаунта (signer, writable) передаются от вызывающей программы к вызываемой. Вызываемая программа не может повысить привилегии сверх переданных.
- Общий бюджет вычислений: Использование CU вызываемой программой уменьшает оставшийся бюджет вызывающей.
- Реентерабельность: Прямая саморекурсия разрешена (A→A→A). Косвенная
реентерабельность запрещена (A→B→A возвращает
ReentrancyNotAllowed).
Ограничения
| Ограничение | Значение | Источник |
|---|---|---|
| Максимальная глубина стека инструкций | 5 (9 с SIMD-0268) | MAX_INSTRUCTION_STACK_DEPTH, MAX_INSTRUCTION_STACK_DEPTH_SIMD_0268 |
| Стоимость вызова CPI | 1 000 CU (946 с SIMD-0339) | DEFAULT_INVOCATION_COST, INVOKE_UNITS_COST_SIMD_0339 |
| Максимум PDA-подписантов на CPI | 16 | MAX_SIGNERS |
| Максимальный размер данных инструкции CPI | 10 КиБ (10 240 байт) | MAX_INSTRUCTION_DATA_LEN |
| Максимальный размер возвращаемых данных | 1 024 байта | MAX_RETURN_DATA |
| Максимум CPI account infos | 128 (255 с SIMD-0339)* | MAX_CPI_ACCOUNT_INFOS, MAX_CPI_ACCOUNT_INFOS_SIMD_0339 |
| Стоимость сериализации CPI | 1 CU за 250 байт | cpi_bytes_per_unit |
| Максимальный realloc данных аккаунта на CPI | 10 240 байт (10 КиБ) | MAX_PERMITTED_DATA_INCREASE |
invoke против invoke_signed
Solana предоставляет две функции для выполнения CPI:
| Функция | Сценарий использования | Подпись от PDA |
|---|---|---|
invoke | CPI, где все необходимые подписанты уже подписали исходную транзакцию | Нет |
invoke_signed | CPI, где вызывающая программа должна подписывать от имени принадлежащего ей PDA | Да, через signer seeds |
Внутри invoke просто вызывает invoke_signed с пустым массивом signer
seeds. Используйте invoke, когда подпись PDA не требуется, и
invoke_signed — когда программе нужно авторизовать действие от имени PDA.
Обе функции в конечном итоге вызывают один и тот же системный вызов
(sol_invoke_signed_rust)
и проходят по одному и тому же пути выполнения
(cpi_common).
Единственное различие — предоставляются ли signer seeds. Если seeds указаны,
рантайм вычисляет PDA pubkey и добавляет их в список допустимых подписантов до
проверки привилегий.
Is this page helpful?