Unformatierte Blockchain-Daten lesen · Lektion 3 von 6
Rohe Bitcoin-Transaktionen
9 Min. Lesezeit
Explorer zeigen Bitcoin-Transaktionen als übersichtliche Listen von Adressen und Beträgen an. Diese Ansicht ist jedoch eine Dekodierung von Rohbytes, und manches, was sie anzeigt, steht gar nicht in der Transaktion. Wer die Rohstruktur liest, erkennt, was tatsächlich on-chain erfasst ist und was abgeleitet wurde, warum sich die Gebühr nicht allein aus einer Transaktion berechnen lässt und welche Felder die Fingerabdrücke enthalten, auf die sich spätere Heuristiken stützen.
Die Serialisierung, Feld für Feld
Eine Transaktion wird als Bytefolge übertragen und gespeichert. Seit SegWit (BIP 141, aktiviert im August 2017) gibt es zwei Formen: die Legacy-Form und die in BIP 144 definierte erweiterte Form, die verwendet wird, wenn mindestens ein Input Witness-Daten enthält.
| Feld | Größe | Hinweise |
|---|---|---|
| Version | 4 Byte | Little-Endian-Ganzzahl, üblicherweise 1 oder 2 |
| Marker, Flag | 2 Byte | 00 01, nur in der SegWit-Form vorhanden |
| Anzahl der Inputs | variabel | CompactSize-Ganzzahl |
| Inputs | variabel | Jeweils: vorherige txid (32), Output-Index (4), Länge von scriptSig und scriptSig, Sequence (4) |
| Anzahl der Outputs | variabel | CompactSize-Ganzzahl |
| Outputs | variabel | Jeweils: Wert in Satoshis (8), Länge von scriptPubKey und scriptPubKey |
| Witness | variabel | Nur in der SegWit-Form: Anzahl der Elemente und die Elemente für jeden Input |
| Locktime | 4 Byte | Früheste Blockhöhe oder Zeit, ab der die Transaktion gültig ist |
Ganzzahlen werden in Little-Endian gespeichert: Das niederwertigste Byte steht zuerst. Eine CompactSize-Ganzzahl benötigt für Werte unter 253 ein Byte, andernfalls ein Präfixbyte (fd, fe oder ff), auf das 2, 4 oder 8 Byte folgen. Hier ist eine SegWit-Transaktion mit einem Input und zwei Outputs in ihre Felder aufgeteilt; lange Werte sind gekürzt:
02000000 Version 2
00 01 SegWit-Marker und -Flag
01 Anzahl der Inputs: 1
ab09…1d7c Vorherige txid, interne Byte-Reihenfolge (32 Byte)
01000000 Index des vorherigen Outputs: 1
00 Länge von scriptSig: 0 (nativer SegWit-Input)
fdffffff Sequence 0xfffffffd
02 Anzahl der Outputs: 2
40420f0000000000 Wert: 1.000.000 sat
16 0014 3c1e…9d02 Script, 22 Byte: P2WPKH
0c6a070000000000 Wert: 485.900 sat
16 0014 77b4…e051 Script, 22 Byte: P2WPKH
02 47 3044…01 21 02a1…5f Witness: 2 Elemente, Signatur (71 Byte), öffentlicher Schlüssel (33 Byte)
00000000 Locktime 0
Lies den ersten Wert, indem du seine Byte-Reihenfolge umkehrst: 40 42 0f 00 … wird zu 0x0f4240, also 1.000.000 Satoshis (0,01 BTC). Beachte, was fehlt: Es gibt weder eine Absenderadresse noch einen Input-Betrag oder eine Gebühr.
Inputs und Outpoints
Ein Input enthält keine Coins; er verweist auf einen früheren Output, einen sogenannten Outpoint, der als txid:vout geschrieben wird. Die 32-Byte-txid im Input wird in interner Byte-Reihenfolge gespeichert, also in umgekehrter Reihenfolge zu der, die Explorer anzeigen: Die Bytes ab09…1d7c erscheinen auf dem Bildschirm als 7c1d…09ab. Wird diese Umkehrung vergessen, führt das häufig zu der Meldung „Transaktion nicht gefunden“.
Der Betrag und das Script, das ausgegeben wird, befinden sich im vorherigen Output, nicht im Input. Um zu erfahren, wer gezahlt hat und wie viel, musst du jeden Outpoint nachschlagen. Das scriptSig des Inputs (bei Legacy-Scripts) oder der Witness (bei SegWit-Scripts) liefert die Daten, die die Bedingungen des vorherigen Outputs erfüllen, üblicherweise Signaturen und öffentliche Schlüssel.
Das 4-Byte-Feld Sequence signalisiert ebenfalls eine Absicht: Werte unter 0xfffffffe signalisieren die Ersetzbarkeit nach BIP 125; 0xfffffffd ist die gängige Wahl und zugleich ein Wallet-Fingerabdruck. Seit Bitcoin Core 28.0 (2024) akzeptieren Nodes standardmäßig Ersatztransaktionen, unabhängig davon, ob die ursprüngliche Transaktion die Ersetzbarkeit signalisiert hat. Heute ist der Wert für Analysten daher hauptsächlich als Fingerabdruck relevant. Relative Zeitsperren (BIP 68) verwenden dasselbe Feld. Ein Coinbase-Input, der neue Coins erzeugt, hat eine vollständig aus Nullen bestehende vorherige txid und den Index 0xffffffff.
Version, Locktime und Wallet-Fingerabdrücke
Die Felder rund um Inputs und Outputs wirken wie bloße Formalitäten, enthalten aber Informationen. Die Version ist bei fast allen Transaktionen 1 oder 2; Version 2 wird für relative Zeitsperren benötigt, und Wallets unterscheiden sich darin, welche Version sie verwenden. Die Locktime wird als Blockhöhe gelesen, wenn sie unter 500.000.000 liegt, andernfalls als Unix-Zeitstempel; null bedeutet, dass keine Einschränkung gilt. Viele Wallets setzen sie auf die aktuelle Blockhöhe, um Miner davon abzuhalten, kürzlich erzeugte Blöcke umzuschreiben und Gebühren einzunehmen (eine Praxis namens Anti-Fee-Sniping). Eine Locktime von 880.213 in einer Transaktion, die bei Blockhöhe 880.214 bestätigt wurde, sagt daher etwas über die Software aus, mit der sie erstellt wurde.
Versions-, Locktime- und Sequence-Werte bilden zusammen mit den verwendeten Script-Typen und der Reihenfolge der Outputs einen Wallet-Fingerabdruck. Ein einzelner Fingerabdruck beweist nichts, aber eine konsistente Kombination über mehrere Transaktionen hinweg ist eines der Signale, die in der Lektion Heuristiken zur Erkennung von Wechselgeld verwendet werden, um eine Zahlung von Wechselgeld zu unterscheiden.
Outputs und Script-Typen
Jeder Output enthält einen Wert in Satoshis und ein scriptPubKey, also die Bedingung für seine Ausgabe. Standard-Scripts folgen festen Vorlagen, sodass sich der Typ anhand der ersten Bytes ablesen lässt:
| Typ | scriptPubKey-Muster | Länge | Definiert in | Adressen beginnen mit | Bitcoin-Core-type |
|---|---|---|---|---|---|
| P2PKH | 76 a9 14 {20 bytes} 88 ac | 25 | ursprünglich | 1 | pubkeyhash |
| P2SH | a9 14 {20 bytes} 87 | 23 | BIP 16 | 3 | scripthash |
| P2WPKH | 00 14 {20 bytes} | 22 | BIP 141 | bc1q | witness_v0_keyhash |
| P2WSH | 00 20 {32 bytes} | 34 | BIP 141 | bc1q (länger) | witness_v0_scripthash |
| P2TR | 51 20 {32 bytes} | 34 | BIP 341 | bc1p | witness_v1_taproot |
| OP_RETURN | 6a … | unterschiedlich | — | keine | nulldata |
Bei P2PKH steht 76 a9 14 … 88 ac für OP_DUP OP_HASH160 {push 20 bytes} OP_EQUALVERIFY OP_CHECKSIG. SegWit-Outputs beginnen mit einem Versions-Opcode (00 für Version 0, 51 für Version 1, Taproot), auf den ein Push des Programms folgt. Ein OP_RETURN-Output ist nachweislich nicht ausgebbar und enthält Daten, keinen Wert.
Eine Adresse ist eine Kodierung eines Standardscripts und kein Feld der Transaktion. Decoder leiten sie ab. Bei einem nicht standardmäßigen Script gibt es möglicherweise überhaupt keine Adresse, und Explorer zeigen unter Umständen eine provisorische an. Die Kodierungen selbst werden in der Lektion Script-Typen und Adressformate behandelt.
Witness-Daten
SegWit verlagert Signaturen aus dem scriptSig in einen separaten Witness-Abschnitt. Was der Witness enthält, hängt vom ausgegebenen Typ ab:
- P2WPKH: zwei Elemente, eine DER-Signatur mit einem Sighash-Byte (üblicherweise 71 oder 72 Byte) und ein komprimierter öffentlicher Schlüssel mit 33 Byte.
- P2WSH: die Elemente, die die Bedingungen erfüllen, gefolgt vom Witness-Script selbst, zum Beispiel einem 2-aus-3-Multisig-Script. Die Ausgabebedingungen werden erst sichtbar, wenn der Output ausgegeben wird.
- P2TR-Key-Path: eine einzelne 64-Byte-Schnorr-Signatur (BIP 340) oder 65 Byte bei einem nicht standardmäßigen Sighash-Typ. Bei einer Ausgabe über den Script-Path werden stattdessen ein Script (BIP 342) und ein Control Block offengelegt.
- P2SH-umhülltes SegWit: Das scriptSig enthält nur ein kurzes Redeem-Script wie
0014…, und die Signaturen befinden sich im Witness.
Witness-Bytes werden beim Blockspeicherplatz geringer gewichtet. BIP 141 definiert das Gewicht als Basisgröße × 3 + Gesamtgröße, wobei die Basisgröße Marker, Flag und Witness ausschließt. Die virtuelle Größe (vsize) ist das Gewicht ÷ 4, aufgerundet; Gebührenraten werden pro vByte angegeben.
Eine dekodierte Transaktion im JSON-Format
Bitcoin Cores getrawtransaction mit Verbosität 2 gibt die obige Transaktion dekodiert zurück, einschließlich jedes ausgegebenen Outputs (prevout) und der Gebühr, sofern der Node über die Undo-Daten des Blocks verfügt:
{
"txid": "4f3a…c21e", "hash": "9b07…e4d2",
"version": 2, "size": 222, "vsize": 141, "weight": 561, "locktime": 0,
"vin": [{
"txid": "7c1d…09ab", "vout": 1,
"scriptSig": {"asm": "", "hex": ""},
"txinwitness": ["3044…01", "02a1…5f"],
"prevout": {"value": 0.01500000, "height": 868120,
"scriptPubKey": {"type": "witness_v0_keyhash", "address": "bc1q…7k3f"}},
"sequence": 4294967293
}],
"vout": [
{"value": 0.01000000, "n": 0,
"scriptPubKey": {"type": "witness_v0_keyhash", "address": "bc1q…m2d8"}},
{"value": 0.00485900, "n": 1,
"scriptPubKey": {"type": "witness_v0_keyhash", "address": "bc1q…x9qa"}}
],
"fee": 0.00014100
}
Die Größen stimmen: Die Basisform ist 113 Byte groß, und der Witness-Abschnitt fügt einschließlich Marker und Flag 109 Byte hinzu, was insgesamt 222 Byte ergibt. Das Gewicht beträgt 113 × 3 + 222 = 561, und 561 ÷ 4 wird auf eine vsize von 141 aufgerundet. Beträge werden im JSON als BTC-Zahlen angegeben; wandle sie vor Berechnungen in ganzzahlige Satoshis um, wie in der Lektion Datenqualität, Normalisierung und Provenienz erläutert. Das einfache decoderawtransaction gibt dieselbe Struktur ohne prevout und fee zurück, da es keinen Zugriff auf vorherige Outputs hat.
Die Gebühr aus Rohdaten berechnen
Die Gebühr steht nie in der Transaktion. Sie ergibt sich aus der Differenz zwischen den Werten der Inputs und den Werten der Outputs:
- Inputs: ein Outpoint im Wert von 1.500.000 sat
- Outputs: 1.000.000 + 485.900 = 1.485.900 sat
- Gebühr: 1.500.000 − 1.485.900 = 14.100 sat, also 14.100 ÷ 141 = 100 sat/vB
Eine Coinbase-Transaktion hat keine Gebühr; ihre Outputs beanspruchen den Block-Subsidy zuzüglich der Gebühren aller anderen Transaktionen. In einem Data Warehouse mit separaten Tabellen für Inputs und Outputs sieht dieselbe Berechnung so aus (Tabellen- und Spaltennamen variieren je nach Datensatz):
-- Gebühr pro Transaktion in Satoshis: Summe der ausgegebenen Outputs minus Summe der neuen Outputs
WITH ins AS (
SELECT i.spending_txid AS txid, SUM(o.value_sat) AS in_sat
FROM inputs i
JOIN outputs o ON o.txid = i.prev_txid AND o.vout = i.prev_vout
GROUP BY i.spending_txid
), outs AS (
SELECT txid, SUM(value_sat) AS out_sat FROM outputs GROUP BY txid
)
SELECT ins.txid, ins.in_sat - outs.out_sat AS fee_sat
FROM ins JOIN outs ON outs.txid = ins.txid;
Der Join jedes Inputs mit seinem vorherigen Output ist der Schritt, den die Rohtransaktion nicht selbst ausführen kann. Coinbase-Transaktionen fallen heraus, weil ihre Inputs keinem früheren Output entsprechen.
txid und wtxid
Die txid ist der doppelte SHA-256-Hash der Transaktion, serialisiert ohne Marker, Flag und Witness. Die wtxid ist derselbe Hash über die vollständige SegWit-Form. Bei einer Transaktion ohne Witness-Daten sind beide identisch; Bitcoin Core zeigt die wtxid als hash an.
Das Ausschließen des Witness aus der txid behob ein seit Langem bestehendes Problem: die Drittparteien-Malleabilität. Durch eine Änderung der Signaturkodierung änderte sich zuvor die txid einer ansonsten identischen Transaktion. Änderungen am Witness verändern nur die wtxid, sodass sich Ketten unbestätigter Transaktionen sicher aufeinander beziehen können. Blöcke verpflichten sich über ein Witness-Commitment in der Coinbase zur Einbeziehung der wtxids; dabei wird die eigene wtxid der Coinbase als null gezählt. Identifiziere Transaktionen in Berichten und Suchabfragen anhand der txid in der angezeigten Byte-Reihenfolge.
Prüfungsschwerpunkt: Reihenfolge und Größe der Serialisierungsfelder, Little-Endian-Ganzzahlen und CompactSize; Outpoints und die umgekehrte interne Byte-Reihenfolge von txids; die scriptPubKey-Vorlagen von P2PKH, P2SH, P2WPKH, P2WSH und P2TR mit den zugehörigen BIPs und Adresspräfixen; dass Adressen abgeleitet und nicht gespeichert werden; welche Informationen Witness-Daten für jeden Script-Typ offenlegen; Gewicht (Basis × 3 + Gesamtgröße) und vsize; Berechnung der Gebühr anhand vorheriger Outputs; txid im Vergleich zu wtxid und Malleabilität.