Cross Program Invocation (CPI) — це коли одна програма викликає інструкцію іншої програми під час виконання. CPI забезпечують композиційність: інструкції будь-якої програми можуть бути викликані будь-якою іншою програмою в мережі.
Приклад міжпрограмного виклику
CPI без підписувачів PDA
Використання функції invoke, Anchor CpiContext, приклади на нативному Rust, приклади CPI для переказу SOL.
CPI з підписувачами PDA
Використання invoke_signed з сідами підписувача, Anchor CpiContext з PDA, приклади підписання PDA на нативному Rust.
Виконання CPI та привілеї
11-кроковий процес виконання CPI, правила розширення привілеїв, реентерабельність, валідація акаунтів.
Модель вартості CPI та синхронізація даних
Формула вартості CPI, витрати на серіалізацію, синхронізація даних акаунтів, підписання PDA, повернення даних.
Ключові факти
- Дві функції:
invoke(без підписання PDA) таinvoke_signed(з підписанням PDA). - Розширення привілеїв: привілеї акаунта (підписувач, доступний для запису) передаються від викликача до викликаного. Викликаний не може підвищити привілеї понад те, що передав викликач.
- Спільний бюджет обчислень: споживання 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 |
| Макс. розмір instruction data для CPI | 10 КіБ (10,240 байтів) | MAX_INSTRUCTION_DATA_LEN |
| Макс. розмір даних, що повертаються | 1,024 байти | MAX_RETURN_DATA |
| Макс. кількість account infos для CPI | 128 (255 з SIMD-0339)* | MAX_CPI_ACCOUNT_INFOS, MAX_CPI_ACCOUNT_INFOS_SIMD_0339 |
| Вартість серіалізації CPI | 1 CU на 250 байтів | cpi_bytes_per_unit |
| Макс. зміна розміру даних акаунта на CPI | 10,240 байтів (10 КіБ) | MAX_PERMITTED_DATA_INCREASE |
invoke проти invoke_signed
Solana надає дві функції для здійснення CPI:
| Функція | Випадок використання | Підписання PDA |
|---|---|---|
invoke | CPI, де всі необхідні підписувачі вже підписали початкову транзакцію | Ні |
invoke_signed | CPI, де програма, що викликає, повинна підписати від імені PDA, яким вона володіє | Так, через сіди підписувача |
Під капотом invoke просто викликає invoke_signed з порожнім масивом
сідів підписувача. Використовуйте invoke, коли вам не потрібне підписання
PDA, і invoke_signed, коли програма повинна авторизувати дію від імені
PDA.
Обидві функції зрештою викликають один і той самий системний виклик
(sol_invoke_signed_rust)
і проходять через один і той самий шлях виконання
(cpi_common).
Єдина різниця полягає в тому, чи надаються сіди підписувача. Коли сіди
надаються, середовище виконання виводить публічні ключі PDA та додає їх до
набору дійсних підписувачів перед перевіркою привілеїв.
Is this page helpful?