Um Cross-Program Invocation (CPI) ocorre quando um programa chama uma instrução em outro programa durante a execução. CPIs permitem composabilidade: as instruções de qualquer programa podem ser invocadas por qualquer outro programa na rede.
Exemplo de cross-program invocation
CPIs sem signatários PDA
Usando a função invoke, Anchor CpiContext, exemplos em Rust nativo, exemplos de CPI de transferência SOL.
CPIs com signatários PDA
Usando invoke_signed com seeds de signatário, Anchor CpiContext com PDA, exemplos de assinatura PDA em Rust nativo.
Execução e privilégios de CPI
Fluxo de execução de CPI em 11 etapas, regras de extensão de privilégios, reentrância, validação de contas.
Modelo de custo de CPI e sincronização de dados
Fórmula de custo de CPI, custos de serialização, sincronização de dados de conta, assinatura PDA, dados de retorno.
Factos principais
- Duas funções:
invoke(sem assinatura PDA) einvoke_signed(com assinatura PDA). - Extensão de privilégios: Os privilégios de conta (signatário, gravável) estendem-se do chamador para o chamado. Um chamado não pode escalar privilégios além do que o chamador passou.
- Orçamento de computação partilhado: O consumo de CU do chamado reduz o orçamento restante do chamador.
- Reentrância: A auto-recursão direta é permitida (A->A->A). A reentrância
indireta não é permitida (A->B->A retorna
ReentrancyNotAllowed).
Limites
| Limite | Valor | Fonte |
|---|---|---|
| Profundidade máxima da pilha de instruções | 5 (9 com SIMD-0268) | MAX_INSTRUCTION_STACK_DEPTH, MAX_INSTRUCTION_STACK_DEPTH_SIMD_0268 |
| Custo de invocação de CPI | 1.000 CUs (946 com SIMD-0339) | DEFAULT_INVOCATION_COST, INVOKE_UNITS_COST_SIMD_0339 |
| Máximo de signatários 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 dados de retorno | 1.024 bytes | MAX_RETURN_DATA |
| Máximo de account infos de CPI | 128 (255 com SIMD-0339)* | MAX_CPI_ACCOUNT_INFOS, MAX_CPI_ACCOUNT_INFOS_SIMD_0339 |
| Custo de serialização de CPI | 1 CU por 250 bytes | cpi_bytes_per_unit |
| Máximo de realocação de dados de conta por CPI | 10.240 bytes (10 KiB) | MAX_PERMITTED_DATA_INCREASE |
invoke vs invoke_signed
Solana fornece duas funções para fazer CPIs:
| Função | Caso de uso | Assinatura PDA |
|---|---|---|
invoke | CPIs onde todos os signatários necessários já assinaram a transação original | Não |
invoke_signed | CPIs onde o programa chamador precisa assinar em nome de um PDA que possui | Sim, via sementes de signatário |
Internamente, invoke simplesmente chama invoke_signed com um array
vazio de sementes de signatário. Use invoke quando não precisar de
assinatura PDA, e invoke_signed quando o programa precisar autorizar uma
ação em nome de um PDA.
Ambas as funções acabam por acionar a mesma syscall
(sol_invoke_signed_rust)
e fluem pelo mesmo caminho de runtime
(cpi_common).
A única diferença é se as sementes de signatário são fornecidas. Quando as
sementes são fornecidas, o runtime deriva chaves públicas PDA e adiciona-as ao
conjunto de signatários válidos antes da verificação de privilégios.
Is this page helpful?