On-Chain-Daten und SQL · Lektion 1 von 9
Blöcke, Header und Node-APIs
12 Min. Lesezeit
Blöcke sind das Mittel, mit dem eine Blockchain Zeit und Reihenfolge festhält. Daher hängt jede Zeitleiste, jede Tagessumme und jede Aussage über ein „Davor oder Danach“ in einem Fall davon ab, sie richtig zu lesen. Der jüngste Teil jeder Blockchain ist vorläufig: Blöcke nahe der Spitze können ersetzt werden. Hinter jedem Explorer, jedem Datensatz und jeder Analyseplattform steht ein Node, der API-Aufrufe beantwortet. Ein Ermittler, der weiß, was ein Header enthält, wie weit dessen Zeitstempel vertraut werden kann, wann ein Block verlässlich verwendet werden kann und welcher Node-Aufruf eine Kennzahl geliefert hat, kann vorläufige Daten aus Befunden heraushalten und die Anzeigen eines Drittanbieter-Tools überprüfen.
Was ein Header enthält
Ein Block-Header ist ein kleiner Datensatz, der den Block zusammenfasst und ihn mit seinem Vorgänger verknüpft. Ein Bitcoin-Header umfasst genau 80 Bytes mit sechs Feldern:
| Feld | Größe | Bedeutung für den Analysten |
|---|---|---|
| version | 4 Bytes | Regelwerk und Signalisierungsbits für Soft Forks |
| previous block hash | 32 Bytes | Verknüpfung zum Vorgänger; aus diesen Verknüpfungen entsteht die Blockchain |
| merkle root | 32 Bytes | Kryptografische Bindung an jede Transaktion im Block |
| time | 4 Bytes | Vom Miner gewählter Unix-Zeitstempel |
| bits | 4 Bytes | Kompakte Kodierung des Schwierigkeitszielwerts |
| nonce | 4 Bytes | Wert, den Miner verändern, um einen gültigen Hash zu finden |
Der Block-Hash ist kein Header-Feld. Er ist der doppelte SHA-256-Hash der 80 Header-Bytes, und Explorer zeigen ihn in umgekehrter Byte-Reihenfolge an, weshalb er mit Nullen beginnt. Bitcoin Cores getblock ergänzt abgeleitete Werte wie height, mediantime, chainwork und confirmations.
Ein Ethereum-Header bindet auch Zustand und Transaktionsbelege kryptografisch ein. Die von Analysten am häufigsten verwendeten Felder:
| Feld | Bedeutung |
|---|---|
number, parentHash | Höhe und Verknüpfung zum Vorgänger |
timestamp | Unix-Zeit in Sekunden |
miner | Vom Block-Proposer gewählter Gebührenempfänger (der Name stammt aus der Zeit vor Proof of Stake) |
stateRoot, transactionsRoot, receiptsRoot | Kryptografische Bindungen an Zustand, Transaktionen und Transaktionsbelege |
logsBloom | Bloom-Filter, mit dem Clients Blöcke ohne passende Logs überspringen können |
gasLimit, gasUsed, baseFeePerGas | Kapazität, Verbrauch und verbrannte Basisgebühr pro Gas (London, August 2021) |
withdrawalsRoot | Auszahlungen an Validatoren (Shanghai, April 2023) |
blobGasUsed, excessBlobGas, parentBeaconBlockRoot | Blob-Abrechnung und Konsensverknüpfung (Cancun, März 2024) |
requestsHash | Anfragen von der Ausführungsschicht an die Konsensschicht, EIP-7685 (Prague, Mai 2025) |
Felder sind erst ab dem Upgrade vorhanden, mit dem sie eingeführt wurden. Daher muss eine Pipeline ihr Fehlen in älteren Blöcken akzeptieren. Seit dem Merge sind difficulty und nonce null, und mixHash enthält den Zufallswert der Beacon Chain. Daten aus der Zeit vor dem Merge enthalten außerdem Ommer-Blöcke (Uncle-Blöcke): gültige Blöcke, die ein Rennen verloren haben, aber von einem späteren Block über sha3Uncles und die Liste uncles referenziert wurden. Ihre Miner erhielten ohne jede Transaktion eine reduzierte Belohnung. Daher muss die Analyse von Belohnungen aus der Mining-Ära diese Blöcke einbeziehen.
Höhe gegenüber Hash
Die Höhe (number bei Ethereum) ist eine Position: die Anzahl der Blöcke seit dem Genesis-Block. Der Block-Hash ist eine Identität. Zwei Blöcke können bei einer Verzweigung der Blockchain dieselbe Höhe haben, und nur einer gelangt letztlich in die Hauptkette; ein Hash identifiziert für immer genau einen Block. Verwenden Sie die Höhe für Bereiche („Blöcke 21.000.000 bis 21.000.999“) und den Hash als Schlüssel bei der Speicherung. Geben Sie in einem Bericht beides an: „Höhe 880.214, Hash 0000…3f1a.“ Bitcoins getblockhash liefert den Hash, der aktuell einer Höhe zugeordnet ist; nahe der Spitze kann sich dieser ändern.
Zeitstempel und ihre Zuverlässigkeit
Der Zeitstempel eines Blocks ist die Zeit, die ein Analyst jeder darin enthaltenen Transaktion zuordnet.
Bitcoin-Zeitstempel werden vom Miner unter Einhaltung zweier Regeln festgelegt: Die Zeit muss größer sein als der Median der vorherigen 11 Blöcke (die Median Time Past), und Nodes lehnen Blöcke ab, die ihrer eigenen Uhr um mehr als zwei Stunden voraus sind (ältere Versionen von Bitcoin Core verwendeten eine von Peers abgeleitete „netzwerkangepasste“ Zeit). Ein Block kann daher einen früheren Zeitstempel als sein Vorgänger tragen, und jeder einzelne Zeitstempel kann um eine Stunde oder mehr abweichen. Verwenden Sie die Höhe für die Reihenfolge; mediantime nimmt niemals ab und dient als monotone Uhr. Geben Sie Bitcoin-Zeiten nur mit einer Genauigkeit an, die von den Daten gestützt wird.
Ethereum hat seit dem Merge (September 2022) feste Slots von 12 Sekunden: Der Zeitstempel eines Blocks entspricht der Genesis-Zeit plus 12 Sekunden multipliziert mit seiner Slot-Nummer. Ein Abstand von 24 oder 36 Sekunden zwischen aufeinanderfolgenden Blöcken bedeutet, dass in einem oder zwei Slots kein Block erzeugt wurde. Vor dem Merge legten Miner Zeitstempel nach weniger strengen Regeln fest; bei Rollups legt der Sequencer sie nach den jeweiligen Regeln des Rollups fest.
Zwei Vorbehalte gelten überall. Die Blockzeit gibt an, wann eine Transaktion aufgenommen wurde, nicht wann sie signiert oder verbreitet wurde. Außerdem stammen die von Explorern angezeigten Zeiten für „erstmals gesehen“ von deren eigenen Mempool-Beobachtern: nützliche Anhaltspunkte, die jedoch nur für einen einzelnen Beobachter gelten.
Reorganisationen und Finalität
Eine Reorganisation (Reorg) tritt auf, wenn Nodes zu einem konkurrierenden Zweig wechseln. Die ersetzten Blöcke sind veraltet oder werden im allgemeinen Sprachgebrauch als verwaist bezeichnet. Bei Bitcoin folgen Nodes dem Zweig mit der höchsten kumulierten Arbeit (chainwork); die Transaktionen eines veralteten Blocks tauchen gewöhnlich im siegreichen Zweig wieder auf, möglicherweise in einem anderen Block und an einer anderen Position, oder gar nicht, wenn stattdessen eine konkurrierende Transaktion bestätigt wurde. getchaintips listet bekannte Zweige auf, und getblock meldet für einen Block außerhalb der Hauptkette den Wert −1 für confirmations. Bei Ethereum macht Proof of Stake Reorgs seltener und beschränkt ihre Tiefe gewöhnlich auf einen Block; über Abonnements oder Filter gelieferte Logs tragen removed: true, wenn sie durch eine Reorg entfernt werden.
Finalität ist der Punkt, ab dem ein Block als dauerhaft betrachtet werden kann. Die Finalität bei Bitcoin ist probabilistisch: Jede Bestätigung macht einen Austausch exponentiell teurer; sechs Bestätigungen sind eine gängige Konvention für Wertübertragungen, und Coinbase-Outputs können für 100 Blöcke nicht ausgegeben werden. Ethereum besitzt explizite ökonomische Finalität: Slots bilden Epochen aus 32 Slots (6,4 Minuten), und Checkpoints werden zunächst gerechtfertigt und dann finalisiert, normalerweise nach etwa zwei Epochen (ungefähr 13 Minuten). Die Rücknahme eines finalisierten Blocks würde erfordern, dass mindestens ein Drittel aller als Stake hinterlegten ETH vernichtet wird.
Ethereum JSON-RPC stellt dies über Block-Tags bereit, die anstelle einer Zahl akzeptiert werden: earliest, latest, safe, finalized und pending. Was safe zurückgibt, hängt vom Konsens-Client ab (häufig der jüngste gerechtfertigte Checkpoint, obwohl manche Clients ihn innerhalb von Sekunden an die Spitze nachführen). Prüfen Sie daher Ihren Node, statt Annahmen zu treffen.
| Verwendung | Bitcoin | Ethereum |
|---|---|---|
| Echtzeit-Alarmierung | 0–1 Bestätigungen, mit Reorg-Behandlung | latest, mit Reorg-Behandlung |
| Operative Entscheidungen | Richtliniengemäße Tiefe, oft 3–6 | safe oder finalized |
| Berichte und Statistiken | Deutlich mehr als 6 oder eine feste, weit zurückliegende Grenze | finalized |
Umgang mit verwaisten Daten
Eine robuste Pipeline speichert den Hash und den Vorgänger-Hash jedes Blocks, prüft bei jedem neuen Block, ob dessen Vorgänger-Hash mit dem gespeicherten Hash eine Höhe darunter übereinstimmt, und geht andernfalls bis zum gemeinsamen Vorfahren zurück, übernimmt den neuen Zweig und verschiebt die ersetzten Zeilen in eine Audit-Tabelle, anstatt sie zu löschen. Die folgenden Abfragen verwenden das generische Schema aus Lektion 2.7, in dem blocks die kanonische Kette enthält und transactions den zugehörigen block_hash führt:
-- Tägliche Transaktionszahlen, nie über den finalisierten Block hinaus
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, nicht Höhe: schließt Zeilen veralteter Blöcke aus
WHERE b.number <= :finalized_block -- aus eth_getBlockByNumber("finalized", false)
GROUP BY DATE_TRUNC('day', b.block_timestamp)
ORDER BY day_utc;
-- Blöcke mit fehlendem Vorgänger: Lücken oder unbehandelte 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);
Die Audit-Tabelle ist bei der Fallbearbeitung wichtig. Angenommen, eine Börse hat eine Einzahlung nach einer Bestätigung gutgeschrieben, der Block wurde veraltet, und stattdessen wurde eine konkurrierende Transaktion bestätigt, die dieselben Coins ausgibt. Eine zwischengespeicherte Explorer-Seite zeigt möglicherweise weiterhin die erste Transaktion; nur gespeicherte Daten veralteter Blöcke erklären, warum eine „bestätigte“ Einzahlung in der endgültigen Kette nie existiert hat.
Die Blockchain über Node-APIs lesen
Bitcoin Core stellt JSON-RPC bereit (einen HTTP-POST mit method und einem params-Array, authentifiziert über eine Cookie-Datei oder einen konfigurierten Benutzer), das auch über bitcoin-cli verfügbar ist. Beträge werden in BTC als JSON-Zahlen zurückgegeben. Ethereum-Ausführungsclients (Geth, Nethermind, Besu, Erigon, Reth) implementieren eine gemeinsame JSON-RPC-Spezifikation, und die meisten EVM-Chains, Rollups und Sidechains bieten dieselbe Schnittstelle an. Mengenangaben sind hexadezimale Zeichenfolgen ("0x1b4"); Namensräume wie debug_ und trace_ sind clientspezifisch.
Bitcoin-Core-Methoden
| Methode | Rückgabe | Hinweise |
|---|---|---|
getblockchaininfo | Blockchain, Höhe, bester Hash, Pruning-Status | Erster Aufruf in jeder Sitzung |
getblockhash height / getblockheader hash | Hash an einer Höhe / Header und confirmations | Hash kann sich nahe der Spitze ändern |
getblock hash verbosity | 0: Hex; 1: Header und txids; 2: dekodierte Transaktionen mit Gebühren; 3: ergänzt prevout pro Input | Gebühren und Prevouts benötigen Undo-Daten |
getrawtransaction txid verbosity | 0: Hex; 1: dekodiert; 2: ergänzt Gebühr und Prevouts | Bestätigte Transaktionen benötigen txindex=1 oder einen Block-Hash |
gettxout txid n | Output-Details, sofern aktuell nicht ausgegeben | Null, wenn ausgegeben oder unbekannt |
gettxspendingprevout | Transaktion, die angegebene Outputs ausgibt | Nur Mempool, sofern txospenderindex nicht aktiviert ist (31.0 und neuer) |
getchaintips | Bekannte Zweige und deren Status | Untersuchung von Reorgs |
Eine typische Abfolge zur Untersuchung einer Zahlung:
getblockhash 880214 -> "0000…3f1a"
getblock "0000…3f1a" 1 -> Header-Felder und die Liste der txids
getrawtransaction "4f3a…c21e" 2 -> dekodierte Transaktion mit Prevout-Werten und Gebühr
gettxout "4f3a…c21e" 1 -> Output 1, falls noch nicht ausgegeben, andernfalls null
gettxout zeigt Ihnen, ob ein Output jetzt nicht ausgegeben ist, nicht wann oder wodurch er ausgegeben wurde. Bitcoin Core besitzt keine Methode, die den Verlauf einer Adresse auflistet; dafür ist ein Adressindexer oder ein Data Warehouse erforderlich.
Ethereum-Methoden
| Methode | Rückgabe |
|---|---|
eth_chainId | Chain-ID (EIP-695): bestätigt, in welchem Netzwerk Sie sich befinden |
eth_blockNumber, eth_getBlockByNumber, eth_getBlockByHash | Jüngste Höhe; Header mit Transaktions-Hashes oder vollständige Transaktionen, wenn der zweite Parameter true ist |
eth_getTransactionByHash, eth_getTransactionReceipt | Signierte Transaktion mit rekonstruiertem from; Status, Gas und Logs |
eth_getBlockReceipts | Alle Transaktionsbelege eines Blocks in einem Aufruf |
eth_getLogs | Logs, die einem Filter entsprechen |
eth_getBalance, eth_getCode, eth_getStorageAt, eth_call | Zustand bei einem bestimmten Block |
Zwei Verhaltensweisen überraschen Einsteiger. Ein Transaktionsbeleg mit dem Wert null bedeutet, dass die Transaktion ausstehend oder dem Node unbekannt ist, nicht, dass sie fehlgeschlagen ist. Außerdem antworten Zustandsmethoden für den von Ihnen übergebenen Block: eth_getBalance bei latest ändert sich alle paar Sekunden. Übergeben Sie daher für jede Zahl, die Sie in einem Bericht angeben, eine explizite Blocknummer.
eth_getLogs nimmt fromBlock und toBlock (oder einen einzelnen blockHash), eine optionale address und ein positionsabhängiges topics-Array entgegen. Diese Anfrage fragt bei einem Token-Contract Transfer-Ereignisse an eine Adresse über die Blöcke 21.000.000 (0x1406f40) bis 21.000.999 (0x1407327) ab:
{"jsonrpc": "2.0", "id": 1, "method": "eth_getLogs",
"params": [{
"fromBlock": "0x1406f40", "toBlock": "0x1407327",
"address": "0x5d3a…7c10",
"topics": ["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
null,
"0x000000000000000000000000c3d4…22e1"]
}]}
Topics werden nach Position abgeglichen: Das erste ist die Transfer-Signatur, null akzeptiert jeden Absender, und topics[2] legt den Empfänger fest. Eine Position kann auch ein Array mit der Bedeutung „eines davon“ enthalten; wird die aufgefüllte Adresse an die zweite Position verschoben, werden von ihr gesendete Transfers zurückgegeben.
Debug- und Trace-Methoden
Interne Aufrufe erfordern eine erneute Ausführung. Clients im Geth-Stil bieten debug_traceTransaction, debug_traceBlockByNumber und debug_traceCall mit einem tracer wie callTracer (Aufrufbaum) oder prestateTracer (betroffener Zustand). Clients im Parity-Stil (Erigon, Nethermind, Reth) bieten trace_transaction, trace_block, trace_filter und trace_replayTransaction, die flache Aufruflisten zurückgeben. Beide Varianten sind aufwendig, oft deaktiviert oder bei Anbietern mit Zusatzkosten verbunden und unterscheiden sich in ihrer Struktur (beispielsweise darin, ob Aufrufe von Precompiles erscheinen). Normalisieren Sie sie daher, bevor Sie Ergebnisse zusammenführen.
Welche Fragen welchen Node benötigen
| Frage | Bitcoin | Ethereum |
|---|---|---|
| Blöcke, Transaktionen, Transaktionsbelege, Logs | Full Node (txindex=1 für die Suche nach txid) | Full Node; die Historie vor dem Merge kann bereits abgelaufen sein |
| Aktueller Kontostand oder UTXO-Status | gettxout oder ein Indexer für Adressen | Full Node, eth_getBalance |
| Kontostand bei einem früheren Block | Indexer oder Data Warehouse | Archiv-Node |
| Adressverlauf | Adressindexer oder Data Warehouse | Indexer oder Data Warehouse (keine native Methode) |
| Interne Aufrufe alter Transaktionen | Nicht zutreffend | Archiv-Node mit Tracing |
Pruned Nodes können alte Blöcke überhaupt nicht bereitstellen. Ein Ethereum-Full-Node, der nach einem Zustand gefragt wird, der älter als sein Aufbewahrungsfenster ist, liefert einen Fehler statt einer falschen Zahl: ein Hinweis darauf, dass Sie einen Archiv-Node benötigen.
Anbieter, Ratenbegrenzungen und Vertrauen
Hosting-Anbieter setzen Ratenbegrenzungen durch (Anfragen pro Sekunde oder gewichtete „Recheneinheiten“) und begrenzen eth_getLogs nach Blockbereich, Ergebnisanzahl oder beidem. Eine robuste Extraktion unterteilt einen Bereich in Teilbereiche, halbiert einen vom Anbieter abgelehnten Teilbereich, wiederholt Anfragen mit exponentiell zunehmenden Wartezeiten und protokolliert abgeschlossene Bereiche. JSON-RPC-Stapelanfragen reduzieren den Overhead, werden aber auf dieselben Limits angerechnet. Anbieter werfen außerdem Vertrauensfragen auf:
- Inkonsistente Spitzen. Hinter einem Load Balancer können aufeinanderfolgende Aufrufe Nodes auf unterschiedlichen Höhen erreichen. Binden Sie die Verarbeitung an einen Block-Hash, nicht an
latest. - Fehler und Verzögerungen. Vergleichen Sie bei Tatsachen, von denen ein Befund abhängt, den Block-Hash an Ihrer Referenzhöhe anhand zweier unabhängiger Quellen oder Ihres eigenen Nodes, und halten Sie die Client-Version fest (
web3_clientVersionoder das Feldsubversionvongetnetworkinfo). - Vertraulichkeit von Abfragen. Ein Anbieter sieht jede Adresse, die Sie abfragen; seine Protokolle können den Gegenstand einer Ermittlung offenlegen. Ihr eigener Node tut dies nicht.
Für umfangreiche historische Daten ist die RPC-Extraktion langsam. Öffentliche Datensätze (die Krypto-Datensätze von Google BigQuery, erstellt mit den Open-Source-Werkzeugen blockchain-etl; der AWS Public Blockchain Data-Datensatz in Parquet) und ETL-Frameworks (Ethereum ETL, Bitcoin ETL, cryo, TrueBlocks, The Graph) sind die Alternativen; Lektion 2.7 vergleicht sie.
Prüfungsschwerpunkt: Rechnen Sie mit Fragen, in denen Sie die richtige Datenquelle oder Auswertungsgrenze für einen Befund auswählen müssen: die sechs Bitcoin-Header-Felder und die Tatsache, dass der Block-Hash berechnet wird; Höhe als Position gegenüber Hash als Identität; Median Time Past, die Zwei-Stunden-Regel und nicht chronologisch geordnete Bitcoin-Zeitstempel gegenüber exakten Ethereum-Slots von 12 Sekunden; Reorgs, Logs mitremoved: trueund Audit-Daten veralteter Blöcke; Bestätigungen, Epochen und die Tagslatest,safeundfinalized; die Detailstufen vongetblockundgetrawtransactionsowietxindex; die Grenzen vongettxout; positionsabhängiger Topic-Abgleich ineth_getLogs;debug_- gegenübertrace_-Methoden; wann ein Archiv-Node benötigt wird; Überprüfung von Anbietern.