Para desenvolvedores / JSON-RPC
Histórico e retenção
O nó é um índice RPC, não um arquivo. Ele guarda mais ou menos dois minutos de blocos, e uma consulta além disso responde null em vez de dar erro - é por isso que esta página existe antes de você escrever um indexador, e não depois.
O que o nó conserva
| Dado | Conservado |
|---|---|
| EVM block history | ~2 minuteskeep_evm_blocks() = 120,000 / EVM_BLOCK_MS - 480 blocks at the default. Older blocks return null and their logs become unqueryable |
| Mini-block history | 20,000KEEP_MINI_BLOCKS, roughly 200 seconds at the 10 ms scheduling target |
| Receipts and bodies | 200,000MAX_RECEIPTS, evicted first-in-first-out |
| Full history | not on the nodeit lives in Postgres behind the explorer, fed by the sequencer's spool. This RPC is an index, not an archive |
A janela de blocos é derivada e não fixa: keep_evm_blocks() = 120_000 / EVM_BLOCK_MS, ou seja 480 blocos na cadência padrão. Os logs são despejados junto com o seu bloco. Os recibos e os corpos das transações têm o próprio teto primeiro-a-entrar-primeiro-a-sair e podem sumir antes do bloco deles.
As leituras são servidas a partir de um instantâneo publicado em cópia-sob-escrita e nunca tomam a trava de execução, e é por isso que um eth_call lento não consegue travar a produção de blocos e um bloco travado não consegue travar as leituras. É o desenho que torna a janela aceitável: o nó otimiza para servir o presente rápido, e entrega o histórico a algo construído para isso.
Como isso falha
Fora da janela você recebe null, não um erro
eth_getTransactionReceipt, eth_getTransactionByHash e toda busca de bloco respondem null para o que foi despejado. Nada distingue "nunca existiu" de "existiu e foi removido".
Três padrões que parecem corretos e não são:
- Sondar um recibo com um recuo longo. Espere o bastante entre as tentativas e o recibo pode ser despejado entre duas sondagens. Ele existe cerca de 10 ms depois do envio - sonde cedo e com frequência, não com paciência.
- Recuperar o histórico a partir do bloco 0.
earliesté o bloco conservado mais antigo, e ele avança enquanto você trabalha. Um laço de recuperação que corre atrás dele nunca alcança um ponto de partida fixo. - Reconciliar um registro toda noite. Quando um trabalho noturno rodar, todos os blocos que ele queria já sumiram.
O que fazer no lugar
O histórico completo existe - ele é transmitido do sequenciador para o Postgres atrás do explorador, que é construído para ser um arquivo. Então:
- Para o presente - os últimos segundos - use o nó. As inscrições e o
eth_getLogssobre um intervalo estreito são aquilo em que ele é rápido. - Para o passado, leia o explorador. Ele também tem os rastros de chamadas, que o nó não expõe de forma alguma, já que não há espaço de nomes
debug. - Para manter o seu próprio histórico, inscreva-se e persista à medida que os eventos chegam, em vez de pedi-los mais tarde. O fluxo de miniblocos é a fonte de maior fidelidade; um manipulador lento é expulso dele, então empurre para uma fila e processe em outro lugar.
// Right: capture as it happens, persist immediately.
socket.send(JSON.stringify({
jsonrpc: "2.0", id: 1, method: "eth_subscribe",
params: ["logs", { address: MY_CONTRACT }],
}));
// Wrong on this chain: a range that has already scrolled out of the window
// returns an empty array rather than an error, so this looks like "no events".
await client.getLogs({ address: MY_CONTRACT, fromBlock: 0n, toBlock: "latest" });E se você indexar um armazenamento de eventos por (blockNumber, logIndex), inclua o hash da transação: aqui o logIndex é enumerado por transação, então esse par não é único.
Os recibos através de um reinício
O estado sobrevive a um reinício; o índice dos recibos, não
O índice de recibos e logs é mantido em memória. Já se observou o recibo de uma transferência confirmada sumir depois de um reinício do sequenciador enquanto a mudança de saldo sobreviveu corretamente - portanto um recibo não é o registro durável de coisa alguma. Trate o explorador como o registro do que aconteceu, e o recibo do nó como um aviso de recebimento rápido e perecível.