On-Chain-Daten und SQL · Lektion 3 von 9
Das UTXO-Modell für Analysten
9 Min. Lesezeit
Bitcoin und die davon abgeleiteten Blockchains (Litecoin, Bitcoin Cash, Dogecoin und andere) speichern keine Guthaben. Sie speichern einzelne Outputs, die durch eine Transaktion erzeugt und durch eine andere vernichtet werden. Jedes Guthaben, jeder Wertfluss, jede Nachverfolgung und jedes Cluster, das Analysten für diese Blockchains erstellen, beruht auf dieser Struktur. Die meisten Anfängerfehler (Doppelzählungen, Phantomguthaben, „Zahlungen“, die tatsächlich Wechselgeld waren) entstehen, weil dies vergessen wird.
Coins sind Outputs
Ein Transaktionsoutput besteht aus einem Betrag und einem Sperrskript (dem scriptPubKey). Er wird durch seinen Outpoint identifiziert: die txid der Transaktion, die ihn erzeugt hat, und seine Position in der Output-Liste dieser Transaktion, geschrieben als txid:vout. Ein Output kennt nur zwei Zustände: nicht ausgegeben oder ausgegeben. Er wird genau einmal und vollständig ausgegeben. Es gibt weder eine teilweise Ausgabe noch ein „Konto“, von dem etwas abgebucht wird.
Ein Input enthält keinen Betrag. Er verweist auf einen früheren Outpoint und liefert die Daten (Signatur, öffentlicher Schlüssel, Skript), die das Sperrskript dieses Outputs erfüllen. Um den Wert eines Inputs zu ermitteln, schlagen Sie den Output nach, den er ausgibt (siehe die Lektion Rohe Bitcoin-Transaktionen und Skripttypen).
Daraus ergeben sich drei Konsequenzen für die Analyse:
| Was Nutzer sehen | Was die Blockchain aufzeichnet |
|---|---|
| „Meine Adresse hält 1,2 BTC“ | Mehrere nicht ausgegebene Outputs, deren Skripte sich zu dieser Adresse dekodieren lassen und die zusammen 1,2 BTC ergeben |
| „Ich habe 0,5 BTC gesendet“ | Eine Transaktion, die vollständige Outputs verbraucht und neue erzeugt hat, meist einschließlich Wechselgeld |
| „Mein Guthaben ist gesunken“ | Outputs sind aus der Menge der nicht ausgegebenen in die Menge der ausgegebenen Outputs gewechselt |
Ein Adressguthaben ist somit eine abgeleitete Größe, niemals eine gespeicherte. Neue Coins gelangen durch die Coinbase-Transaktion in Umlauf. Sie hat keine echten Inputs und zahlt die Blocksubvention zuzüglich Gebühren aus. Coinbase-Outputs können erst in einem Block ausgegeben werden, der mindestens 100 Blöcke nach dem Block liegt, in dem sie erzeugt wurden. Diese Regel wird als Coinbase-Reife bezeichnet.
Der Ausgabegraph
Da jeder Input auf genau einen früheren Output verweist, bildet die Blockchain einen Ausgabegraphen. Hier ein kleines dekodiertes Beispiel:
{
"txid": "b7e0…5d19",
"vin": [
{ "txid": "4f3a…c21e", "vout": 0 },
{ "txid": "9b1d…07aa", "vout": 1 }
],
"vout": [
{ "n": 0, "value": 1.00000000, "address": "3J9x…Qe1m" },
{ "n": 1, "value": 0.09950000, "address": "bc1q…r8tn" }
]
}
Die Transaktion b7e0…5d19 gibt Output 0 von 4f3a…c21e (0,80 BTC) und Output 1 von 9b1d…07aa (0,30 BTC) aus. Die Inputs ergeben insgesamt 1,10 BTC, die Outputs insgesamt 1,0995 BTC. Die Gebühr ist die Differenz: 0,0005 BTC. Die beiden Outputs sind nun nicht ausgegeben und werden erst dann zu Kanten, wenn sie ausgegeben werden.
Als Graph betrachtet sind Transaktionen Knoten und Outputs gerichtete Kanten von der Transaktion, die sie erzeugt hat, zu der Transaktion, die sie ausgegeben hat. Nicht ausgegebene Outputs sind Kanten, die noch kein Ziel haben. Der Graph ist azyklisch und weist zeitlich stets nach vorn. Daher lässt sich jeder Satoshi Schritt für Schritt rückwärts bis zu den Coinbase-Transaktionen verfolgen, die ihn erzeugt haben.
Eine Eigenschaft ist wichtiger als alle anderen: Innerhalb einer Transaktion verknüpft das Protokoll keine bestimmten Inputs mit bestimmten Outputs. Wenn 0,80 und 0,30 BTC hineingehen und 1,00 und 0,0995 herauskommen, besagt nichts auf der Blockchain, welcher Input welchen Output „bezahlt“ hat. Der Wert wird zusammengeführt und neu verteilt. Jede Nachverfolgungsmethode, die Inputs bestimmten Outputs zuordnet (First-in-first-out, Haircut und so weiter), ist eine Konvention der Analysten und keine aus den Daten ablesbare Tatsache. Die Lektion Nachverfolgungsmethoden und ihre Konsequenzen vergleicht diese Methoden.
Wechselgeldoutputs
Da Outputs vollständig ausgegeben werden, sendet eine Zahlung üblicherweise einen Teil des Werts an den Empfänger und den Rest als Wechselgeld an den Absender zurück. Im obigen Beispiel ist einer der beiden Outputs wahrscheinlich Wechselgeld, doch das Protokoll kennzeichnet nicht, welcher. Seine Identifizierung beruht auf Heuristiken (Skripttyp, runde Beträge, Neuheit der Adresse), die in der Lektion Heuristiken zur Wechselgelderkennung behandelt werden.
Eine falsche Einordnung von Wechselgeld hat erhebliche Folgen. Wenn Sie Wechselgeld als Zahlung behandeln, erfinden Sie eine Gegenpartei und verfolgen den falschen Zweig weiter. Wenn Sie alle Outputs als übertragenen Wert zählen, wird das On-Chain-„Volumen“ aufgebläht, denn Wechselgeld und Eigenübertragungen bewegen keinen Wert zwischen Parteien. Seriöse Volumenkennzahlen versuchen, Wechselgeld und Konsolidierungen auszuschließen. Jede solche Kennzahl ist jedoch nur so gut wie ihr Wechselgeldmodell.
Es hilft, einige häufige Transaktionsmuster zu erkennen:
| Muster | Typische Struktur | Übliche Bedeutung |
|---|---|---|
| Einfache Zahlung | 1–3 Inputs, 2 Outputs | Zahlung plus Wechselgeld |
| Konsolidierung | Viele Inputs, 1 Output | Eine Wallet führt kleine Outputs zusammen, häufig bei niedrigen Gebühren |
| Sammelauszahlung | Wenige Inputs, viele Outputs | Ein Dienst zahlt viele Kunden gleichzeitig aus |
| Peel-Schritt | 1 Input, 2 Outputs: ein kleiner, ein großer | Teil einer Peel-Chain; der große Output wird weitergeführt (siehe die Lektion Transaktionsgraphen und Graphmetriken) |
Coin-Alter und Dormanz
Für jeden Output wird festgehalten, in welchem Block er erzeugt wurde. Daher hat jeder nicht ausgegebene Output ein Alter. Wenn ein Output ausgegeben wird, berechnen Analysten die vernichteten Coin-Tage (Coin Days Destroyed, CDD): den Betrag multipliziert mit der Anzahl der Tage, die er nicht ausgegeben blieb. Ein Output von 2 BTC, der 400 Tage zuvor erzeugt wurde, vernichtet bei seiner Ausgabe 800 Coin-Tage. Die gesamten CDD eines Tages, geteilt durch die an diesem Tag bewegten BTC, ergeben eine durchschnittliche Dormanz: wie lange die bewegten Coins im Durchschnitt zuvor stillgelegen hatten.
Das Alter ist für Ermittlungen wichtig, weil plötzliche Bewegungen lange inaktiver Coins ein klassisches Warnsignal sind. Ein großer Teil der 2016 bei Bitfinex gestohlenen Bitcoin blieb jahrelang in der Wallet des Hackers, bis Behörden 2022 etwa 94.000 BTC beschlagnahmten. Outputs, die mit einem alten Vorfall verbunden sind, auf ihre erste Ausgabe zu überwachen, ist eine der einfachsten und wertvollsten Regeln, die Analysten einrichten können.
Eine Aufschlüsselung der UTXO-Menge nach Alter bei einer festen Blockhöhe sieht in SQL so aus. Das Schema ist das allgemeine Schema, das im gesamten Modul verwendet wird (Lektionen 2.7 und 2.9): eine Tabelle outputs mit einer Zeile pro Output und eine Tabelle inputs, in der jede Zeile den Outpoint benennt, den sie ausgibt (spent_transaction_hash, spent_output_index); die Werte sind in Satoshis angegeben.
-- Nicht ausgegebene Outputs auf Höhe 900000, nach Alter gruppiert (etwa 144 Blöcke pro Tag)
WITH spent AS (
SELECT spent_transaction_hash, spent_output_index
FROM inputs
WHERE block_number <= 900000
)
SELECT
CASE WHEN 900000 - o.block_number < 144 * 30 THEN '1: unter 1 Monat'
WHEN 900000 - o.block_number < 144 * 365 THEN '2: 1-12 Monate'
ELSE '3: über 1 Jahr' END AS age_band,
COUNT(*) AS utxos,
SUM(o.value) / 100000000.0 AS btc
FROM outputs o
LEFT JOIN spent s
ON s.spent_transaction_hash = o.transaction_hash
AND s.spent_output_index = o.output_index
WHERE o.block_number <= 900000
AND s.spent_transaction_hash IS NULL -- keine Ausgabe auf oder vor dieser Höhe
GROUP BY 1
ORDER BY 1;
Die Abfrage behält nur Outputs bei, die auf oder vor der gewählten Höhe erzeugt wurden und für die es auf oder vor dieser Höhe keine passende Ausgabe gibt. Das ist die Definition der UTXO-Menge zu diesem Zeitpunkt. Die Altersgruppen verwenden Blockzahlen als Näherung für die Zeit. Für präzise Altersangaben verknüpfen Sie die Daten mit der Blocktabelle und verwenden Sie die Blockzeitstempel (unter Berücksichtigung der Einschränkungen bei Zeitstempeln in der Lektion Blöcke, Header und Node-APIs). Beachten Sie den Divisor 100000000.0: Eine Ganzzahldivision würde in manchen Datenbank-Engines die Nachkommastellen ohne Warnung abschneiden.
Die UTXO-Menge
Die Menge aller nicht ausgegebenen Outputs bei einem bestimmten Block ist die UTXO-Menge. Nodes speichern sie in einer eigenen Datenbank (dem Chainstate), weil sie diese zur Validierung neuer Transaktionen benötigen. Sie ist stark gewachsen, unter anderem durch Experimente mit Inscriptions und Token, die viele kleine Outputs erzeugt haben. Abfragen darüber sind daher ressourcenintensiv.
Zwei RPC-Methoden von Bitcoin Core sind hier nützlich:
gettxoutsetinfoliefert zusammenfassende Statistiken zur Menge, daruntertxouts(die Anzahl der nicht ausgegebenen Outputs) undtotal_amount(die darin enthaltenen Coins). Die Abfrage einer historischen Höhe erfordert den optionalen coinstatsindex.scantxoutsetdurchsucht die aktuelle UTXO-Menge nach Outputs, die Output-Deskriptoren wieaddr(...)entsprechen, und gibt jeden Treffer mit txid, vout, Betrag und Höhe zurück. Die Methode sieht nur nicht ausgegebene Outputs, niemals den Verlauf.
Bitcoin Core führt keinen Adressindex. Ein vollständiger Transaktionsverlauf für eine Adresse erfordert daher einen Indexer oder ein Data Warehouse (siehe die Lektion Blöcke, Header und Node-APIs).
Die Menge ermöglicht auch eine Plausibilitätsprüfung. Ihr total_amount sollte nahe an der insgesamt jemals ausgegebenen Blocksubvention liegen, aber darunter, weil manche Werte nachweislich nicht ausgebbar sind und nie in die Menge gelangen: die Belohnung des Genesis-Blocks, OP_RETURN-Outputs sowie Gebühren oder Blocksubventionen, die Miner nicht beansprucht haben. Eine Pipeline, deren berechnete UTXO-Gesamtsumme die ausgegebene Coin-Menge übersteigt, enthält einen Fehler, typischerweise fehlende Ausgaben oder doppelte Outputs.
Adresswiederverwendung
Adressen sind keine Konten. Ordnungsgemäß arbeitende Wallets leiten für jeden Empfang eine neue Adresse aus einem hierarchisch-deterministischen Seed ab, und die meisten davon bekommt der Nutzer nie zu sehen. Eine Person kann Tausende Adressen kontrollieren; eine einzige Hot-Wallet-Adresse einer Börse kann mit Millionen von Gegenparteien interagieren.
Adresswiederverwendung (der mehrmalige Empfang an derselben Adresse) ist dennoch verbreitet: bei Spendenadressen, manchen Einzahlungsadressen von Börsen, alten Wallets und unvorsichtigen Nutzern. Für Analysten ist sie Geschenk und Falle zugleich. Die Wiederverwendung verknüpft Zahlungen ohne jede Heuristik miteinander, und sobald von einer Adresse ausgegeben wurde, ist ihr öffentlicher Schlüssel auf der Blockchain sichtbar. Adressbezogene Kennzahlen wie „aktive Adressen“ oder „Adressen mit mehr als 1 BTC“ messen jedoch Skripte, nicht Personen, und dürfen niemals als Nutzerzahlen dargestellt werden.
Eine Feinheit: Derselbe öffentliche Schlüssel kann mehrere unterschiedliche Adressen erzeugen, eine pro Skripttyp (zum Beispiel Legacy-P2PKH und natives SegWit-P2WPKH). Sie wirken unverbunden, doch sobald der Schlüssel bei einer Ausgabe offengelegt wird, können Analysten sie anhand des öffentlichen Schlüssels selbst verknüpfen.
Prüfungsschwerpunkt: Ein Output wird durch seinen Outpoint (txid:vout) identifiziert und genau einmal sowie vollständig ausgegeben; Inputs enthalten keinen Betrag, daher werden Input-Werte und Guthaben aus den Outputs selbst abgeleitet; das Protokoll verknüpft keine bestimmten Inputs mit bestimmten Outputs, daher ist die Nachverfolgung von Inputs zu Outputs eine Konvention; Wechselgeldoutputs und warum ihre falsche Einordnung Nachverfolgungen und Volumen verzerrt; Coinbase-Reife von 100 Blöcken sowie vernichtete Coin-Tage (Betrag × Tage ohne Ausgabe) und Dormanz als Warnsignale; Berechnung der UTXO-Menge bei einer bestimmten Höhe (auf oder vor dieser Höhe erzeugt, auf oder vor dieser Höhe nicht ausgegeben);gettxoutsetinfoundscantxoutsetund ihre Grenzen; Adresswiederverwendung und warum Adresszahlen keine Nutzerzahlen sind.