On-Chain-Daten und SQL · Lektion 1 von 9
Blocks, headers and node APIs
11 Min. Lesezeit
Diese Lektion ist noch nicht auf Deutsch verfügbar und wird daher auf Englisch angezeigt.
Blocks are how a blockchain records time and order, so every timeline, daily total and "before or after" statement in a case depends on reading them correctly. The most recent part of any chain is provisional: blocks near the tip can be replaced. Behind every explorer, dataset and analytics platform is a node answering API calls. An investigator who knows what a header contains, how far its timestamp can be trusted, when a block is safe to rely on and which node call produced a figure can keep provisional data out of findings and check what a third-party tool shows.
What a header contains
A block header is a small record that summarizes the block and links it to its parent. A Bitcoin header is exactly 80 bytes with six fields:
| Field | Size | Meaning for the analyst |
|---|---|---|
| version | 4 bytes | Rule set and soft-fork signaling bits |
| previous block hash | 32 bytes | Link to the parent; the chain is built from these links |
| merkle root | 32 bytes | Commitment to every transaction in the block |
| time | 4 bytes | Unix timestamp chosen by the miner |
| bits | 4 bytes | Compact encoding of the difficulty target |
| nonce | 4 bytes | Value miners vary to find a valid hash |
The block hash is not a header field. It is the double SHA-256 of the 80 header bytes, and explorers display it in reversed byte order, which is why it begins with zeros. Bitcoin Core's getblock adds derived values such as height, mediantime, chainwork and confirmations.
An Ethereum header also commits to state and receipts. The fields analysts use most:
| Field | Meaning |
|---|---|
number, parentHash | Height and link to the parent |
timestamp | Unix time in seconds |
miner | Fee recipient chosen by the block proposer (the name predates proof of stake) |
stateRoot, transactionsRoot, receiptsRoot | Commitments to state, transactions and receipts |
logsBloom | Bloom filter that lets clients skip blocks with no matching logs |
gasLimit, gasUsed, baseFeePerGas | Capacity, usage and burned base fee per gas (London, August 2021) |
withdrawalsRoot | Validator withdrawals (Shanghai, April 2023) |
blobGasUsed, excessBlobGas, parentBeaconBlockRoot | Blob accounting and consensus link (Cancun, March 2024) |
requestsHash | Execution-to-consensus requests, EIP-7685 (Prague, May 2025) |
Fields appear only from the upgrade that introduced them, so a pipeline must accept their absence in older blocks. Since the Merge, difficulty and nonce are zero and mixHash carries the beacon chain's randomness value. Pre-Merge data also contains ommer (uncle) blocks: valid blocks that lost a race but were referenced by a later block through sha3Uncles and the uncles list. Their miners received a reduced reward without any transaction, so reward analysis for the mining era must include them.
Height versus hash
Height (Ethereum's number) is a position: the count of blocks since genesis. The block hash is an identity. Two blocks can share a height when the chain forks, and only one ends up in the main chain; a hash identifies exactly one block forever. Use height for ranges ("blocks 21,000,000 to 21,000,999") and the hash as the key in storage. In a report, cite both: "height 880,214, hash 0000…3f1a." Bitcoin's getblockhash returns the hash currently at a height, which can change near the tip.
Timestamps and their reliability
A block's timestamp is the time an analyst attaches to every transaction in it.
Bitcoin timestamps are set by the miner within two rules: the time must be greater than the median of the previous 11 blocks (the median time past), and nodes reject blocks more than two hours ahead of their own clock (older versions of Bitcoin Core used a "network-adjusted" time from peers). A block can therefore carry an earlier timestamp than its parent, and any single timestamp can be off by an hour or more. Use height for ordering; mediantime never decreases and serves as a monotonic clock. State Bitcoin times only at a precision the data supports.
Ethereum since the Merge (September 2022) has fixed 12-second slots: a block's timestamp equals the genesis time plus 12 seconds times its slot number. A gap of 24 or 36 seconds between consecutive blocks means one or two slots had no block. Before the Merge, miners set timestamps under looser rules; on rollups, the sequencer sets them under each rollup's own rules.
Two cautions apply everywhere. The block time is when a transaction was included, not when it was signed or broadcast. And "first seen" times shown by explorers come from their own mempool observers: useful clues, but local to one observer.
Reorganizations and finality
A reorganization (reorg) happens when nodes switch to a competing branch. The replaced blocks are stale or, in common usage, orphaned. On Bitcoin, nodes follow the branch with the most cumulative work (chainwork); a stale block's transactions usually reappear in the winning branch, possibly in a different block and position, or not at all if a conflicting transaction confirmed instead. getchaintips lists known branches, and getblock reports confirmations of −1 for a block off the main chain. On Ethereum, proof of stake makes reorgs rarer and usually one block deep; logs delivered by subscriptions or filters carry removed: true when a reorg drops them.
Finality is the point at which a block can be treated as permanent. Bitcoin finality is probabilistic: each confirmation makes replacement exponentially more expensive, six is a common convention for value transfers, and coinbase outputs cannot be spent for 100 blocks. Ethereum has explicit economic finality: slots form epochs of 32 slots (6.4 minutes), and checkpoints become justified and then finalized, normally after about two epochs (roughly 13 minutes). Reverting a finalized block would require at least one third of all staked ETH to be destroyed.
Ethereum JSON-RPC exposes this through block tags accepted in place of a number: earliest, latest, safe, finalized and pending. What safe returns depends on the consensus client (often the latest justified checkpoint, though some clients move it within seconds of the head), so check your node rather than assume.
| Use | Bitcoin | Ethereum |
|---|---|---|
| Real-time alerting | 0–1 confirmations, with reorg handling | latest, with reorg handling |
| Operational decisions | Policy depth, often 3–6 | safe or finalized |
| Reports and statistics | Well beyond 6, or a fixed old cutoff | finalized |
Handling orphaned data
A robust pipeline stores the hash and parent hash of every block, checks on each new block that its parent hash matches the stored hash one height below, and, when it does not, walks back to the common ancestor, ingests the new branch and moves the replaced rows to an audit table instead of deleting them. The queries below use the generic schema of Lesson 2.7, where blocks holds the canonical chain and transactions carries its block_hash:
-- Daily transaction counts, never beyond the finalized block
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, not height: drops stale-block rows
WHERE b.number <= :finalized_block -- from eth_getBlockByNumber("finalized", false)
GROUP BY DATE_TRUNC('day', b.block_timestamp)
ORDER BY day_utc;
-- Blocks whose parent is missing: gaps or unhandled reorgs
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);
The audit table matters in casework. Suppose an exchange credited a deposit after one confirmation, the block went stale and a conflicting transaction spending the same coins confirmed instead. An explorer's cached page may still show the first transaction; only stored stale-block data explains why a "confirmed" deposit never existed on the final chain.
Reading the chain through node APIs
Bitcoin Core exposes JSON-RPC (an HTTP POST with a method and a params array, authenticated by cookie file or configured user), also available through bitcoin-cli. Amounts are returned in BTC as JSON numbers. Ethereum execution clients (Geth, Nethermind, Besu, Erigon, Reth) implement a common JSON-RPC specification, and most EVM chains, rollups and sidechains offer the same interface. Quantities are hexadecimal strings ("0x1b4"); namespaces such as debug_ and trace_ are client-specific.
Bitcoin Core methods
| Method | Returns | Notes |
|---|---|---|
getblockchaininfo | Chain, height, best hash, pruning status | First call in any session |
getblockhash height / getblockheader hash | Hash at a height / header and confirmations | Hash can change near the tip |
getblock hash verbosity | 0: hex; 1: header and txids; 2: decoded transactions with fees; 3: adds prevout per input | Fees and prevouts need undo data |
getrawtransaction txid verbosity | 0: hex; 1: decoded; 2: adds fee and prevouts | Confirmed transactions need txindex=1 or a block hash |
gettxout txid n | Output details if currently unspent | Null if spent or unknown |
gettxspendingprevout | Transaction spending given outputs | Mempool only, unless txospenderindex is enabled (31.0 and later) |
getchaintips | Known branches and their status | Reorg investigation |
A typical sequence for examining a payment:
getblockhash 880214 -> "0000…3f1a"
getblock "0000…3f1a" 1 -> header fields and the list of txids
getrawtransaction "4f3a…c21e" 2 -> decoded transaction with prevout values and fee
gettxout "4f3a…c21e" 1 -> output 1 if still unspent, otherwise null
gettxout tells you whether an output is unspent now, not when or by what it was spent. Bitcoin Core has no method that lists an address's history; that needs an address indexer or a warehouse.
Ethereum methods
| Method | Returns |
|---|---|
eth_chainId | Chain ID (EIP-695): confirms which network you are on |
eth_blockNumber, eth_getBlockByNumber, eth_getBlockByHash | Latest height; header with transaction hashes, or full transactions when the second parameter is true |
eth_getTransactionByHash, eth_getTransactionReceipt | Signed transaction with from recovered; status, gas and logs |
eth_getBlockReceipts | All receipts of a block in one call |
eth_getLogs | Logs matching a filter |
eth_getBalance, eth_getCode, eth_getStorageAt, eth_call | State at a given block |
Two behaviors catch newcomers. A receipt of null means the transaction is pending or unknown to the node, not that it failed. And state methods answer at the block you pass: eth_getBalance at latest changes every few seconds, so pass an explicit block number for any figure you report.
eth_getLogs takes fromBlock and toBlock (or one blockHash), an optional address and a positional topics array. This request asks a token contract for Transfer events sent to one address over blocks 21,000,000 (0x1406f40) to 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"]
}]}
Topics match by position: the first is the Transfer signature, null accepts any sender, and topics[2] fixes the recipient. A position may also hold an array meaning "any of these"; moving the padded address to the second position returns transfers sent by it.
Debug and trace methods
Internal calls require re-execution. Geth-style clients offer debug_traceTransaction, debug_traceBlockByNumber and debug_traceCall with a tracer such as callTracer (call tree) or prestateTracer (state touched). Parity-style clients (Erigon, Nethermind, Reth) offer trace_transaction, trace_block, trace_filter and trace_replayTransaction, which return flat call lists. Both are expensive, often disabled or charged extra by providers, and differ in shape (for example, whether precompile calls appear), so normalize them before mixing results.
Which questions need which node
| Question | Bitcoin | Ethereum |
|---|---|---|
| Blocks, transactions, receipts, logs | Full node (txindex=1 for lookup by txid) | Full node; pre-Merge history may be expired |
| Current balance or UTXO status | gettxout, or an indexer for addresses | Full node, eth_getBalance |
| Balance at a past block | Indexer or warehouse | Archive node |
| Address history | Address indexer or warehouse | Indexer or warehouse (no native method) |
| Internal calls of old transactions | Not applicable | Archive node with tracing |
Pruned nodes cannot serve old blocks at all. An Ethereum full node asked for state older than its retained window returns an error rather than a wrong number: a signal that you need an archive node.
Providers, rate limits and trust
Hosted providers enforce rate limits (requests per second or weighted "compute units") and cap eth_getLogs by block range, result count or both. Robust extraction splits a range into chunks, halves a chunk the provider rejects, retries with exponential backoff and records completed ranges. JSON-RPC batch requests reduce overhead but count against the same limits. Providers also raise trust questions:
- Inconsistent heads. Behind a load balancer, consecutive calls can reach nodes at different heights. Pin work to a block hash, not
latest. - Errors and lag. For facts a finding depends on, compare the block hash at your anchor height across two independent sources or your own node, and record the client version (
web3_clientVersion, or thesubversionfield ofgetnetworkinfo). - Query privacy. A provider sees every address you ask about; its logs can reveal the subject of an investigation. Your own node does not.
For bulk history, RPC extraction is slow. Public datasets (Google BigQuery's crypto datasets, built with the open-source blockchain-etl tools; the AWS Public Blockchain Data set in Parquet) and ETL frameworks (Ethereum ETL, Bitcoin ETL, cryo, TrueBlocks, The Graph) are the alternatives; Lesson 2.7 compares them.
Exam focus: expect questions that ask you to choose the right data source or cutoff for a finding: the six Bitcoin header fields and that the block hash is computed; height as position versus hash as identity; median time past, the two-hour rule and out-of-order Bitcoin timestamps versus exact 12-second Ethereum slots; reorgs,removed: truelogs and stale-block audit data; confirmations, epochs and thelatest,safeandfinalizedtags;getblockandgetrawtransactionverbosity andtxindex; the limits ofgettxout; positional topic matching ineth_getLogs;debug_versustrace_methods; when an archive node is needed; verifying providers.