Dados on-chain e SQL · Aula 1 de 9
Blocos, cabeçalhos e APIs de nós
13 min de leitura
Os blocos são a forma como uma blockchain registra o tempo e a ordem, de modo que toda linha do tempo, total diário e afirmação sobre "antes ou depois" em um caso depende de sua leitura correta. A parte mais recente de qualquer cadeia é provisória: os blocos próximos à ponta podem ser substituídos. Por trás de todo explorador, conjunto de dados e plataforma de análise, há um nó respondendo a chamadas de API. Um investigador que sabe o que um cabeçalho contém, até que ponto seu timestamp é confiável, quando é seguro se basear em um bloco e qual chamada ao nó produziu um valor consegue manter dados provisórios fora das conclusões e verificar o que uma ferramenta de terceiros mostra.
O que um cabeçalho contém
Um cabeçalho de bloco é um pequeno registro que resume o bloco e o vincula ao seu bloco pai. Um cabeçalho do Bitcoin tem exatamente 80 bytes, com seis campos:
| Campo | Tamanho | Significado para o analista |
|---|---|---|
| versão | 4 bytes | Conjunto de regras e bits de sinalização de soft fork |
| hash do bloco anterior | 32 bytes | Vínculo com o bloco pai; a cadeia é construída a partir desses vínculos |
| raiz de Merkle | 32 bytes | Compromisso criptográfico com todas as transações do bloco |
| tempo | 4 bytes | Timestamp Unix escolhido pelo minerador |
| bits | 4 bytes | Codificação compacta do alvo de dificuldade |
| nonce | 4 bytes | Valor que os mineradores variam para encontrar um hash válido |
O hash do bloco não é um campo do cabeçalho. Ele é o SHA-256 duplo dos 80 bytes do cabeçalho, e os exploradores o exibem com a ordem dos bytes invertida, motivo pelo qual começa com zeros. O getblock do Bitcoin Core acrescenta valores derivados, como height, mediantime, chainwork e confirmations.
Um cabeçalho do Ethereum também inclui compromissos criptográficos com o estado e os recibos. Os campos mais usados pelos analistas:
| Campo | Significado |
|---|---|
number, parentHash | Altura e vínculo com o bloco pai |
timestamp | Tempo Unix em segundos |
miner | Destinatário das taxas escolhido pelo proponente do bloco (o nome é anterior à prova de participação) |
stateRoot, transactionsRoot, receiptsRoot | Compromissos criptográficos com o estado, as transações e os recibos |
logsBloom | Filtro de Bloom que permite aos clientes ignorar blocos sem logs correspondentes |
gasLimit, gasUsed, baseFeePerGas | Capacidade, uso e taxa-base queimada por gas (London, agosto de 2021) |
withdrawalsRoot | Saques de validadores (Shanghai, abril de 2023) |
blobGasUsed, excessBlobGas, parentBeaconBlockRoot | Contabilização de blobs e vínculo com o consenso (Cancun, março de 2024) |
requestsHash | Solicitações da camada de execução para a de consenso, EIP-7685 (Prague, maio de 2025) |
Os campos aparecem somente a partir da atualização que os introduziu, portanto um pipeline deve aceitar sua ausência em blocos mais antigos. Desde o Merge, difficulty e nonce são zero, e mixHash contém o valor de aleatoriedade da beacon chain. Os dados anteriores ao Merge também contêm blocos ommer (tios): blocos válidos que perderam uma disputa, mas foram referenciados por um bloco posterior por meio de sha3Uncles e da lista uncles. Seus mineradores receberam uma recompensa reduzida sem nenhuma transação, portanto a análise de recompensas da era da mineração deve incluí-los.
Altura versus hash
A altura (number no Ethereum) é uma posição: a contagem de blocos desde o bloco gênese. O hash do bloco é uma identidade. Dois blocos podem ter a mesma altura quando a cadeia se bifurca, e apenas um acaba na cadeia principal; um hash identifica exatamente um bloco para sempre. Use a altura para intervalos ("blocos 21.000.000 a 21.000.999") e o hash como chave no armazenamento. Em um relatório, cite ambos: "altura 880.214, hash 0000…3f1a". O getblockhash do Bitcoin retorna o hash que está atualmente em uma altura, o que pode mudar próximo à ponta.
Timestamps e sua confiabilidade
O timestamp de um bloco é o horário que um analista associa a todas as transações nele contidas.
Os timestamps do Bitcoin são definidos pelo minerador dentro de duas regras: o horário deve ser maior que a mediana dos 11 blocos anteriores (o tempo mediano passado), e os nós rejeitam blocos mais de duas horas à frente de seu próprio relógio (versões mais antigas do Bitcoin Core usavam um horário "ajustado pela rede", obtido dos pares). Portanto, um bloco pode ter um timestamp anterior ao de seu bloco pai, e qualquer timestamp individual pode apresentar um desvio de uma hora ou mais. Use a altura para ordenar; mediantime nunca diminui e funciona como um relógio monotônico. Informe os horários do Bitcoin apenas com a precisão que os dados permitem.
O Ethereum, desde o Merge (setembro de 2022), tem slots fixos de 12 segundos: o timestamp de um bloco é igual ao horário do bloco gênese mais 12 segundos multiplicados pelo número de seu slot. Um intervalo de 24 ou 36 segundos entre blocos consecutivos significa que um ou dois slots ficaram sem bloco. Antes do Merge, os mineradores definiam timestamps segundo regras menos rígidas; nos rollups, o sequenciador os define conforme as regras de cada rollup.
Duas ressalvas se aplicam em todos os casos. O horário do bloco indica quando uma transação foi incluída, não quando foi assinada ou transmitida. E os horários de "primeira observação" exibidos pelos exploradores vêm de seus próprios observadores do mempool: são indícios úteis, mas locais a um único observador.
Reorganizações e finalização
Uma reorganização (reorg) ocorre quando os nós mudam para uma ramificação concorrente. Os blocos substituídos são obsoletos ou, no uso comum, órfãos. No Bitcoin, os nós seguem a ramificação com o maior trabalho acumulado (chainwork); as transações de um bloco obsoleto geralmente reaparecem na ramificação vencedora, possivelmente em outro bloco e posição, ou não reaparecem se uma transação conflitante tiver sido confirmada em seu lugar. getchaintips lista as ramificações conhecidas, e getblock informa confirmations de −1 para um bloco fora da cadeia principal. No Ethereum, a prova de participação torna as reorganizações mais raras e geralmente limitadas a um bloco de profundidade; os logs entregues por assinaturas ou filtros contêm removed: true quando uma reorganização os remove.
A finalização é o ponto em que um bloco pode ser tratado como permanente. A finalização do Bitcoin é probabilística: cada confirmação torna a substituição exponencialmente mais cara, seis é uma convenção comum para transferências de valor, e as saídas coinbase não podem ser gastas por 100 blocos. O Ethereum tem finalização econômica explícita: os slots formam épocas de 32 slots (6,4 minutos), e os pontos de controle tornam-se justificados e depois finalizados, normalmente após cerca de duas épocas (aproximadamente 13 minutos). Reverter um bloco finalizado exigiria que pelo menos um terço de todo o ETH em staking fosse destruído.
O JSON-RPC do Ethereum expõe isso por meio de tags de bloco aceitas no lugar de um número: earliest, latest, safe, finalized e pending. O que safe retorna depende do cliente de consenso (frequentemente o ponto de controle justificado mais recente, embora alguns clientes o avancem poucos segundos após a ponta), portanto verifique seu nó em vez de presumir.
| Uso | Bitcoin | Ethereum |
|---|---|---|
| Alertas em tempo real | 0–1 confirmações, com tratamento de reorganizações | latest, com tratamento de reorganizações |
| Decisões operacionais | Profundidade definida por política, frequentemente 3–6 | safe ou finalized |
| Relatórios e estatísticas | Muito além de 6, ou um corte antigo fixo | finalized |
Tratamento de dados órfãos
Um pipeline robusto armazena o hash e o hash do bloco pai de cada bloco, verifica a cada novo bloco se o hash de seu pai corresponde ao hash armazenado uma altura abaixo e, quando não corresponde, retrocede até o ancestral comum, ingere a nova ramificação e move as linhas substituídas para uma tabela de auditoria em vez de excluí-las. As consultas abaixo usam o esquema genérico da Aula 2.7, em que blocks contém a cadeia canônica e transactions contém seu block_hash:
-- Contagens diárias de transações, nunca além do bloco finalizado
SELECT DATE_TRUNC('day', b.block_timestamp) AS day_utc,
COUNT(*) AS tx_count
FROM transactions t
JOIN blocks b ON b.hash = t.block_hash -- hash, não altura: exclui linhas de blocos obsoletos
WHERE b.number <= :finalized_block -- de eth_getBlockByNumber("finalized", false)
GROUP BY DATE_TRUNC('day', b.block_timestamp)
ORDER BY day_utc;
-- Blocos cujo pai está ausente: lacunas ou reorganizações não tratadas
SELECT c.number, c.hash, c.parent_hash
FROM blocks c
LEFT JOIN blocks p ON p.hash = c.parent_hash
WHERE p.hash IS NULL
AND c.number > (SELECT MIN(number) FROM blocks);
A tabela de auditoria é importante no trabalho pericial. Suponha que uma exchange tenha creditado um depósito após uma confirmação, o bloco tenha se tornado obsoleto e uma transação conflitante que gastava as mesmas moedas tenha sido confirmada em seu lugar. A página em cache de um explorador ainda pode mostrar a primeira transação; somente os dados armazenados do bloco obsoleto explicam por que um depósito "confirmado" nunca existiu na cadeia final.
Leitura da cadeia por meio de APIs de nós
O Bitcoin Core expõe JSON-RPC (um HTTP POST com um method e um array params, autenticado por arquivo de cookie ou usuário configurado), também disponível por meio de bitcoin-cli. Os valores são retornados em BTC como números JSON. Os clientes de execução do Ethereum (Geth, Nethermind, Besu, Erigon, Reth) implementam uma especificação JSON-RPC comum, e a maioria das cadeias EVM, rollups e sidechains oferece a mesma interface. As quantidades são strings hexadecimais ("0x1b4"); namespaces como debug_ e trace_ são específicos de cada cliente.
Métodos do Bitcoin Core
| Método | Retorna | Observações |
|---|---|---|
getblockchaininfo | Cadeia, altura, melhor hash, status de poda | Primeira chamada em qualquer sessão |
getblockhash height / getblockheader hash | Hash em uma altura / cabeçalho e confirmations | O hash pode mudar próximo à ponta |
getblock hash verbosity | 0: hexadecimal; 1: cabeçalho e txids; 2: transações decodificadas com taxas; 3: acrescenta prevout por entrada | Taxas e prevouts precisam de dados de desfazimento |
getrawtransaction txid verbosity | 0: hexadecimal; 1: decodificada; 2: acrescenta taxa e prevouts | Transações confirmadas precisam de txindex=1 ou de um hash de bloco |
gettxout txid n | Detalhes da saída se ela não estiver gasta atualmente | Null se estiver gasta ou for desconhecida |
gettxspendingprevout | Transação que gasta as saídas fornecidas | Apenas o mempool, a menos que txospenderindex esteja habilitado (31.0 e posteriores) |
getchaintips | Ramificações conhecidas e seus status | Investigação de reorganizações |
Uma sequência típica para examinar um pagamento:
getblockhash 880214 -> "0000…3f1a"
getblock "0000…3f1a" 1 -> campos do cabeçalho e a lista de txids
getrawtransaction "4f3a…c21e" 2 -> transação decodificada com valores de prevout e taxa
gettxout "4f3a…c21e" 1 -> saída 1 se ainda não gasta, caso contrário null
gettxout informa se uma saída está não gasta agora, não quando ou por qual transação ela foi gasta. O Bitcoin Core não tem um método que liste o histórico de um endereço; isso exige um indexador de endereços ou um data warehouse.
Métodos do Ethereum
| Método | Retorna |
|---|---|
eth_chainId | ID da cadeia (EIP-695): confirma em qual rede você está |
eth_blockNumber, eth_getBlockByNumber, eth_getBlockByHash | Altura mais recente; cabeçalho com hashes de transações, ou transações completas quando o segundo parâmetro é true |
eth_getTransactionByHash, eth_getTransactionReceipt | Transação assinada com from recuperado; status, gas e logs |
eth_getBlockReceipts | Todos os recibos de um bloco em uma única chamada |
eth_getLogs | Logs que correspondem a um filtro |
eth_getBalance, eth_getCode, eth_getStorageAt, eth_call | Estado em um determinado bloco |
Dois comportamentos surpreendem os iniciantes. Um recibo null significa que a transação está pendente ou é desconhecida para o nó, não que falhou. E os métodos de estado respondem com base no bloco que você informa: eth_getBalance em latest muda a cada poucos segundos, portanto informe um número de bloco explícito para qualquer valor que você relatar.
eth_getLogs recebe fromBlock e toBlock (ou um único blockHash), um address opcional e um array posicional topics. Esta solicitação consulta um contrato de token para obter eventos Transfer enviados a um endereço nos blocos 21.000.000 (0x1406f40) a 21.000.999 (0x1407327):
{"jsonrpc": "2.0", "id": 1, "method": "eth_getLogs",
"params": [{
"fromBlock": "0x1406f40", "toBlock": "0x1407327",
"address": "0x5d3a…7c10",
"topics": ["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
null,
"0x000000000000000000000000c3d4…22e1"]
}]}
Os tópicos correspondem por posição: o primeiro é a assinatura de Transfer, null aceita qualquer remetente, e topics[2] fixa o destinatário. Uma posição também pode conter um array que significa "qualquer um destes"; mover o endereço preenchido com zeros para a segunda posição retorna as transferências enviadas por ele.
Métodos de depuração e rastreamento
As chamadas internas exigem reexecução. Clientes no estilo Geth oferecem debug_traceTransaction, debug_traceBlockByNumber e debug_traceCall com um tracer como callTracer (árvore de chamadas) ou prestateTracer (estado acessado). Clientes no estilo Parity (Erigon, Nethermind, Reth) oferecem trace_transaction, trace_block, trace_filter e trace_replayTransaction, que retornam listas planas de chamadas. Ambos têm alto custo computacional, frequentemente são desabilitados ou cobrados à parte pelos provedores e diferem no formato (por exemplo, se chamadas a pré-compilados aparecem), portanto normalize-os antes de combinar resultados.
Quais perguntas exigem qual nó
| Pergunta | Bitcoin | Ethereum |
|---|---|---|
| Blocos, transações, recibos, logs | Nó completo (txindex=1 para consulta por txid) | Nó completo; o histórico anterior ao Merge pode ter expirado |
| Saldo atual ou status de UTXO | gettxout, ou um indexador para endereços | Nó completo, eth_getBalance |
| Saldo em um bloco passado | Indexador ou data warehouse | Nó de arquivo |
| Histórico de endereço | Indexador de endereços ou data warehouse | Indexador ou data warehouse (sem método nativo) |
| Chamadas internas de transações antigas | Não se aplica | Nó de arquivo com rastreamento |
Nós podados não conseguem fornecer blocos antigos. Um nó completo do Ethereum consultado sobre um estado anterior à sua janela de retenção retorna um erro em vez de um número incorreto: um sinal de que você precisa de um nó de arquivo.
Provedores, limites de requisições e confiança
Provedores hospedados impõem limites de requisições (requisições por segundo ou "unidades de computação" ponderadas) e limitam eth_getLogs por intervalo de blocos, quantidade de resultados ou ambos. Uma extração robusta divide um intervalo em partes, reduz pela metade uma parte rejeitada pelo provedor, tenta novamente com espera exponencial e registra os intervalos concluídos. Requisições JSON-RPC em lote reduzem a sobrecarga, mas são contabilizadas nos mesmos limites. Os provedores também levantam questões de confiança:
- Pontas inconsistentes. Por trás de um balanceador de carga, chamadas consecutivas podem chegar a nós em alturas diferentes. Fixe o trabalho em um hash de bloco, não em
latest. - Erros e atraso. Para fatos dos quais uma conclusão depende, compare o hash do bloco na altura de referência entre duas fontes independentes ou com seu próprio nó, e registre a versão do cliente (
web3_clientVersion, ou o camposubversiondegetnetworkinfo). - Privacidade das consultas. Um provedor vê todos os endereços que você consulta; seus logs podem revelar o alvo de uma investigação. Seu próprio nó não faz isso.
Para grandes volumes de histórico, a extração via RPC é lenta. Conjuntos de dados públicos (os conjuntos de dados de criptomoedas do Google BigQuery, construídos com as ferramentas de código aberto blockchain-etl; o conjunto AWS Public Blockchain Data em Parquet) e frameworks de ETL (Ethereum ETL, Bitcoin ETL, cryo, TrueBlocks, The Graph) são as alternativas; a Aula 2.7 os compara.
Foco no exame: espere questões que peçam para escolher a fonte de dados ou o corte correto para uma conclusão: os seis campos do cabeçalho do Bitcoin e o fato de que o hash do bloco é calculado; altura como posição versus hash como identidade; tempo mediano passado, a regra das duas horas e timestamps fora de ordem do Bitcoin versus slots exatos de 12 segundos do Ethereum; reorganizações, logs comremoved: truee dados de auditoria de blocos obsoletos; confirmações, épocas e as tagslatest,safeefinalized; níveis de detalhamento degetblockegetrawtransactionetxindex; as limitações degettxout; correspondência posicional de tópicos emeth_getLogs; métodosdebug_versustrace_; quando um nó de arquivo é necessário; verificação de provedores.