BLOG |

Anleitungen

Fallstudie: Ein echter einseitiger „Spark“-Exit im Bitcoin-Mainnet

Wiederherstellung von 100.000 Sats mithilfe von Seed- und Status-Backups.

Fallstudie: Ein echter einseitiger „Spark“-Exit im Bitcoin-Mainnet
13. Juli 2026
openoms

Ein echter einseitiger Austritt aus dem Spark-Netzwerk: die Zahlen, die Misserfolge und die Lehren. Alles, was im Folgenden beschrieben wird, fand im Bitcoin-Mainnet statt und ist öffentlich in der Blockchain nachprüfbar.

Ich habe eine nicht-verwahrende Blink (unter Verwendung von Spark) im Bitcoin-Mainnet zwangsweise geschlossen. Alles, was für den Ausstieg erforderlich war, wurde aus dem Wallet-Seed abgeleitet: die Bereitstellung der Gebühren, die Signierung der Transaktion und der abschließende Abzug. Die einzige zusätzliche Komponente ist ein Wiederherstellungsbündel – ein Snapshot der Ausstiegsdaten der Wallet, der gespeichert wurde, als das Spark-Netzwerk noch erreichbar war. Mit diesem Bündel in der Hand erforderte der Ausstieg selbst keinerlei Zusammenarbeit von irgendjemandem.

Die realistischen Zahlen für eine Wallet mit 100.000 Sat:

  • 22 Abgänge, 253 Transaktionspakete bis zum vollständigen Ausstieg
  • Nur 4 „Leaves“ (90 % des Wertes) waren es wert, verkauft zu werden. Die Gebühren hätten die restlichen 18 aufgezehrt.
  • ~9,4k Sats an Gebühren, um 90,1k zurückzuerhalten, ein Paket pro Block pro Kette (eine v3/TRUC-Mempool-Regel, die weiter unten erläutert wird), anschließend eine Timelock-Wartezeit von etwa 10 Tagen

„Ohne Freiheitsentzug“ bedeutet, dass man jederzeit gehen kann. Aber die Feuerleiter ist schmal. Hier ist die ganze Geschichte – mit Kosten, Misserfolgen und Lehren.

Warum wir das getan haben

„Non-custodial“ ist ein Begriff, der sich leicht in Marketingtexte einbauen lässt. Wir wollten jedoch, dass man dies überprüfen kann und nicht einfach nur glauben muss. Also haben wir eine echte Blink genommen, so getan, als wäre das Spark-Netzwerk verschwunden, und jedes wiederherstellbare Satoshi mithilfe von nichts anderem als dem Seed, einem gespeicherten Wiederherstellungsbundle und Open-Source-Tools, die jeder ausführen kann, zurück auf die Bitcoin-Blockchain übertragen. Dieser Beitrag ist der Nachweis dafür.

Die Geldbörse

Eine mobile Spark-Wallet mit 100.000 Sats, verteilt auf 22 „Leaves“.

(zur Veranschaulichung)

‍‍EinkurzerÜberblick für Leser, die Spark noch nicht kennen: Die Guthaben einer Spark-Wallet befinden sich in einem gemeinsamen On-Chain-Baum, der von einer Gruppe von Betreibern verwaltet wird, und jedes Blatt dieses Baums ist ein eigenständiger Teil des Guthabens der Wallet mit einem eigenen, vorab signierten Pfad zurück zu Bitcoin. Ein einseitiger Ausstieg bedeutet, diesen Pfad – die Ausstiegskette des Blatts aus On-Chain-Transaktionen, die Ebene für Ebene entlang des Baums bestätigt wird – zu übertragen, um das Blatt ohne die Mitwirkung der Betreiber auf Bitcoin zu zwingen.

Eine mobile Spark-Wallet mit 100.000 Sats, verteilt auf 22 Blätter. Spark-Wallets sammeln Blätter durch normale Nutzung an (Zahlungen teilen und teilen den Baum erneut auf), und jedes Blatt verfügt über eine eigene Ausstiegskette: die On-Chain-Transaktionen, die Ebene für Ebene bestätigt werden müssen, um das Blatt ohne Mitwirkung der Betreiber auf Bitcoin zu zwingen. Für diese Wallet bedeutete das 253 Transaktionspakete über die 22 Ketten hinweg. Für 100.000 Sats.

Schritt 1: Das Wiederherstellungs-Bundle auf dem neuesten Stand halten

Eine Wiederherstellung allein anhand des Seeds ist nicht möglich, sobald die Spark-Operatoren offline sind: Aktuelle Leaf-Transaktionen lassen sich nicht allein anhand des Seeds ermitteln. Für den Ausstieg ist ein Wiederherstellungsbundle erforderlich – ein JSON-Snapshot der Leaf-Transaktionen der Wallet und ihrer Vorgängotransaktionen –, der aktualisiert werden muss, solange die Operatoren noch online sind:

make refresh-recovery-bundle SEED_FILE=../.spark-seed.txt BUNDLE=../recovery-bundle.json

Erste Lektion aus der Praxis: Unser erstes Bundle war unbemerkt unvollständig. Die Massen von Betreibern query_nodes(include_parents=true) Die API lässt den Stammknoten bei älteren Mainnet-Bäumen weg, sodass jede der 22 Exit-Chains oben eine Lücke aufwies und die Erstellung des Offline-Pakets mit folgendem Fehler fehlschlug: Die Exit-Kette ist unvollständig. Das erneute Abrufen fehlender Vorfahren anhand der Knoten-ID (wodurch das Überspringen der Wurzel umgangen wird) hat das Problem behoben – der Exporter führt dies nun automatisch durch und weigert sich, ein Bundle mit offenen Ketten zu schreiben.

Überprüfen Sie die Vorläuferketten Ihres Bundles, bevor Sie sie benötigen; ein unvollständiges Bundle, das erst während eines Ausfalls entdeckt wird, lässt sich nicht mehr wiederherstellen.

Schritt 2: Finanzierung der Gebühren aus demselben Startkapital

Ausgangstransaktionen werden gebührenfrei vorab signiert und die Gebühren werden über kurzlebige CPFP-Anker bezahlt; daher benötigt der Ausgang ein unabhängiges L1-Bitcoin-UTXO, um Gebührenerhöhungen zu finanzieren. Das Tool leitet eine spezielle Finanzierungsadresse aus dem Wallet-Seed selbst ab (Pfad m/8797556'/<account>/0: Nur der Zweck-Index ist gehärtet, der Konto- und der Adress-Index hingegen nicht; daher kann eine „Watch-Only“-Wallet die Einzahlungsadresse aus einem XPUB ableiten und überwachen, ohne dass ein privater Schlüssel erforderlich ist):

make cpfp-address SEED_FILE=../.spark-seed.txt BUNDLE=../recovery-bundle.json FEE_RATE=1

Bei 1 sat/vB waren dafür 78.573 Sats erforderlich, um alle 22 Zweige zu verlassen. Fast 79 % des Wallet-Guthabens gingen als Gebühren drauf. Wir haben den Betrag 3ab20a4c…7262 eingezahlt, bevor wir die Berechnung pro Zweig durchgeführt haben. Mehr dazu weiter unten.

Schritt 3: Die naive Rundsendung und warum sie fehlschlug

Beim ersten Versuch wurden alle 253 Pakete nacheinander über den POST-Endpunkt /txs/package von Esplora gepackt, signiert und übermittelt. Das erste Paket wurde bestätigt (Eltern-ID 16895bc8…9619, CPFP-Kind-ID 384cdc6d…3b37). Die übrigen 252 wurden abgelehnt:

"error": "TRUC-Verstoß, Transaktion 16895bc8… würde das Limit für die Anzahl der Nachkommen überschreiten"

"error": "bad-txns-inputs-missingorspent"

Spark-Exit-Transaktionen sind vom Typ v3, auch TRUC (Topologically Restricted Until Confirmation, BIP 431) genannt. Die Mempool-Richtlinie begrenzt einen v3-Cluster auf einen unbestätigten übergeordneten Block plus einen untergeordneten Block. Dadurch lassen sich die vorab signierten, gebührenfreien Exit-Transaktionen sicher durch Gebührenerhöhungen in den Mempool bringen, und es bedeutet auch, dass jede Ebene einer Exit-Kette bestätigt werden muss, bevor die nächste Ebene in den Mempool gelangen kann. Eine Kette mit 15 Paketen benötigt mindestens 15 Blöcke, unabhängig davon, wie sie eingereicht wird. Jedes Tool, das Pakete direkt nacheinander sendet, lässt alles nach dem ersten Paket pro Kette zurückbleiben.

Schritt 4: Beende nur das, was es wert ist, beendet zu werden

Bevor wir die Schleife automatisiert haben, haben wir jedes Blatt bewertet: die CPFP-Gebühren für die jeweilige Kette zuzüglich des abschließenden Sweeps von ca. 111 vB, gemessen am Wert des Blattes. Das Ergebnis für diese echte Wallet bei 1 sat/vB:

BlätterWertAusstiegskosten
Wirtschaftlich490.112 Sats8.388 Sats
Unwirtschaftlich (Staub)189.888 Sats~69.000 Sats

Vier Blätter (32.768 + 32.768 + 16.384 + 8.192 Sats) machten 90 % des Guthabens aus. Die übrigen 18 – Restbeträge aus routinemäßigen Wallet-Aktivitäten, von denen einige nur 1 Sat betrugen – hätten jeweils 2.100–4.600 Sats gekostet, um sie abzuheben: Die Abhebung aller Beträge hätte ~77,5k Sats an Gebühren gekostet, um 100k zurückzugewinnen. Das Tool berechnet dies nun pro Blatt und überspringt unwirtschaftliche Blätter standardmäßig. (INCLUDE_UNECONOMICAL=1 hebt dies auf; die wirtschaftliche Berechnung wurde anhand genau dieses Bündels regressionsgetestet und an den Regtest angepasst).

Was kommt also am Zielort an?

Verfolgung jedes einzelnen Sats der 100.000-Sat-Wallet über den wirtschaftlichen Ausstieg bei 1 Sat/vB. Dabei sind zwei Geldbeträge im Spiel: das Wallet-Guthaben selbst und die 9.388 Sats an Gebühren, die den wirtschaftlichen Ausstieg finanzieren und tatsächlich von der Finanzierungsadresse verbraucht wurden.

Die 100.000 Sats in der Wallet:

sats
4 günstige Flüge, Stornierung von Kettenbuchungen + Rückerstattungen bestätigt90,112
− Sweep-Gebühren (4 × ~111 vB × 1 sat/vB)−444
kommt an der Zieladresse an89,668
Staub in 18 unwirtschaftlichen Blättern, die in Spark zurückgelassen wurden9,888

Spark-Exit- und Rückerstattungstransaktionen werden vorab ohne Gebühr signiert (die Gebühren richten sich nach den CPFP-Ankern), sodass jede Rückerstattungsausgabe den vollen Leaf-Wert enthält; der einzige Abzug vom Wallet-Guthaben selbst ist die abschließende Sweep-Gebühr.

Die 9.388 Sats aus der Gebührenfinanzierung wurden entnommen aus:

sats
Anstieg der CPFP-Gebühren bei den vier Ausstiegsketten8,388
Sicherheitspuffer, wird als Wechselgeld an die Einzahlungsadresse zurückerstattet~1,000

Fazit: 89.668 von 100.000 Sats (~90 %) erreichen das Ziel. Die Gesamtkosten für den Ausstieg betragen ~18.700 Sats – 9.888 gehen als „Dust“ verloren, 8.388 entfallen auf CPFP-Gebühren, 444 auf Sweep-Gebühren – zuzüglich der On-Chain-Gebühr für die Transaktion, mit der die CPFP-Adresse ursprünglich aufgefüllt wurde. Bei höheren Gebührensätzen skalieren alle Werte nach oben, und mehr „Leaves“ fallen unter die wirtschaftliche Schwelle; bei 10 sat/vB würde diese Wallet zwei weitere „Leaves“ aufgeben und für die restlichen das Zehnfache an Gebühren zahlen.

Schritt 5: Die automatisierte „Bestätigen und Weiter“-Schleife

Der überarbeitete Ablauf besteht aus einem einzigen Befehl:

make recover SEED_FILE=../.spark-seed.txt BUNDLE=../recovery-bundle.json NETWORK=mainnet FEE_RATE=1

In jeder Runde werden Pakete anhand des aktuellen Kettenzustands neu erstellt, der CPFP-Bump mit dem Seed signiert, ein Paket pro Leaf-Chain übermittelt, auf die Bestätigung gewartet und der Vorgang wiederholt. Bereits bestätigte Transaktionen werden bei der Neuerstellung übersprungen, sodass die Schleife zustandslos ist: Ratenbeschränkungen, Abstürze und Neustarts haben keine Auswirkungen – nach einem Neustart wird der Vorgang einfach fortgesetzt. Bei Esplora-Störungen wird mit exponentiellem Backoff ein erneuter Versuch unternommen, anstatt eine stundenlange Wartezeit abzubrechen.

Zwei strukturelle Details sind von Bedeutung:

  1. Rückerstattungstransaktionen werden zurückgestellt und nicht gesendet. Die letzte Transaktion jeder Kette (die Rückerstattung, die das Blatt tatsächlich an den Schlüssel des Benutzers übergibt) enthält eine CSV-Zeitverriegelung: etwa 2.000 Blöcke (ungefähr zwei Wochen) für neue Blätter; die erneuerten Blätter dieser Wallet enthielten 1.400 Blöcke (etwa 10 Tage). Die Schleife entschlüsselt die Sperre jeder Rückerstattung, meldet deren Fälligkeitshöhe und stoppt, sobald nur noch zeitgesperrte Rückerstattungen übrig sind. Da Rückerstattungen niemals vorzeitig gesendet werden, wird die Gebührenfondsänderung niemals von einer zeitgesperrten Transaktion erfasst, und die Blätter werden nacheinander über ein einziges Finanzierungs-UTXO ohne Deadlock abgezogen.
  2. Parallelität ist optional. Im Fan-Out-Modus wird die Finanzierung zunächst auf jeweils ein UTXO pro Blatt aufgeteilt, woraufhin jede Blattkette jeden Block vorantreibt, anstatt sich abzuwechseln. Für diese Wallet hätte dies die Übertragungsphase von etwa 4 Stunden auf etwa 70 Minuten verkürzt, bei zusätzlichen Kosten von etwa 200 Sats. Der Gewinn skaliert mit der Anzahl der Blätter; bei einer Handvoll Blättern war die sequenzielle Abwicklung schnell genug.

Welcher Fan-Out hätte hier etwas geändert?

Wir haben diese Wiederherstellung sequenziell durchgeführt (Standardeinstellung). Bei FAN_OUT=1 hätte die Schleife zunächst eine zusätzliche Transaktion mit vier Ausgängen gesendet – die 9.388 Sats der Mittel würden auf je ein UTXO pro wirtschaftlichem Blatt aufgeteilt, wobei jedes UTXO so bemessen wäre, dass es die verbleibenden CPFP-Gebühren dieses Blattes sowie einen Puffer von 1.000 Sats abdeckt, wobei der letzte Ausgang den Rest aufnimmt. Eine P2WPKH-Transaktion mit 1 Input und 4 Outputs beträgt ~203 vB, also ~203 Sats bei 1 Sat/vB.

Von da an verlaufen vier Ketten parallel – eine pro Blatt. Jede Blattkette bildet einen eigenen TRUC-Cluster, sodass alle vier Pakete einer Runde unabhängig voneinander sind und im selben Block bestätigt werden können. Jedes der vier Blätter dieser Wallet wies vor der Rückerstattung eine Kette mit etwa sechs Paketen auf:

Blöcke, bis die Zeitverriegelung abläuftca. 10 Min./Block
Sequenziell (Standard)4 Blätter × ~6 Packungen ≈ 24 Blöcke~4 Stunden
FAN_OUT=11 (Fan-Out) + ~6 (tiefste Kette) ≈ 7 Blöcke~70 Minuten

Etwa eine 3,5-fache Steigerung der Realisierungszeit für ~203 Sats, und nach Ablauf der Rückerstattungsfrist wiederholt sich das gleiche Muster: Die vier Rückerstattungspakete werden in einem Block mit UTXOs pro Blatt gesendet, anstatt in vier aufeinanderfolgenden Blöcken. Der Gewinn skaliert mit der Blattanzahl (Summe der Kettentiefen im Vergleich zur tiefsten einzelnen Kette), sodass eine Wallet mit Dutzenden wirtschaftlicher Blätter immer auf mehrere Blöcke verteilt werden sollte; bei einer Handvoll Blättern ist die sequenzielle Vorgehensweise einfacher und war hier schnell genug.

Schritt 6: Zeitsperren, dann durchgehen

Nachdem die Schleife beendet ist, wartet die Rückerstattung für jedes „economical leaf“ ab, bis die CSV-Sperrfrist abgelaufen ist. Eine erneute Ausführung derselben wiederherstellen Nach Ablauf der Frist werden die Rückerstattungen bekannt gegeben; sobald diese bestätigt sind, einen Durchlauf durchführen erstellt und signiert Taproot-Key-Path-Ausgaben mit einem Eingang von den Rückerstattungs-Outputs an beliebige Zieladressen und sendet diese als gewöhnliche Transaktionen. Zum Zeitpunkt der Erstellung dieses Artikels erfolgen die vier wirtschaftlichen Ausgänge dieser Wallet über ihre jeweiligen Blockchains und warten auf die Fälligkeit der Rückerstattung.

Das Vertrauensmodell, einfach erklärt

Da lohnt es sich, genau zu sein, denn hier eilen die Marketingfloskeln den Fakten meist voraus:

  • Die Betreiber können Ihr Guthaben niemals ausgeben. Jedes „Blatt“ ist an eine Kombination aus Ihrem und ihrem Schlüssel gebunden; für jede Transaktion ist Ihre Signatur erforderlich. Ein Diebstahl würde erfordern, dass sich alle Betreiber zusammentun. Ein einziger ehrlicher Betreiber macht dies unmöglich, selbst wenn er offline ist: Für einen Diebstahl ist seine aktive Signatur erforderlich, nicht seine Verfügbarkeit. Wenn Betreiber offline gehen, handelt es sich um eine ganz andere Art von Ausfall. Es wird nichts entwendet, der kooperative Pfad friert ein, und der Ausweg darunter ist die Lösung dafür.
  • Der Ausstieg benötigt Daten – einmal pro Zustandsänderung. Das Wiederherstellungs-Bundle muss abgerufen werden, solange die Betreiber online sind, und es erfordert nicht mehr Berechtigungen als die Transaktion selbst: Wann immer Sie Zeit dafür haben, können Sie es aktualisieren. Alles, was von Ihrer letzten Aktualisierung abgedeckt wurde, bleibt für immer ausstiegsfähig, und ein Zurückhalten ist sofort erkennbar (Ihre Aktualisierung schlägt fehl, während Ihre Zahlungen erfolgreich sind).
  • Der Ausstieg selbst erfolgt ohne Genehmigung. Bei einem gespeicherten Bundle erfordern das Packen, Signieren, Senden und Sweepen keinerlei Maßnahmen seitens der Betreiber. Das ist der Teil, den diese Wiederherstellung im Mainnet bewiesen hat.

Nicht vertrauenslos, und wir behaupten auch nicht, dass es das ist. Auf einer Skala betrachtet: schwächer als ein Lightning , der von Natur aus seinen eigenen Kanalstatus verwaltet, aber deutlich sicherer als ein Verwahrer, der sowohl Ihre Schlüssel als auch Ihre Daten verwahrt und dessen Zurückhaltung bis zum Einfrieren der Auszahlungen wie ein normaler Service erscheint.

Das Wichtigste auf einen Blick

  • Ein einseitiger Ausstieg ist ein Notausgang, keine Tür. 253 Pakete, ein Block pro Paket pro Blockchain, eine in Wochen gemessene Zeitbeschränkung und Gebühren, die bei einer wahllosen Anwendung 79 % des Guthabens eines Wallets mit 100.000 Sats aufgezehrt hätten. Dank wirtschaftlicher Triage erreichten etwa 90 % des Guthabens ihr Ziel. Die Selbstverwahrung auf Spark ist real, aber der Ausstiegspfad ist konstruktionsbedingt teuer und langsam; passen Sie Ihre Erwartungen hinsichtlich der Größe entsprechend an.
  • Staubblätter stellen ein Risiko dar.18 von 22 Blättern waren selbst bei 1 sat/vB nicht wert, abgezogen zu werden. Seit dieser Wiederherstellung fasst das Tool die Blätter vor dem Abzug zu abzugsoptimierten Einheiten zusammen (durch kooperative Tauschvorgänge, solange die Betreiber erreichbar sind), sodass bei zukünftigen Wiederherstellungen weitaus weniger aufgegeben wird.
  • Bei dem Bundle kommt es vor allem auf Aktualität und Vollständigkeit an. Ohne ein vollständiges, aktuelles Wiederherstellungs-Bundle gibt es nichts, was man beenden könnte. Das Tool aktualisiert es derzeit bei jedem Durchlauf, sobald sich die Gelegenheit ergibt; der nächste Schritt ist die Integration einer automatischen Aktualisierung in die Blink .
  • Respekt, TRUC. Pro Kette ein unbestätigtes Eltern-Kind-Paar. Die Ausgabevorrichtung muss bestätigen und fortfahren sowie tolerieren TRUC-Verstoß und fehlende Eingaben wie normale Sequenzierungssignale und behandeln Sie eine Paketcharge niemals nach dem Prinzip „Fire-and-Forget“.
  • Alles basiert auf dem Seed. Bei der Bundle-Aktualisierung, der Gebührenzuführung, der CPFP-Unterzeichnung und dem abschließenden Sweep wurde jeweils der vorhandene Seed der Wallet verwendet – es müssen keine separaten Schlüssel gesichert werden, und die Zuführungsadresse lässt sich über eine xpub nur zur Beobachtung einsehen.

Ausblick: Die in die App integrierte Ausstiegsfunktion

All das wurde bisher manuell mit Open-Source-Tools durchgeführt. Das ist zwar der richtige Ort, um dies unter Beweis zu stellen, aber nicht der, an dem sich die meisten Nutzer aufhalten. Unser Ziel ist es, einen Ausstiegspfad zu schaffen, auf den sich ein Nutzer niemals vorbereiten muss.

Konkret bedeutet dies: Die Blink aktualisiert das Wiederherstellungs-Bundle nach jeder Zustandsänderung – also nach jeder Transaktion – automatisch und speichert es dauerhaft im lokalen Gerätespeicher sowie, sofern der Nutzer dies konfiguriert hat, verschlüsselt in seinem eigenen Cloud-Speicher. Das Bundle beinhaltet keine Ausgabebefugnis; es handelt sich um Ausstiegsdaten, nicht um Schlüssel, sodass die automatische Sicherung das Ausstiegsfenster erweitert, ohne die Angriffsfläche zu vergrößern. Der Seed bleibt das einzige Geheimnis, das es zu schützen gilt – genau wie heute.

Der springende Punkt ist, dass „man jederzeit aussteigen kann“ keine Vorbereitungen erfordern sollte. Unabhängig davon, wie die letzte Transaktion aussah, sind die Daten, die erforderlich sind, um diese Gelder zurück auf Bitcoin zu übertragen, bereits gespeichert. Sollte Spark nicht erreichbar sein, wird der Ausstieg über die Blink oder über das Open-Source-Tool anhand desselben Bundles durchgeführt – es entsteht kein hektisches Hin und Her, um den Status von Betreibern abzurufen, die möglicherweise bereits nicht mehr erreichbar sind.

Damit wird die Lücke geschlossen, die diese Fallstudie aufgezeigt hat: Die Tools können zwar beendet werden, jedoch nur im Vergleich zu einem vollständigen, aktuellen Bundle. Die Automatisierung der Aktualisierung, sodass diese stets auf dem neuesten Stand ist und stets gesichert wird, verwandelt eine Notausstiegsmöglichkeit, die man erst aufbauen muss, in eine, die einfach schon da ist.

‍Allehier verwendeten Tools sind Open Source, und die technische Fallstudie mit allen Befehlen und Transaktions-IDs befindet sich direkt neben dem Code:

Probier es doch mal mit dem Bundle deiner eigenen Wallet aus, bevor du es brauchst. Darum geht es ja.

Fanden Sie dies nützlich? Geben Sie dem Autor einen Tipp!

Fanden Sie dies nützlich? Geben Sie dem Autor einen Tipp!

Social-Share-Komponente

Blink herunterladen

Empfangen und senden Sie jetzt Bitcoin

Community