UTXO- und Kontenmodelle · Lektion 1 von 6
Das UTXO-Modell für Analysten
9 Min. Lesezeit
Bitcoin und die davon abgeleiteten Chains (Litecoin, Bitcoin Cash, Dogecoin und andere) speichern keine Kontostände. Sie speichern einzelne Outputs, die von einer Transaktion erstellt und von einer anderen ausgegeben werden. Jeder Kontostand, jeder Flow, jede Nachverfolgung und jedes Cluster, das ein Analyst für diese Chains erstellt, basiert auf dieser Struktur. Die meisten Anfängerfehler (doppelte Zählung, Phantomkontostände, „Zahlungen“, die in Wirklichkeit Wechselgeld waren) entstehen dadurch, dass man das vergisst.
Coins sind Outputs
Ein Transaktionsoutput ist ein Betrag zusammen mit einem Sperrskript (dem scriptPubKey). Er wird durch seinen Outpoint identifiziert: die txid der Transaktion, die ihn erstellt hat, und seine Position in der Output-Liste dieser Transaktion, geschrieben als txid:vout. Ein Output hat nur zwei Zustände: nicht ausgegeben oder ausgegeben; er wird genau einmal und vollständig ausgegeben. Es gibt keine Teilausgaben und kein „Konto“, von dem etwas abgebucht wird.
Ein Input enthält keinen Betrag. Er verweist auf einen früheren Outpoint und liefert die Daten (Signatur, öffentlichen Schlüssel, Skript), die das Sperrskript dieses Outputs erfüllen. Um den Wert eines Inputs zu ermitteln, schlägt man den Output nach, den er ausgibt (siehe die Lektion Rohe Bitcoin-Transaktionen).
Daraus ergeben sich drei Konsequenzen für die Analyse:
| Was Nutzer sehen | Was die Chain erfasst |
|---|---|
| „Auf meiner Adresse liegen 1,2 BTC“ | Mehrere nicht ausgegebene Outputs, deren Skripte zu dieser Adresse dekodiert werden und zusammen 1,2 BTC ergeben |
| „Ich habe 0,5 BTC gesendet“ | Eine Transaktion, die ganze Outputs ausgegeben und neue erstellt hat, üblicherweise einschließlich Wechselgeld |
| „Mein Kontostand ist gesunken“ | Outputs wurden aus der Menge der nicht ausgegebenen in die Menge der ausgegebenen Outputs verschoben |
Ein Adresskontostand ist daher eine abgeleitete Größe und wird nie gespeichert. Neue Coins gelangen über die Coinbase-Transaktion ins System. Sie hat keine echten Inputs und zahlt die Blocksubvention zuzüglich der 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 erstellt wurden. Diese Regel heißt Coinbase-Maturität.
Der Ausgabengraph
Da jeder Input auf genau einen früheren Output verweist, bildet die Chain einen Ausgabengraphen. Hier ist 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 zusammen 1,10 BTC; die Outputs ergeben zusammen 1,0995 BTC; die Gebühr ist die Differenz: 0,0005 BTC. Die beiden Outputs sind jetzt nicht ausgegeben und werden erst dann zu Kanten, wenn sie ausgegeben werden.
Als Graph gelesen, sind Transaktionen Knoten und Outputs gerichtete Kanten von der Transaktion, die sie erstellt hat, zu der Transaktion, die sie ausgegeben hat. Nicht ausgegebene Outputs sind Kanten, die noch kein Ziel haben. Der Graph ist azyklisch und weist immer in die Zukunft, sodass sich jedes Satoshi rückwärts, Schritt für Schritt, bis zu den Coinbase-Transaktionen zurückverfolgen lässt, durch die es erstellt wurde.
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 BTC herauskommen, sagt nichts auf der Chain, welcher Input welchen Output „bezahlt“ hat. Der Wert wird zusammengelegt und neu verteilt. Jede Nachverfolgungsmethode, die Inputs Outputs zuordnet (First-in-first-out, Haircut und Ähnliches), ist eine Konvention von Analysten und keine aus den Daten ablesbare Tatsache. Die Lektion Geldflüsse vorwärts und rückwärts nachverfolgen vergleicht diese Methoden.
Wechselgeld-Outputs
Da Outputs vollständig ausgegeben werden, sendet eine Zahlung gewöhnlich einen Teil des Werts an den Empfänger und gibt den Rest als Wechselgeld an den Absender zurück. Im obigen Beispiel ist wahrscheinlich einer der beiden Outputs Wechselgeld, aber das Protokoll kennzeichnet nicht, welcher. Die Identifizierung erfolgt anhand von Heuristiken (Skripttyp, runde Beträge, Alter der Adresse), die in der Lektion Heuristiken zur Erkennung von Wechselgeld behandelt werden.
Eine falsche Zuordnung von Wechselgeld hat große Auswirkungen. Wird Wechselgeld als Zahlung behandelt, erfindet man eine Gegenpartei und verfolgt den Flow entlang des falschen Zweigs weiter. Werden alle Outputs als übertragener Wert gezählt, wird das On-Chain-„Volumen“ überhöht, denn Wechselgeld und Transfers zwischen eigenen Adressen verschieben keinen Wert zwischen Parteien. Seriöse Volumenmessungen versuchen, Wechselgeld und Konsolidierungen auszuschließen. Jede solche Messung ist nur so gut wie ihr Wechselgeldmodell.
Das Erkennen einiger gängiger Transaktionsformen hilft:
| Form | 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, oft bei niedrigen Gebühren |
| Sammelauszahlung | Wenige Inputs, viele Outputs | Ein Dienstleister bezahlt viele Kunden auf einmal |
| Peel-Schritt | 1 Input, 2 Outputs: einer klein, einer groß | Teil einer Peel-Kette; der große Output wird weiterverwendet (siehe die Lektion Graphmetriken und Muster) |
Coin-Alter und Dormanz
Jeder Output speichert den Block, in dem er erstellt wurde, daher hat jeder nicht ausgegebene Output ein Alter. Wenn ein Output ausgegeben wird, berechnen Analysten die vernichteten Coin-Tage (CDD): den Betrag multipliziert mit der Anzahl der Tage, an denen er nicht ausgegeben wurde. Ein Output von 2 BTC, der 400 Tage zuvor erstellt wurde, vernichtet bei seiner Ausgabe 800 Coin-Tage. Die CDD-Gesamtsumme eines Tages geteilt durch die an diesem Tag bewegten BTC ergibt die durchschnittliche Dormanz: wie lange die bewegten Coins im Durchschnitt stillgelegen hatten.
Das Alter ist bei Untersuchungen relevant, denn Coins, die lange inaktiv waren und sich plötzlich bewegen, sind ein klassischer Warnhinweis. Ein großer Teil der 2016 von Bitfinex gestohlenen Bitcoins blieb jahrelang in der Wallet des Hackers, bis die Behörden 2022 etwa 94.000 BTC beschlagnahmten. Outputs, die mit einem alten Vorfall verknüpft sind, auf ihre erste Ausgabe zu überwachen, ist eine der einfachsten und wertvollsten Regeln, die ein Analyst festlegen kann.
Eine Aufschlüsselung der UTXO-Menge nach Alter zu einer festgelegten Blockhöhe sieht in SQL so aus. Das Schema ist typisch: eine Tabelle outputs mit einer Zeile pro Output und eine Tabelle inputs, in der jede Zeile den Outpoint benennt, den sie ausgibt.
-- Nicht ausgegebene Outputs bei Blockhöhe 900000, nach Alter gruppiert (etwa 144 Blöcke pro Tag)
WITH spent AS (
SELECT prev_txid, prev_vout
FROM inputs
WHERE block_height <= 900000
)
SELECT
CASE WHEN 900000 - o.block_height < 144 * 30 THEN '1: unter 1 Monat'
WHEN 900000 - o.block_height < 144 * 365 THEN '2: 1–12 Monate'
ELSE '3: über 1 Jahr' END AS age_band,
COUNT(*) AS utxos,
SUM(o.value_sat) / 100000000.0 AS btc
FROM outputs o
LEFT JOIN spent s
ON s.prev_txid = o.txid AND s.prev_vout = o.vout
WHERE o.block_height <= 900000
AND s.prev_txid IS NULL -- keine Ausgabe bei oder vor dieser Blockhöhe
GROUP BY 1
ORDER BY 1;
Die Abfrage berücksichtigt nur Outputs, die bei oder vor der gewählten Blockhöhe erstellt wurden und für die es bei oder vor dieser Blockhöhe keine passende Ausgabe gibt. Das ist die Definition der UTXO-Menge zu diesem Zeitpunkt. Die Altersgruppen verwenden Blockzahlen als Näherungswert für die Zeit. Für genaue Altersangaben verbindet man die Daten mit der Tabelle blocks und verwendet Blockzeitstempel (unter Berücksichtigung der Hinweise zu Zeitstempeln in der Lektion Blöcke und Header als Daten). Beachten Sie den Divisor 100000000.0: Ganzzahldivision würde in einigen Engines stillschweigend abrunden.
Die UTXO-Menge
Die Menge aller nicht ausgegebenen Outputs in einem bestimmten Block ist die UTXO-Menge. Nodes halten sie in einer eigenen Datenbank (dem Chainstate), weil sie diese zur Validierung neuer Transaktionen benötigen. Sie ist stark gewachsen, teilweise durch Experimente mit Inscriptions und Token, bei denen viele kleine Outputs entstanden sind. Abfragen darüber sind daher rechenintensiv.
Zwei Bitcoin-Core-RPC-Methoden sind hier nützlich:
gettxoutsetinfogibt zusammenfassende Statistiken zur Menge zurück, daruntertxouts(die Anzahl der nicht ausgegebenen Outputs) undtotal_amount(die darin enthaltenen Coins). Für eine historische Blockhöhe ist der optionale coinstatsindex erforderlich.scantxoutsetdurchsucht die aktuelle UTXO-Menge nach Outputs, die zu Output-Deskriptoren wieaddr(...)passen, und gibt jeden Treffer zusammen mit seiner txid, seinem vout, seinem Betrag und seiner Blockhöhe zurück. Die Methode sieht nur nicht ausgegebene Outputs, niemals die Historie.
Bitcoin Core führt keinen Adressindex. Für eine vollständige Transaktionshistorie zu einer Adresse ist daher ein Indexer oder ein Data Warehouse erforderlich (siehe die Lektion Node-APIs und Datenzugriff).
Die Menge bietet außerdem eine Plausibilitätsprüfung. Ihr total_amount sollte nahe an der insgesamt jemals ausgegebenen Subvention liegen, aber darunter, weil ein Teil des Werts nachweislich nicht ausgegeben werden kann und nie in die Menge gelangt: die Blockbelohnung des Genesis-Blocks, OP_RETURN-Outputs sowie Gebühren oder Subventionen, die Miner nicht beansprucht haben. Wenn die von einer Pipeline berechnete UTXO-Gesamtsumme die ausgegebene Menge übersteigt, liegt ein Fehler vor, typischerweise weil Ausgaben fehlen oder Outputs doppelt gezählt wurden.
Wiederverwendung von Adressen
Adressen sind keine Konten. Ordnungsgemäß eingerichtete Wallets leiten für jeden Empfang eine neue Adresse aus einem hierarchisch-deterministischen Seed ab, und der Nutzer sieht die meisten dieser Adressen nie. Eine Person kann Tausende von Adressen kontrollieren; eine einzige Hot-Wallet-Adresse einer Börse kann Millionen von Gegenparteien berühren.
Die Wiederverwendung von Adressen (mehrere Zahlungseingänge an dieselbe Adresse) ist dennoch verbreitet: bei Spendenadressen, einigen Einzahlungsadressen von Börsen, alten Wallets und unvorsichtigen Nutzern. Für Analysten ist das ein Geschenk und eine Falle. Die Wiederverwendung verknüpft Zahlungen ohne jede Heuristik, und sobald eine Adresse etwas ausgegeben hat, ist ihr öffentlicher Schlüssel auf der Chain sichtbar. Metriken auf Adressbasis wie „aktive Adressen“ oder „Adressen mit mehr als 1 BTC“ messen jedoch Skripte und keine Personen und sollten niemals als Nutzerzahlen dargestellt werden.
Ein Detail ist wichtig: Aus demselben öffentlichen Schlüssel lassen sich mehrere verschiedene Adressen erzeugen, je eine pro Skripttyp (zum Beispiel das alte P2PKH-Format und native SegWit-P2WPKH). Sie sehen nicht miteinander verbunden aus, aber sobald der Schlüssel bei einer Ausgabe offengelegt wird, kann ein Analyst sie über den öffentlichen Schlüssel selbst verknüpfen.
Prüfungsschwerpunkt: Ein Output wird durch seinen Outpoint (txid:vout) identifiziert und einmal vollständig ausgegeben; Inputs enthalten keinen Betrag, daher werden Inputwerte und Kontostände aus den Outputs selbst abgeleitet; das Protokoll verknüpft keine bestimmten Inputs mit bestimmten Outputs, daher ist die Zuordnung von Inputs zu Outputs eine Konvention; Wechselgeld-Outputs und die Gründe, warum ihre falsche Einordnung Nachverfolgungen und Volumen verzerrt; Coinbase-Maturität von 100 Blöcken sowie vernichtete Coin-Tage (Betrag × Tage nicht ausgegeben) und Dormanz als Warnhinweise; Berechnung der UTXO-Menge zu einer Blockhöhe (bei oder davor erstellt, bei oder davor nicht ausgegeben);gettxoutsetinfoundscantxoutsetsamt ihren Einschränkungen; Wiederverwendung von Adressen und die Gründe, warum Adresszahlen keine Nutzerzahlen sind.