Un Cross Program Invocation (CPI) es cuando un programa llama a una instrucción en otro programa durante la ejecución. Los CPIs permiten la composabilidad: las instrucciones de cualquier programa pueden ser invocadas por cualquier otro programa en la red.
Ejemplo de cross-program invocation
CPIs sin firmantes PDA
Usando la función invoke, Anchor CpiContext, ejemplos de Rust nativo, ejemplos de CPI de transferencia de SOL.
CPIs con firmantes PDA
Usando invoke_signed con signer seeds, Anchor CpiContext con PDA, ejemplos de firma PDA en Rust nativo.
Ejecución y privilegios de CPI
Flujo de ejecución de CPI en 11 pasos, reglas de extensión de privilegios, reentrancia, validación de cuentas.
Modelo de costos de CPI y sincronización de datos
Fórmula de costos de CPI, costos de serialización, sincronización de datos de cuentas, firma PDA, datos de retorno.
Datos clave
- Dos funciones:
invoke(sin firma PDA) yinvoke_signed(con firma PDA). - Extensión de privilegios: Los privilegios de cuenta (firmante, escribible) se extienden del llamador al llamado. Un llamado no puede escalar privilegios más allá de lo que el llamador pasó.
- Presupuesto de cómputo compartido: El consumo de CU del llamado reduce el presupuesto restante del llamador.
- Reentrancia: La auto-recursión directa está permitida (A->A->A). La
reentrancia indirecta no lo está (A->B->A devuelve
ReentrancyNotAllowed).
Límites
| Límite | Valor | Fuente |
|---|---|---|
| Profundidad máxima de pila de instrucciones | 5 (9 con SIMD-0268) | MAX_INSTRUCTION_STACK_DEPTH, MAX_INSTRUCTION_STACK_DEPTH_SIMD_0268 |
| Costo de invocación de CPI | 1,000 CUs (946 con SIMD-0339) | DEFAULT_INVOCATION_COST, INVOKE_UNITS_COST_SIMD_0339 |
| Máximo de firmantes PDA por CPI | 16 | MAX_SIGNERS |
| Máximo de instruction data de CPI | 10 KiB (10,240 bytes) | MAX_INSTRUCTION_DATA_LEN |
| Máximo de datos de retorno | 1,024 bytes | MAX_RETURN_DATA |
| Máximo de account infos de CPI | 128 (255 con SIMD-0339)* | MAX_CPI_ACCOUNT_INFOS, MAX_CPI_ACCOUNT_INFOS_SIMD_0339 |
| Costo de serialización de CPI | 1 CU por 250 bytes | cpi_bytes_per_unit |
| Máximo de realloc de datos de cuenta por CPI | 10,240 bytes (10 KiB) | MAX_PERMITTED_DATA_INCREASE |
invoke vs invoke_signed
Solana proporciona dos funciones para realizar CPIs:
| Función | Caso de uso | Firma de PDA |
|---|---|---|
invoke | CPIs donde todos los firmantes requeridos ya han firmado la transacción original | No |
invoke_signed | CPIs donde el programa que llama necesita firmar en nombre de un PDA que posee | Sí, mediante semillas de firmante |
Internamente, invoke simplemente llama a invoke_signed con un array
de semillas de firmante vacío. Usa invoke cuando no necesites firma de
PDA, y invoke_signed cuando el programa deba autorizar una acción en
nombre de un PDA.
Ambas funciones finalmente activan la misma syscall
(sol_invoke_signed_rust)
y fluyen a través de la misma ruta de ejecución
(cpi_common).
La única diferencia es si se proporcionan semillas de firmante. Cuando se
proporcionan semillas, el runtime deriva las claves públicas de PDA y las añade
al conjunto de firmantes válidos antes de la verificación de privilegios.
Is this page helpful?