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.
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?