Leitura de dados brutos da blockchain · Aula 5 de 6
APIs de nós e acesso a dados
9 min de leitura
Todo explorador, conjunto de dados e plataforma de análise acaba lendo a blockchain por meio da API de um nó. Conhecer essas APIs permite buscar exatamente os dados dos quais uma conclusão depende, verificar o que uma ferramenta de terceiros mostra e entender por que uma consulta que funciona para um bloco recente falha para um antigo. Esta aula aborda os métodos mais usados por analistas, os tipos de nós necessários e os limites práticos dos provedores e conjuntos de dados públicos.
Duas famílias de APIs
Bitcoin Core expõe uma interface JSON-RPC: uma solicitação HTTP POST com um nome de method e um array params, autenticada com um arquivo de cookie ou um usuário configurado. Os mesmos métodos estão disponíveis na linha de comando por meio de bitcoin-cli. Os valores são retornados em BTC como números JSON.
Clientes de execução do Ethereum implementam uma especificação JSON-RPC comum, mantida pela comunidade Ethereum, portanto os métodos centrais eth_ funcionam da mesma forma no Geth, Nethermind, Besu, Erigon e Reth. A maioria das blockchains EVM, incluindo rollups e sidechains, oferece a mesma interface. Namespaces adicionais, como debug_ e trace_, são específicos de cada cliente. As quantidades são retornadas como strings hexadecimais ("0x1b4"), e os argumentos de bloco aceitam um número hexadecimal ou uma tag (latest, safe, finalized, earliest, pending), conforme explicado na aula Blocos e cabeçalhos como dados.
Métodos do Bitcoin Core usados por analistas
| Método | Retorna | Observações |
|---|---|---|
getblockchaininfo | Blockchain, altura, hash do melhor bloco, status de poda | Primeira chamada em qualquer sessão |
getblockhash height | Hash do bloco da cadeia principal naquela altura | Pode mudar perto da ponta |
getblockheader hash | Campos do cabeçalho e confirmations | Leve e rápido |
getblock hash verbosity | 0: hex; 1: cabeçalho e txids; 2: transações decodificadas com taxas; 3: adiciona prevout para cada entrada | Taxas e prevouts precisam de dados de desfazer |
getrawtransaction txid verbosity | 0: hex; 1: decodificada; 2: adiciona taxa e prevouts | Transações confirmadas precisam de txindex=1 ou de um hash de bloco |
decoderawtransaction hex | Estrutura decodificada de uma transação hexadecimal | Sem prevouts, portanto sem taxa |
gettxout txid n | Detalhes da saída se ela ainda não tiver sido gasta | Null se já tiver sido gasta ou for desconhecida |
gettxspendingprevout | Transação que gasta as saídas indicadas | Apenas mempool, a menos que txospenderindex esteja ativado (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 tiver sido gasta; caso contrário, null
A última chamada verifica apenas o conjunto atual de UTXOs: informa se uma saída ainda não foi gasta agora, não quando ou por quem ela foi gasta. Tradicionalmente, encontrar a transação que a gastou exigia um indexador ou um repositório de dados; desde a versão 31.0, o Bitcoin Core oferece um índice opcional de transações gastadoras (txospenderindex), que permite a gettxspendingprevout retornar a transação confirmada que gastou uma saída. O Bitcoin Core ainda não tem um método que liste o histórico de um endereço; essa consulta exige um indexador de endereços ou um repositório de dados.
Métodos JSON-RPC do Ethereum
| Método | Retorna |
|---|---|
eth_chainId | O ID da blockchain (EIP-695); confirma em qual rede você está |
eth_blockNumber | Altura do bloco mais recente |
eth_getBlockByNumber, eth_getBlockByHash | Cabeçalho e hashes das transações, ou transações completas quando o segundo parâmetro é true |
eth_getTransactionByHash | A transação assinada com from recuperado |
eth_getTransactionReceipt | Status, gas, logs |
eth_getBlockReceipts | Todos os recibos de um bloco em uma única chamada; amplamente implementado pelos clientes, mas ausente de documentações mais antigas |
eth_getLogs | Logs que correspondem a um filtro |
eth_getBalance, eth_getCode, eth_getStorageAt, eth_call | Estado em um determinado bloco |
Dois comportamentos costumam surpreender quem está começando. eth_getTransactionReceipt retorna null para uma transação pendente ou desconhecida pelo nó, o que não é o mesmo que uma falha. E os métodos de estado recebem um argumento de bloco: eth_getBalance em latest retorna um valor diferente a cada poucos segundos, portanto, passe um número de bloco explícito para qualquer valor que pretenda informar.
eth_getLogs é a ferramenta de trabalho para análise de tokens e protocolos. Seu filtro recebe fromBlock e toBlock (ou, em vez deles, um único blockHash), um address opcional e um array posicional topics. Esta solicitação consulta um contrato de token em busca de eventos Transfer enviados para um endereço ao longo de 1.000 blocos:
{"jsonrpc": "2.0", "id": 1, "method": "eth_getLogs",
"params": [{
"fromBlock": "0x1406f40",
"toBlock": "0x1407327",
"address": "0x5d3a…7c10",
"topics": ["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
null,
"0x000000000000000000000000c3d4…22e1"]
}]}
Os blocos vão de 21.000.000 (0x1406f40) a 21.000.999 (0x1407327). Os tópicos correspondem por posição: o primeiro é a assinatura de Transfer, null aceita qualquer remetente, e o terceiro, 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 para a segunda posição retornaria as transferências enviadas por ele.
Métodos de depuração e rastreamento
Chamadas internas exigem reexecução. Clientes no estilo Geth oferecem debug_traceTransaction, debug_traceBlockByNumber e debug_traceCall, com uma opção tracer, como callTracer (a árvore de chamadas) ou prestateTracer (o estado acessado por uma transação). Clientes no estilo Parity, como Erigon, Nethermind e Reth, também oferecem trace_transaction, trace_block, trace_filter e trace_replayTransaction, que retornam listas planas de chamadas.
Esses métodos são caros: um nó reexecuta cada opcode da transação e, para blocos antigos, primeiro precisa reconstruir o estado histórico. Provedores muitas vezes os desativam, limitam ou cobram mais por eles. Os dois estilos também diferem no formato e em detalhes como a inclusão ou não de chamadas a pré-compilados, portanto normalize os resultados antes de combinar dados de clientes diferentes.
Quais perguntas exigem quais nós
| Pergunta | Bitcoin | Ethereum |
|---|---|---|
| Blocos, transações, recibos, logs | Nó completo (txindex=1 para consultas por txid) | Nó completo; o histórico anterior à Merge pode ter sido removido |
| Saldo atual ou status de UTXO | gettxout, ou um indexador para endereços | Nó completo, eth_getBalance em latest |
| Saldo em um bloco passado | Indexador ou repositório de dados | Nó de arquivo |
| Histórico de endereços | Indexador de endereços ou repositório de dados | Indexador ou repositório de dados (sem método nativo) |
| Chamadas internas de transações antigas | Não aplicável | Nó de arquivo com rastreamento |
Nós podados de qualquer uma das blockchains não conseguem fornecer blocos antigos, e um nó completo do Ethereum consultado sobre um estado anterior à janela que reteve retorna um erro, não um número incorreto. Esse erro é um sinal útil de que você precisa de um nó de arquivo.
Limites de taxa, paginação e confiança nos provedores
Provedores hospedados protegem seus nós com limites de taxa, contabilizados em solicitações por segundo ou em “unidades de computação” ponderadas, e com limites para eth_getLogs: um intervalo máximo de blocos, um número máximo de resultados ou ambos. Um código robusto de extração divide um intervalo em blocos menores, reduz um bloco pela metade quando o provedor o rejeita, tenta novamente com espera exponencial e registra quais intervalos foram concluídos. Muitos provedores aceitam solicitações JSON-RPC em lote (um array de chamadas em uma solicitação HTTP), o que reduz a sobrecarga, mas é contabilizado nos mesmos limites.
Os provedores também levantam questões de confiança:
- Cabeçalhos inconsistentes. Por trás de um balanceador de carga, chamadas consecutivas podem chegar a nós em alturas diferentes, então um bloco retornado por uma chamada pode estar “não encontrado” na seguinte. Fixe o trabalho a um hash de bloco, em vez de usar
latest. - Erros e atraso. O nó de um provedor pode estar fora de sincronia, mal configurado ou usando uma versão diferente do cliente. Para fatos dos quais uma conclusão depende, compare o hash do bloco na altura de referência entre duas fontes independentes ou confira no seu próprio nó. Registre a versão do cliente com
web3_clientVersionno Ethereum ou o camposubversiondegetnetworkinfono Bitcoin Core. - Privacidade das consultas. Um provedor vê todos os endereços e transações sobre os quais você consulta. Em investigações sensíveis, os registros de um provedor revelam o objeto do seu interesse; seu próprio nó não.
Conjuntos de dados públicos e estruturas de ETL
Para históricos em grande escala, extrair tudo por RPC é lento. Há duas alternativas.
Conjuntos de dados públicos hospedados por grandes provedores de nuvem contêm dados de Bitcoin, Ethereum e outras blockchains já carregados em tabelas: por exemplo, os conjuntos de dados de cripto do programa de dados públicos do Google BigQuery, produzidos pelo projeto de código aberto blockchain-etl, e o AWS Public Blockchain Data set, publicado como arquivos Parquet. Eles oferecem acesso via SQL ao histórico completo em minutos. Em contrapartida, você aceita o esquema, as escolhas de decodificação, o atraso nas atualizações e a política de reorganização deles, aspectos que deve ler antes de confiar em uma tabela.
Estruturas de ETL permitem criar suas próprias tabelas a partir de um nó: Bitcoin ETL e Ethereum ETL (blockchain-etl), cryo (que extrai blocos, transações, logs e rastreamentos para Parquet ou CSV), TrueBlocks (que indexa cada ocorrência de um endereço) e The Graph (que indexa eventos de protocolos específicos por meio de subgráficos). Executar seu próprio pipeline exige esforço, mas dá a você controle sobre o nó, a decodificação e a proveniência de cada linha. A aula A pilha de dados de análise compara essas opções.
Foco no exame: os níveis de verbosidade degetblockegetrawtransactiondo Bitcoin Core e o requisito detxindex; quegettxoutverifica apenas o conjunto atual de UTXOs e que o Bitcoin Core não tem método de histórico de endereços; os métodos centrais do Ethereum, incluindoeth_getBlockByNumber,eth_getTransactionReceipt,eth_getBlockReceiptseeth_chainId; o filtroeth_getLogse a correspondência posicional de tópicos com curingasnull; os métodosdebug_trace*no estilo Geth em contraste com os métodostrace_*no estilo Parity; quais perguntas exigem um nó de arquivo e como lidar com limites de taxa e limites de intervalo; a verificação de provedores e o registro das versões dos clientes; conjuntos de dados públicos e estruturas de ETL e suas compensações.
Questões de prática
Verifique o que você aprendeu. Estas questões não contam para o exame.
Entre para salvar seu progresso e continuar de onde parou. É grátis. Entrar