Landing Transactions Key Points
Aterrissar uma transação significa que um leader a inclui em um bloco enquanto seu recent blockhash ainda é válido, para que a assinatura passe de "desconhecida" para um status confirmado que você pode mostrar na UX do produto.
Esta página é o mapa conceitual de Priority Fees & Transaction Optimization - por que txs travam, como CU price e limites interagem, como clientes retentam com segurança, quando ALTs e Jito ajudam, e como escolhas de montagem moldam mercados de fee locais no Agave 4.1.1.
Resumo
- Inclusão é uma corrida contra expiração de blockhash sob capacidade do leader e competição de fee; clientes vencem licitando com inteligência (priority fees / tips), solicitando o compute budget certo, cabendo no pacote (v0 + ALTs) e retransmitindo ou reconstruindo com retries disciplinados.
- Por que importa: Simulação pode ter sucesso enquanto a mainnet ainda descarta o pacote; usuários veem "pendente para sempre" e lançamentos falham quando aterrissagem é um detalhe em vez de métrica de produto.
- Conceitos-chave: taxa de aterrissagem, recent blockhash / lastValidBlockHeight, limite de compute unit (CU), compute unit price (microLamports), priority fee, mercado de fee local, address lookup table (ALT), transação versionada (v0), Jito bundle / tip, preflight vs confirmação.
- Quando usar este modelo: Projetar pipelines de envio para carteiras, relayers, mints ou rotas DeFi; depurar descartes intermitentes; definir política de fee e retry antes de alto tráfego.
- Limitações / trade-offs: Lances e tips maiores elevam custo do usuário; simulação não reserva capacidade do leader; Jito e RPC privado melhoram probabilidade, não correção de programa; over-retry sem idempotência arrisca execução dupla.
- Tópicos relacionados: Why Transactions Fail to Land, Estimating Compute Units, Setting Priority Fees, Retries & Blockhash Management, Address Lookup Tables in Practice, Jito Bundles, Transaction Assembly.
Fundamentos
Um cliente monta uma mensagem (instruções, account metas, fee payer, recent blockhash), assina e envia a transação wire via RPC ou block engine. O nó pode rodar simulação de preflight, depois encaminha o pacote para leaders futuros.
Aterrissagem é inclusão em um bloco produzido. Confirmação é o quanto esse bloco progrediu em votos (processed → confirmed → finalized). Sucesso de produto quase sempre significa "aterrissou e teve sucesso no commitment escolhido", não "RPC aceitou o envio".
sendTransaction retornando assinatura só prova que o nó aceitou o caminho de submissão. A assinatura pode permanecer desconhecida para sempre se o pacote nunca ganhar um slot antes do blockhash expirar (~150 slots, frequentemente cerca de um minuto de relógio).
| Resultado | O que você observa | Causa típica |
|---|---|---|
| Nunca incluída | Status desconhecido / null após espera | Subprecificada, descartada, blockhash expirado, pacote oversized, peer ruim |
| Incluída, programa falhou | Assinatura encontrada, meta.err definido | Lógica, contas, CU excedido durante execução |
| Incluída, sucesso | Status no commitment escolhido, sem err | Caminho saudável |
Só a primeira linha é problema puro de aterrissagem. Orçamento de CU ainda importa tanto para economia de aterrissagem (preço × limite) quanto para a segunda linha (falha de execução após inclusão).
Fees têm duas camadas. Uma base fee cobre assinaturas. Uma priority fee é definida com instruções Compute Budget: set compute unit limit e set compute unit price (microLamports por CU). Priority lamports escalam aproximadamente com price × limit / 1_000_000. Leaders usam sinais de fee quando muitas transações competem por capacidade de bloco e locks de conta.
Essa competição é frequentemente local: contas quentes (vault de mint, pool popular, config compartilhada) criam mercado de fee local para transações que escrevem essas chaves, mesmo quando o resto da rede está tranquila.
Mecânica e interações
Por que transações falham em aterrissar
Leaders têm capacidade finita por slot. Sob carga preferem trabalho de maior valor. Sua transação também compete com validade de blockhash: após lastValidBlockHeight, validadores rejeitam a mensagem.
Caminhos comuns de descarte:
- Priority subprecificada em relação a pares bloqueando as mesmas contas quentes.
- Serialização oversized (mensagens legacy com muitas pubkeys completas).
- Problemas de RPC / caminho: endpoints públicos, perda de pacote ou peers que nunca chegam ao leader atual.
- Blockhash obsoleto no momento da assinatura ou loop de retry que mantém hash expirado.
- Falsa confiança de preflight: sim OK em snapshot de bank não reserva capacidade do leader.
Trate taxa de aterrissagem (envios que chegam a confirmed sem esgotar reconstruções) e p95 de tempo até confirmed como métricas de produto.
Priority fees e CU price
Use getRecentPrioritizationFees (opcionalmente escopado às contas que sua transação bloqueia) ou API de fee de provedor. Alvo um percentil: p50 tranquilo, p75 UX padrão, p90 mints e outra contenção. Aplique fator de segurança pequeno e teto rígido para que picos de fee não esvaziem usuários.
priority_fee_lamports ≈ (microLamports_per_CU × compute_unit_limit) / 1_000_000
total_user_fee ≈ base_signature_fee + priority_fee_lamports (+ optional tip)
Preço e limite multiplicam. Limite de CU inchado com preço agressivo paga demais; limite apertado com preço alto ainda falha se execução exceder o limite após inclusão. Corrija limite a partir de medição primeiro, depois licite preço para inclusão.
Estimando compute units
Orçamentos padrão não são ajustados para sua rota. Simule a transação totalmente montada, leia unitsConsumed e defina SetComputeUnitLimit para aproximadamente consumido × 1.1–1.2 de margem para variância de estado.
Em stacks da era Agave 4.1.1, tetos de CU por transação são finitos. Simulação que erra é problema de correção; simulação com sucesso e alto consumo é sinal de fee e risco. Testes locais (Anchor 0.32.1, LiteSVM, Surfpool) perfilam CU em desenvolvimento; percentis de fee na mainnet ainda precisam de amostras RPC ao vivo.
Retries e gerenciamento de blockhash
Duas operações diferentes:
- Rebroadcast dos mesmos bytes assinados enquanto o blockhash ainda é válido (mesma assinatura, mais propagação).
- Reconstruir com novo
getLatestBlockhash, nova mensagem e novas assinaturas (identidade de transação diferente).
Prefira controle da aplicação: frequentemente maxRetries baixo ou zero no RPC, depois seu loop espera confirmação, rebroadcasta a mesma forma wire até expiração de altura e só então reconstrói com blockhash e amostra de fee novos. Rastreie lastValidBlockHeight e pare rebroadcast após passar. Durable nonces substituem recent blockhashes de curta duração para fluxos multi-signer lentos.
Idempotência importa: se a primeira tentativa ainda pode aterrissar tarde, segunda reconstrução pode executar duas vezes a menos que o caminho do programa seja seguro para retry.
Address lookup tables
Transações versionadas v0 mais address lookup tables substituem muitas chaves de 32 bytes por índices de 1 byte em uma tabela on-chain. Isso reduz pacotes para que swaps multi-hop e montagens multi-instrução fiquem sob limites de tamanho que leaders propagam.
Ciclo de vida: criar → estender com pubkeys estáveis → esperar ativação (~1 slot) → compilar v0 com lookups → opcionalmente congelar. Clientes usando @solana/kit 7.0.0 buscam a ALT antes do compile para índices corresponderem à ordem on-chain. ALTs não elevam priority por si; removem um motivo estrutural de descarte e liberam espaço para instruções de budget e tip.
Jito bundles
Jito block engines aceitam bundles: transações ordenadas que aterrissam juntas atomicamente, tipicamente com transferência de tip. Use quando ordenação e atomicidade importam (mint + tip, caminhos multi-perna) ou quando exposição ao mempool público é inaceitável para fluxo de alto valor.
Bundles complementam priority fees nativas; não substituem limites de CU corretos ou blockhashes válidos. Mercados de tip têm curva de custo própria - reserve para janelas de contenção e rotas de alto valor.
Estratégias de montagem
Ordem de instrução faz parte da confiabilidade de aterrissagem e eficiência de fee:
- Compute budget: limite, depois preço.
- Setup que deve preceder lógica de negócio (create ATA idempotente, abrir contas).
- Instruções principais do programa.
- Tip / cleanup opcional conforme bundle ou política do produto.
Compile com a versão de mensagem certa, conjunto completo de signers e conjunto mínimo de contas writable. Marcar contas writable em excesso aumenta contenção de lock e pode piorar o mercado de fee local em que você licita. Simule a forma wire final antes do envio na mainnet.
fetch blockhash + fee samples (+ ALT accounts)
→ prepend CU limit + price → core ixs (+ optional tip)
→ compile v0 with ALTs → sign → simulate
→ send (RPC and/or Jito) → wait commitment
unknown & hash valid → rebroadcast same bytes
expired / timed out → rebuild (new hash, fees, sign)
landed + err → fix program/accounts (do not blind retry)
landed + ok → done
Considerações avançadas e aplicações
Mercados de fee locais se formam em torno de contas writable contidas. Amostrar prioritization fees com as contas que sua rota bloqueia frequentemente supera amostras globais vazias quando congestionamento é específico do caminho. Mantenha perfis de fee por template (transfer vs swap vs mint) com pisos, percentis e tetos separados.
SWQoS e RPC privado melhoram a chance de pacotes chegarem a leaders. Combinam com política de fee; não a substituem. Caminhos de envio em produção geralmente querem tier pago e envio dual-path para rotas críticas (RPC mais block engine).
UX de custo: mostre priority SOL estimada de price × limit, mais base fee e tip opcional. Limite multiplicadores durante picos. Feature-flag percentis agressivos para decair fora de pico sem crise de deploy.
Medição: registre assinatura, id de rota, microLamports, limite de CU, unidades consumidas (sim e meta aterrissada), tip lamports, tentativas e tempo até confirmed. Taxa de aterrissagem e fee por confirmação bem-sucedida orientam escolha de percentil.
| Situação | Prefira |
|---|---|
| Mainnet tranquila, ix simples | Piso modesto de CU price, retry padrão |
| Contas quentes compartilhadas | Amostras de fee escopadas por conta, percentil maior |
| Listas grandes de contas | Job de manutenção v0 + ALT |
| Multi-tx atômico ou dia de mint | Jito bundle + política de tip |
| Multisig / assinatura lenta | Durable nonce |
| Sim falha | Corrija programa ou contas antes de subir fees |
Ressalva devnet: mercados de fee e taxas de descarte não correspondem à mainnet. Valide montagem, ativação de ALT e máquinas de estado de retry em devnet; valide percentis de fee e SLOs de aterrissagem com probes pequenos na mainnet.
Equívocos comuns
- "RPC retornou assinatura, então a transação aterrissou." Aceitação não é inclusão; espere status ou assinatura até regras de expiração dizerem parar.
- "Priority fee zero está ok se simulação passou." Simulação não compra prioridade do leader; sob congestionamento, trabalho com lance zero fica sem recurso primeiro.
- "Limite máximo de CU mais preço máximo sempre ganha barato." Você multiplica custo; dimensione limite a partir de simulação, depois licite preço com teto.
- "Aumentar limite de CU corrige descartes de aterrissagem." Limite evita falhas compute-exceeded após inclusão; descartes precisam de fees, tamanho, caminho e disciplina de blockhash.
- "maxRetries do RPC sozinho é estratégia de retry." Sem blockhashes novos e esperas de confirmação, você spamma trabalho expirado; controle o loop.
- "Transações legacy são mais simples então aterrissam mais." Listas de contas legacy oversized descartam; v0 + ALTs são o caminho confiável para rotas pesadas.
- "Tips Jito substituem compute unit price." Tips incentivam inclusão em bundle; priority fees nativas ainda importam para envios não-bundle e podem coexistir.
- "Qualquer retry é seguro." Reconstruções com assinaturas novas podem aplicar duas vezes se a primeira tx ainda aterrissar; projete instruções idempotentes ou rastreie estado in-flight.
- "Percentil global de fee equivale ao mercado da minha rota." Contenção local nas suas contas writable pode divergir de amostras em toda a rede.
- "Aterrissagem em devnet prova política na mainnet." Mecânica transfere; níveis de fee e contenção não.
FAQs
O que significa "aterrissar" em uma frase?
Um leader incluiu sua transação em um bloco antes do recent blockhash ficar inválido, para que a assinatura seja descobrível on-chain (sucesso ou erro de programa).
Como aterrissagem difere de confirmação?
Aterrissagem é inclusão. Confirmação é quantos validadores votaram naquele bloco (processed, confirmed, finalized). UX geralmente espera pelo menos confirmed.
Por que transações falham em aterrissar se simulação tem sucesso?
Simulação verifica execução contra snapshot de bank. Não reserva capacidade do leader, vence leilão de fee ou garante propagação de pacote antes da expiração do blockhash.
Como priority fees se relacionam com compute unit price?
Compute unit price é microLamports por CU. Priority fee paga escala com esse preço vezes o limite de compute unit solicitado (base signature fees são separadas).
Como estimar compute units antes do envio?
Monte a transação real, simule, leia unitsConsumed, adicione cerca de 10–20% de margem e defina SetComputeUnitLimit. Detalhes em Estimating Compute Units.
Qual percentil usar para prioritization fees?
Comece em torno de p75 com multiplicador pequeno e teto rígido para UX normal; suba para p90 em mints e janelas quentes; meça taxa de aterrissagem e ajuste. Veja Setting Priority Fees.
Quando rebroadcast vs reconstruir com blockhash novo?
Rebroadcast a mesma transação assinada enquanto lastValidBlockHeight ainda está à frente. Reconstrua e reassine quando o hash expirar ou você precisar mudar fees ou instruções. Veja Retries & Blockhash Management.
Transações que falharam on-chain ainda pagam priority fees?
Se a transação é incluída e falha durante execução, fees de inclusão ainda se aplicam. Transações descartadas que nunca aterrissam não pagam nada on-chain.
Quando usar address lookup tables?
Quando listas de contas tornam mensagens legacy grandes demais ou não deixam espaço para instruções de budget e tip. Use compilação v0 com ALTs mantidas. Veja Address Lookup Tables in Practice.
Quando usar Jito bundles em vez de envio normal?
Quando você precisa de ordenação multi-transação atômica, incentivos de inclusão mais fortes via tips, ou menor exposição ao mempool público para fluxos de alto valor. Veja Jito Bundles.
O que é mercado de fee local?
Pressão de fee concentrada em transações que bloqueiam as mesmas contas writable quentes (pools, mints, vaults compartilhados), que pode superar médias globais tranquilas. Amostre fees com essas contas quando possível.
Em que ordem montar instruções?
Compute budget primeiro, depois setup de contas, depois instruções de negócio principais, depois tips ou cleanup opcional. Padrões completos em Transaction Assembly.
skipPreflight ajuda a aterrissar?
skipPreflight: true pode reduzir latência mas envia mais transações fadadas ao fracasso. Prefira preflight ligado para carteiras de usuário; skip seletivo é para caminhos de baixa latência especializados que já simularam offline.
Priority fees garantem aterrissagem?
Não. Elas elevam probabilidade de inclusão sob contenção. Bugs de programa, esgotamento de CU, contas ruins, blockhashes expirados e falhas de caminho ainda impedem sucesso.
Como @solana/kit e Anchor se encaixam neste modelo?
Anchor 0.32.1 molda programas on-chain e clientes orientados por IDL; @solana/kit 7.0.0 monta, assina, simula e envia transações versionadas. Nenhum remove a necessidade de política de fee, CU, blockhash e confirmação.
Relacionados
- Why Transactions Fail to Land - categorias de falha e sinais de triagem
- Estimating Compute Units - limites de CU baseados em simulação e margem
- Setting Priority Fees - percentis, tetos e estratégia de CU price
- Retries & Blockhash Management - rebroadcast, reconstrução e durable nonces
- Address Lookup Tables in Practice - redução de tamanho v0 para conjuntos grandes de contas
- Jito Bundles - caminhos de aterrissagem atômicos baseados em tip
- Transaction Assembly - ordem de instrução, empacotamento e checklist de compile
Versões da stack: Esta página foi escrita para Agave 4.1.1, Solana CLI 3.0.10, Anchor 0.32.1, Rust 1.91.1 e @solana/kit 7.0.0.