Ein Bitcoin-Node hat von Haus aus keine grafische Oberfläche, keine App-Optik, keinen "Senden"-Knopf zum Anklicken. Trotzdem bauen Blockexplorer, Wallet-Apps, Zahlungsdienstleister und unzählige eigene Tools auf genau diesem Node auf. Der Grund: eine standardisierte Schnittstelle, über die sich praktisch jede beliebige Software mit einem laufenden Bitcoin-Node unterhalten kann.
Warum überhaupt eine eigene Schnittstelle nötig ist
Man könnte sich fragen, warum ein Bitcoin-Node nicht einfach direkt als Programm-Bibliothek in andere Software eingebunden wird, statt über den Umweg einer eigenen Netzwerk-Schnittstelle zu kommunizieren. Der Grund liegt in der Trennung von Verantwortlichkeiten: Der Node selbst (geschrieben in C++, siehe Teil 1 dieser Serie) läuft als eigenständiger, permanent aktiver Hintergrundprozess, unabhängig davon, in welcher Programmiersprache die anfragende Anwendung geschrieben ist. Eine Wallet-App auf deinem Smartphone, ein Web-Backend in Python oder JavaScript, ein Kommandozeilen-Skript in Bash, alle können auf exakt dieselbe Weise mit demselben Node sprechen, ganz ohne dass der Node selbst wissen müsste, wer da gerade anfragt oder in welcher Sprache diese Anwendung geschrieben wurde. Diese saubere Trennung ist ein zentraler Grund, warum rund um Bitcoin Core ein derart vielfältiges Ökosystem an Anwendungen entstehen konnte, ohne dass jede einzelne davon eine eigene, aufwendige Bitcoin-Implementierung mitbringen müsste.
JSON-RPC: eine einfache Frage-Antwort-Sprache
Bitcoin Core stellt seine Funktionen über eine sogenannte JSON-RPC-Schnittstelle bereit: ein weit verbreitetes, einfaches Format, bei dem eine anfragende Anwendung einen klar benannten Befehl mit ein paar Parametern schickt und eine strukturierte Antwort zurückbekommt. bitcoin-cli, das mitgelieferte Kommandozeilen-Werkzeug, ist im Grunde selbst nur ein sehr dünner Übersetzer, der deine Eingabe in genau so eine Anfrage verpackt.
bitcoin-cli: die einfachste Tür zu all dem
Für die meisten Node-Betreiber ist bitcoin-cli der erste und oft einzige direkte Kontakt mit dieser Schnittstelle. Es handelt sich um ein bewusst schlankes Kommandozeilenprogramm, das im Wesentlichen nur drei Dinge tut: deine eingetippten Parameter in eine gültige JSON-RPC-Anfrage verpacken, diese Anfrage an den lokal laufenden Node schicken, und die zurückkommende, meist ebenfalls JSON-formatierte Antwort lesbar auf dem Bildschirm ausgeben. Es enthält selbst keinerlei eigene Bitcoin-Logik; jede noch so komplizierte Frage, die du damit stellst, wird tatsächlich vom Node beantwortet, nicht vom Kommandozeilenprogramm selbst. Diese radikale Einfachheit ist Absicht: Sie hält die Angriffsfläche klein und macht den Werkzeugcode selbst leicht überprüfbar, was gerade bei einem Programm, das potenziell Befehle zum Versenden von Geld entgegennimmt, ein beruhigender Gedanke ist.
Nach Themen geordnet
Im Quellcode sind die verfügbaren Befehle sauber nach Themenbereich in eigene Dateien aufgeteilt (src/rpc/blockchain.cpp, src/rpc/rawtransaction.cpp, src/rpc/net.cpp, src/rpc/mining.cpp, dazu ein eigenes Modul für Wallet-Befehle) und dort in Kommando-Tabellen registriert. Ein kleiner Ausschnitt aus der Kategorie "blockchain" zeigt das Prinzip:
{"blockchain", &getblockchaininfo},
{"blockchain", &getbestblockhash},
{"blockchain", &getblock},
{"blockchain", &gettxout},
{"blockchain", &gettxoutsetinfo},
Für ein erstes Verständnis reichen ein paar zentrale Befehle: getblockchaininfo liefert den aktuellen Status der Blockchain (Höhe, Schwierigkeit, Synchronisationsfortschritt), getblock und getblockheader liefern die Rohdaten eines konkreten Blocks, gettxout prüft einen einzelnen, noch unverbrauchten Ausgabe-Betrag, sendrawtransaction speist eine fertig signierte Transaktion ins Netzwerk ein, und getrawmempool zeigt den aktuellen Wartesaal (siehe Teil 4). Wallet-spezifische Befehle wie listunspent oder sendtoaddress sind nur verfügbar, wenn tatsächlich eine Wallet im Node aktiviert ist.
Ein Beispiel: Wie ein Blockexplorer im Hintergrund arbeitet
Um das Prinzip greifbar zu machen, lohnt sich ein Blick darauf, was passiert, wenn du auf einer beliebigen Blockexplorer-Webseite eine Transaktions-ID eingibst und in Sekundenbruchteilen alle Details siehst. Im Hintergrund läuft dort in der Regel ein eigener, vollständiger Bitcoin-Node, meist mit aktiviertem Transaktions-Index (dazu mehr im letzten Teil dieser Serie). Die Webseite selbst enthält keine eigene Blockchain-Logik; sie übersetzt lediglich deine Eingabe in einen RPC-Aufruf wie getrawtransaction, formatiert die zurückgelieferten, eher technisch-kryptischen Rohdaten (Hex-codierte Werte, Zeitstempel als reine Zahl) in etwas für Menschen Lesbares und zeigt es dir hübsch aufbereitet an. Der komplette "Blockexplorer" ist im Kern also nichts anderes als eine sehr gut gemachte Präsentationsschicht über genau der Schnittstelle, die dieser Beitrag beschreibt; jeder könnte sich mit ein paar Zeilen eigenem Code seinen eigenen, privaten Blockexplorer bauen, ganz ohne fremden Servern vertrauen zu müssen.
Push statt Pull: die ZMQ-Schnittstelle
RPC-Aufrufe haben einen kleinen strukturellen Nachteil: Sie funktionieren nach dem Prinzip "frag nach, dann bekommst du eine Antwort": eine Anwendung, die z.B. sofort informiert werden möchte, sobald ein neuer Block eintrifft, müsste sonst ständig wiederholt nachfragen ("ist jetzt ein neuer Block da? und jetzt?"). Dafür bietet Bitcoin Core zusätzlich eine zweite, ergänzende Schnittstelle an, basierend auf der weit verbreiteten Nachrichten-Technologie ZeroMQ (src/zmq/). Ein Node kann darüber von sich aus, ganz ohne vorherige Anfrage, Benachrichtigungen verschicken, sobald bestimmte Ereignisse eintreten, im Code als eigene Themenkanäle (Topics) definiert: hashblock und rawblock für neue Blöcke, hashtx und rawtx für neue Transaktionen, sowie sequence für sämtliche Mempool-Änderungen. Anwendungen, die auf aktuelle Daten angewiesen sind (etwa Zahlungsdienstleister, die sofort merken müssen, wenn eine erwartete Zahlung eintrifft), abonnieren einfach den passenden Kanal, statt den Node ständig mit Anfragen zu bombardieren.
Eine dritte Tür: die einfache REST-Schnittstelle
Neben JSON-RPC und der gerade beschriebenen ZMQ-Benachrichtigung bietet Bitcoin Core noch eine dritte, bewusst simple Zugriffsart: eine klassische REST-Schnittstelle (src/rest.cpp), wie sie auch unzählige gewöhnliche Webseiten für einfache Datenabfragen nutzen. Statt eines strukturierten RPC-Aufrufs reicht hier eine ganz normale Web-Adresse, um Informationen abzurufen: etwa /rest/tx/ für eine einzelne Transaktion, /rest/block/ für einen kompletten Block, /rest/chaininfo für den aktuellen Kettenstatus, /rest/mempool/ für den aktuellen Mempool-Inhalt (siehe Teil 4) oder /rest/getutxos für eine gezielte Abfrage des UTXO-Satzes. Der große Vorteil: Diese Endpunkte lassen sich buchstäblich mit einem gewöhnlichen Webbrowser oder einem simplen Kommandozeilen-Werkzeug abrufen, ganz ohne dass eine Anwendung überhaupt das strukturiertere JSON-RPC-Format beherrschen müsste, ideal für schnelle, einmalige Abfragen oder sehr einfache Integrationen, bei denen sich der Aufwand für eine vollwertige RPC-Anbindung nicht lohnt.
Bewusst kein offenes Tor
Weil ein RPC-Zugriff bei aktivierter Wallet im schlimmsten Fall vollen Zugriff auf dein Bitcoin-Guthaben ermöglichen kann (inklusive des Befehls, es zu versenden), ist der Zugang standardmäßig strikt eingeschränkt: nur von der eigenen Maschine aus erreichbar (localhost) und nur mit gültiger Authentifizierung, entweder über eine automatisch generierte Cookie-Datei oder ein selbst konfiguriertes Passwort. Wer diese Schnittstelle über das eigene Netzwerk hinaus öffnen möchte (etwa um von einem anderen Rechner im Heimnetz aus zuzugreifen), sollte das ausschließlich über einen verschlüsselten, zusätzlich abgesicherten Kanal tun (z.B. ein VPN oder einen SSH-Tunnel) und sich der Tragweite bewusst sein: Ein offener, unzureichend geschützter RPC-Port im offenen Internet ist der digitale Generalschlüssel zum eigenen Node und wird in der Praxis aktiv von automatisierten Scannern gesucht.
Mehrere Fragen auf einmal: Batch-Anfragen
Wer viele einzelne Informationen abfragen möchte (etwa ein Zahlungsdienstleister, der den Status von hundert verschiedenen, gerade erwarteten Zahlungen gleichzeitig prüfen will), müsste bei einer einzelnen Anfrage pro Frage sehr viele einzelne Netzwerk-Umläufe zwischen Anwendung und Node in Kauf nehmen. Das JSON-RPC-Format, das Bitcoin Core nutzt, erlaubt deshalb sogenannte Batch-Anfragen: mehrere einzelne Befehle werden gemeinsam in einer einzigen Anfrage verschickt, der Node arbeitet sie intern nacheinander ab und schickt alle Antworten gebündelt in einer einzigen Rückmeldung zurück. Das reduziert den Netzwerk-Overhead erheblich und ist einer der Gründe, warum selbst datenintensive Anwendungen wie große Blockexplorer-Plattformen (siehe weiter oben) mit vergleichsweise überschaubarem technischem Aufwand betrieben werden können.
Ein Aufruf zum Anfassen
Um das Ganze etwas greifbarer zu machen: Wer selbst einen Bitcoin-Node betreibt, kann direkt in der Kommandozeile eintippen:
bitcoin-cli getblockchaininfo
Die Antwort kommt als strukturierter Datensatz zurück, der unter anderem den Namen der Chain (main für das echte Netzwerk), die aktuelle Blockhöhe, den Hash des neuesten Blocks und die aktuelle Schwierigkeit enthält, exakt dieselben Werte, die auch jede Wallet-App und jeder Blockexplorer im Hintergrund abfragt, nur eben roh und unformatiert. Genau dieser eine Befehl ist oft der erste Kontakt, den technisch interessierte Nutzer mit ihrem eigenen Node haben, und zugleich der einfachste Weg, sich selbst zu beweisen, dass der eigene Node tatsächlich läuft und synchronisiert ist, statt das nur einer App zu glauben.
Fazit: Die unauffällige Basis von fast allem, was du als Nutzer siehst
Egal ob Blockexplorer-Webseite, mobile Wallet-App oder ein Zahlungs-Backend eines Unternehmens: Fast überall, wo Software mit dem Bitcoin-Netzwerk interagiert, steckt am Ende ein Aufruf genau dieser JSON-RPC-Schnittstelle dahinter, meist so gut versteckt, dass die wenigsten Nutzer je davon erfahren.
Weiter geht's mit Teil 8: Das Gedächtnis der Blockchain, wie Nodes zusätzliche Register führen, um bestimmte Fragen blitzschnell zu beantworten.