BLOG |

Nasıl yapılır

Vaka çalışması: Bitcoin ana ağında gerçekleşen gerçek bir Spark tek taraflı çıkışı

Tohum ve durum yedekleriyle 100 bin sat geri kazanma.

Vaka çalışması: Bitcoin ana ağında gerçekleşen gerçek bir Spark tek taraflı çıkışı
13 Temmuz 2026
openoms

Spark ağından gerçek anlamda tek taraflı bir çıkış: rakamlar, başarısızlıklar ve çıkarılan dersler. Aşağıda anlatılan her şey Bitcoin ana ağında gerçekleşmiştir ve zincir üzerinde herkes tarafından doğrulanabilir.

Bitcoin ana ağında (Spark kullanarak) bir non-custodial Blink cüzdanından zorla çıkış yaptım. Çıkış işlemi için gereken her şey cüzdan tohumundan türetildi: ücret finansmanı, işlem imzalaması ve son temizleme. Tek ek unsur ise bir kurtarma paketi; bu, Spark ağına hâlâ erişilebilirken kaydedilen cüzdanın çıkış verilerinin bir anlık görüntüsüdür. Bu paket elimdeyken, çıkış işlemi için kimsenin işbirliğine gerek kalmadı.

100.000 sat'lık bir cüzdanın gerçek rakamları:

  • Tamamen çıkmak için 22 yaprak, 253 işlem paketi
  • Sadece 4 yaprak (değerin %90’u) satmaya değerdi. Komisyonlar geri kalan 18’i eritirdi.
  • 90,1k’yı geri almak için yaklaşık 9,4k sat’lık ücret, her blokta her zincir için bir paket (aşağıda açıklanan bir v3/TRUC mempool kuralı), ardından yaklaşık 10 günlük bir zaman kilidi bekleme süresi

“Gözaltında tutulmama” durumu, istediğiniz zaman ayrılabileceğiniz anlamına gelir. Ancak yangın merdiveni dardır. İşte maliyetleri, başarısızlıkları ve çıkarılan dersleri içeren hikayenin tamamı.

Bunu neden yaptık?

"Saklama hizmeti sunmayan" ifadesi, pazarlama metinlerine kolayca eklenebilen bir terimdir. Biz bunun, size inanmanızın istendiği bir şey değil, doğrulayabileceğiniz bir şey olmasını istedik. Bu nedenle gerçek bir Blink cüzdanını aldık, Spark ağının ortadan kaybolduğunu varsaydık ve yalnızca tohum anahtarı, kaydedilmiş kurtarma paketi ve herkesin kullanabileceği açık kaynaklı araçları kullanarak kurtarılabilir tüm sat'ları Bitcoin blok zincirine geri aktardık. Bu yazı, bunun kanıtıdır.

Cüzdan

22 yaprağa dağılmış 100.000 sat'ı barındıran bir mobil Spark cüzdanı.

(örnek)

‍‍Spark’ı ilk kez duyan okuyucular içinkısa biraçıklama: Bir Spark cüzdanındaki varlıklar, bir grup operatör tarafından yönetilen paylaşımlı bir zincir üstü ağaçta bulunur ve bu ağacın her bir yaprağı, cüzdan bakiyesinin ayrı bir parçasıdır ve Bitcoin’e geri dönen kendine özgü önceden imzalanmış bir yola sahiptir. Tek taraflı çıkış, bu yolu — yani yaprağın zincir üstü işlemlerden oluşan çıkış zincirini, ağacın aşağısına doğru seviye seviye onaylayarak — yayınlamak ve operatörlerin işbirliği olmadan yaprağı Bitcoin’e zorla aktarmak anlamına gelir.

22 yaprağa yayılmış 100.000 sat'lık bir mobil Spark cüzdanı. Spark cüzdanları normal kullanım yoluyla yaprak biriktirir (ödemeler ağacı böler ve yeniden böler) ve her yaprak kendi çıkış zincirini taşır: operatörün işbirliği olmadan yaprağı Bitcoin'e zorlamak için seviye seviye onaylanması gereken zincir üzerindeki işlemler. Bu cüzdan için bu, 22 zincir boyunca 253 işlem paketi anlamına geliyordu. 100 bin satoshi için.

1. Adım: Kurtarma paketini güncel tutun

Spark operatörleri çevrimdışı hale geldiğinde yalnızca tohum kullanılarak kurtarma işlemi mümkün değildir: mevcut yapraklar yalnızca tohumdan tespit edilemez. Çıkış işlemi için, operatörler hâlâ çevrimiçi iken güncellenen bir kurtarma paketi — cüzdanın yapraklarının ve bunların atası olan işlemlerin bir JSON anlık görüntüsü — gereklidir:

refresh-recovery-bundle komutunu SEED_FILE=../.spark-seed.txt ve BUNDLE=../recovery-bundle.json değerleriyle çalıştır

İlk pratik ders: İlk paketimiz fark edilmeden eksik çıkmıştı. Operatörlerin toplu query_nodes(include_parents=true) API, eski ana ağ ağaçlarında kök düğümünü atladığından, 22 çıkış zincirinin her birinde en üstte bir boşluk oluştu ve çevrimdışı paket oluşturma işlemi şu hatayla başarısız oldu: Çıkış zinciri eksik. Eksik ataları düğüm kimliği kullanılarak yeniden getirme (bu işlem kök atlamasını devre dışı bırakır) sorunu çözdü — dışa aktarıcı artık bunu otomatik olarak yapıyor ve açık zincirleri içeren bir paketi kaydetmeyi reddediyor.

Paketinizin üst zincirlerini, bunlara ihtiyaç duyduğunuzdan önce doğrulayın; bir kesinti sırasında tespit edilen eksik bir paket kurtarılamaz.

2. Adım: Aynı tohumdan ücret finansmanı

Çıkış işlemleri sıfır ücretle önceden imzalanır ve ücretler CPFP geçici bağlantı noktaları aracılığıyla ödenir; bu nedenle çıkış işlemi, ücret artışlarını karşılamak için bağımsız bir L1 Bitcoin UTXO’suna ihtiyaç duyar. Araç, cüzdan tohumundan özel bir fonlama adresi türetir (yol m/8797556'/<account>/0: Yalnızca amaç dizini şifrelenmiştir; hesap ve adres dizinleri şifrelenmemiştir; bu nedenle, salt izleme amaçlı bir cüzdan, herhangi bir özel anahtar kullanmadan bir xpub’dan fon aktarım adresini türetip izleyebilir):

cpfp-address komutunu şu şekilde çalıştırın: SEED_FILE=../.spark-seed.txt BUNDLE=../recovery-bundle.json FEE_RATE=1

1 sat/vB oranında, 22 yaprağın tamamından çıkmak için 78.573 sat gerekiyordu. Cüzdan bakiyesinin neredeyse %79’u ücret olarak harcanacaktı. Yaprak başına hesaplamayı yapmadan önce 3ab20a4c…7262 adres ine fon aktardık. Bu konuyla ilgili daha fazla bilgi aşağıda yer almaktadır.

3. Adım: Basit yayın yöntemi ve neden başarısız olduğu

İlk denemede, 253 paketin tamamı arka arkaya Esplora’nın POST /txs/package arayüzü üzerinden paketlenip imzalandı ve gönderildi. İlk paket onaylandı (ana paket 16895bc8…9619, CPFP alt paketi 384cdc6d…3b37). Diğer 252 paket ise reddedildi:

"hata": "TRUC ihlali, tx 16895bc8… alt düzeydeki öğe sayısı sınırını aşacak"

"hata": "geçersiz işlem girişleri (eksik veya harcanmış)"

Spark çıkış işlemleri v3 standardındadır ve TRUC (Topologically Restricted Until Confirmation, BIP 431) olarak da adlandırılır. Mempool politikası, bir v3 kümesini bir adet onaylanmamış ana işlem artı bir adet alt işlem ile sınırlandırır. Bu, önceden imzalanmış sıfır ücretli çıkış işlemlerinin güvenli bir şekilde ücret artışı yapılabilir olmasını sağlar ve aynı zamanda bir çıkış zincirinin her seviyesinin, bir sonraki seviyenin mempool’a girebilmesi için önce onaylanması gerektiği anlamına gelir. 15 paketlik bir zincir, nasıl gönderilirse gönderilsin en az 15 blok sürer. Paketleri arka arkaya gönderen herhangi bir araç, zincir başına ilk paketten sonraki her şeyi askıda bırakır.

4. Adım: Yalnızca çıkmaya değer olanlardan çıkın

Döngüyü otomatikleştirmeden önce, her bir yaprağın fiyatını belirledik: İlgili zincirdeki CPFP ücretleri artı son ~111 vB’lik temizleme tutarı, yaprağın değerine göre hesaplandı. 1 sat/vB oranında bu gerçek cüzdan için sonuç:

yapraklardeğerçıkış maliyeti
Ekonomik490.112 sat8.388 sat
Ekonomik olmayan (toz)189.888 sat~69.000 sat

Dört yaprak (32.768 + 32.768 + 16.384 + 8.192 sat) bakiyenin %90’ını oluşturuyordu. Diğer 18'i — rutin cüzdan faaliyetlerinden kaynaklanan tozlar, bazıları 1 sat kadar küçük — her birinin çıkışı 2.100–4.600 sat'a mal olacaktı: her şeyi çıkarmak, 100k'yı geri kazanmak için ~77,5k sat'lık ücret harcamak anlamına gelirdi. Araç artık bunu her bir yaprak için hesaplıyor ve varsayılan olarak ekonomik olmayan yaprakları atlıyor. (INCLUDE_UNECONOMICAL=1 ayarı bu ayarı geçersiz kılar; ekonomik hesaplamalar, regtest’e uyarlanmış bu paket üzerinde regresyon testine tabi tutulmuştur).

Peki, varış noktasına ne ulaşır?

100.000 sat'lık cüzdandaki her bir sat, 1 sat/vB oranındaki ekonomik çıkış yoluyla takip edilmektedir. Burada iki farklı para kaynağı söz konusudur: cüzdanın bakiyesi ve ekonomik çıkışı finanse etmek için fon adresinden fiilen harcanan 9.388 sat'lık ücret.

Cüzdandaki 100.000 sat:

sats
4 adet uygun fiyatlı bilet, çıkış zincirleri + iadeler onaylandı90,112
− tarama ücretleri (4 × ~111 vB × 1 sat/vB)−444
hedef adrese ulaşır89,668
Spark'ta geride kalan 18 adet verimsiz yapraktaki toz9,888

Spark çıkış ve geri ödeme işlemleri, sıfır ücretle önceden imzalanır (ücretler CPFP sabit noktalarına göre belirlenir); bu nedenle her geri ödeme çıkışı tam yaprak değerini taşır; cüzdan bakiyesinden yapılan tek kesinti, son toplama ücretidir.

Aşağıdakilerden çekilen 9.388 sat'lık ücret fonu:

sats
4 çıkış zincirinde CPFP ücretlerinde artışlar8,388
güvenlik tamponu, fonlama adresine para üstü olarak geri döner~1,000

Sonuç olarak: 100.000 sat'ın 89.668'i (~%90) hedef adrese ulaştı. Çıkışın toplam maliyeti ~18.700 sat'tır — 9.888'i toz olarak terk edilir, 8.388'i CPFP ücretleri, 444'ü süpürme ücretleri — artı ilk etapta CPFP adresine fon sağlayan işlem için zincir içi ücret. Ücret oranları yükseldikçe her terim ölçeklenir ve daha fazla yaprak ekonomik eşiğin altına düşer; 10 sat/vB'de bu cüzdan iki yaprak daha terk eder ve geri kalanı için on kat daha fazla ücret öder.

5. Adım: Otomatik onaylama ve devam etme döngüsü

Yeniden yazılan akış tek bir komuttan oluşur:

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

Her turda, canlı zincir durumundan paketleri yeniden oluşturur, CPFP artışını tohumla imzalar, her yaprak zinciri için bir paket gönderir, onaylanmasını bekler ve bu süreci tekrarlar. Yeniden oluşturma sırasında zaten onaylanmış işlemler atlanır, bu nedenle döngü durum bilgisi içermez: hız sınırlamaları, çökmeler ve yeniden başlatmalar hiçbir maliyete yol açmaz — yeniden çalıştırıldığında işlem devam eder. Esplora’daki aksaklıklar, saatler süren bir beklemeyi yarıda kesmek yerine, üstel geri çekilme yöntemiyle yeniden denenir.

İki yapısal ayrıntı önemlidir:

  1. Geri ödeme işlemleri ertelenir, yayınlanmaz. Her zincirin son işlemi (yaprağı kullanıcının anahtarına fiilen devreden geri ödeme), bir CSV zaman kilidi içerir: yeni yapraklar için yaklaşık 2.000 blok (kabaca iki hafta); bu cüzdanın yenilenen yaprakları ise 1.400 blok (yaklaşık 10 gün) içeriyordu. Döngü, her geri ödemenin kilidini çözer, vade yüksekliğini bildirir ve geriye sadece zaman kilidi olan geri ödemeler kaldığında durur. Geri ödemeler asla erken yayınlanmadığından, ücret fonlama değişikliği hiçbir zaman zaman kilidi olan bir işlem tarafından yakalanmaz ve yapraklar, kilitlenme olmaksızın tek bir fonlama UTXO'su üzerinden sırayla boşalır.
  2. Paralellik isteğe bağlıdır. Fan-out modunda, fonlar öncelikle her bir yaprak için bir UTXO’ya bölünür; ardından her yaprak zinciri sırayla değil, her bloğu ayrı ayrı ilerletir. Bu cüzdan için bu, yayın aşamasını yaklaşık 4 saatten yaklaşık 70 dakikaya indirmiş olurdu; bunun için ise yaklaşık 200 sats ek maliyet gerekirdi. Kazanç, yaprak sayısıyla orantılıdır; birkaç yaprak söz konusu olduğunda, sıralı mod yeterince hızlıydı.

Burada hangi fan-out seçeneği durumu değiştirirdi?

Bu kurtarma işlemini sıralı olarak (varsayılan ayar) yürüttük. FAN_OUT=1 ayarında döngü, öncelikle 4 çıkışlı fazladan bir işlem yayınlardı — 9.388 sat’lık fon, her bir ekonomik yaprak için bir UTXO’ya bölünür; her bir UTXO’nun boyutu, o yaprağın kalan CPFP ücretlerine ek olarak 1.000 sat’lık bir tampon eklenerek belirlenir ve son çıkış kalan tutarı alır. 1 girişli/4 çıkışlı bir P2WPKH işlemi ~203 vB'dir, dolayısıyla 1 sat/vB oranında ~203 sat'tır.

O andan itibaren 4 zincir paralel olarak ilerler — her bir yaprak için bir tane. Her yaprak zinciri kendi TRUC kümesidir; dolayısıyla bir turun dört paketinin tümü bağımsızdır ve aynı blokta onaylanabilir. Bu cüzdanın dört yaprağının her birinde, geri ödeme yapılmadan önce yaklaşık 6 paketlik bir zincir vardı:

zaman kilidi bekleyene kadar bloklarblok başına yaklaşık 10 dakika
Sıralı (varsayılan)4 yaprak × ~6 paket ≈ 24 blok~4 saat
FAN_OUT=11 (fan-out) + ~6 (en derin zincir) ≈ 7 blok~70 dakika

Yaklaşık 203 sat için 3,5 katlık bir gerçek zamanlı kazanç elde edilir ve geri ödeme vadesi dolduktan sonra aynı şekil tekrarlanır: Dört geri ödeme paketi, dört ardışık blok yerine, her bir yaprak için ayrı UTXO’lar içeren tek bir blokta yayınlanır. Kazanç, yaprak sayısıyla orantılıdır (zincir derinliklerinin toplamı ile en derin tek zincirin karşılaştırılması); bu nedenle, düzinelerce ekonomik yaprağa sahip bir cüzdan her zaman yayılmalı; birkaç yaprak için ise sıralı yöntem daha basittir ve bu örnekte yeterince hızlıydı.

6. Adım: Zaman kilitleri, ardından tarama

Döngü tamamlandıktan sonra, her bir ekonomik yaprağın geri ödemesi, CSV zaman kilidinin sona ermesini bekler. Aynı işlemi yeniden çalıştırmak kurtarmak vade bitiminden sonra geri ödemeleri duyurur; onlar onayladıktan sonra, genel tarama yapmak Geri ödeme çıkışlarından herhangi bir hedef adrese tek girişli Taproot anahtar yolu harcamaları oluşturur, imzalayıp bunları sıradan işlemler olarak yayınlar. Bu yazının yazıldığı tarihte, bu cüzdanın dört ekonomik çıkış yolu kendi zincirleri üzerinden gerçekleşmekte ve geri ödemelerin vadesinin dolmasını beklemektedir.

Güven modeli, açık bir dille ifade edildiğinde

Bu konuda kesin konuşmak gerekiyor, çünkü genellikle pazarlama söylemleri gerçeklerin önüne geçiyor:

  • Operatörler asla fonlarınızı harcayamaz. Her bir blok, sizin anahtarınızla onların anahtarının birleşimiyle kilitlenmiştir; her işlem için sizin imzanız gereklidir. Hırsızlık için tüm operatörlerin birbirleriyle işbirliği yapması gerekir. Tek bir dürüst operatör bile bunu imkansız kılar; hatta çevrimdışı bir operatör bile: hırsızlık için onların aktif imzası gerekir, sadece mevcut olmaları yetmez. Operatörlerin çevrimdışı kalması ise tamamen farklı bir arıza durumudur. Hiçbir şey çalınmaz, işbirliği süreci donar ve bunun çözümü aşağıdaki çıkış yoludur.
  • Çıkış işlemi, durum değişikliği her gerçekleştiğinde bir kez veriye ihtiyaç duyar. Kurtarma paketi, operatörler çevrimiçi iken alınmalıdır ve işlem yapma işleminden daha fazla izin gerektirmez: zaman ayırabildiğiniz her an paketi yenileyebilirsiniz. Son yenileme işleminizin kapsadığı her şey sonsuza kadar çıkışa uygun kalır ve geri çekme durumu anında tespit edilebilir (ödemeleriniz başarılı olurken yenileme işleminiz başarısız olur).
  • Çıkış işleminin kendisi izne tabi değildir. Kaydedilmiş bir paket varken, paketleme, imzalama, yayınlama ve temizleme işlemleri için operatörlerin herhangi bir müdahalesine gerek yoktur. İşte bu kurtarma işleminin ana ağda kanıtladığı şey budur.

Güvene dayalı değildir ve biz de öyle olduğunu iddia etmiyoruz. Bir yelpaze içinde değerlendirildiğinde: Tasarım gereği kendi kanal durumunu tutan bir Lightning daha zayıf, ancak hem anahtarlarınızı hem de verilerinizi elinde tutan ve para çekme işlemi dondurulana kadar bu tutma eylemi normal bir hizmet gibi görünen bir saklama hizmetinden çok daha güvenlidir.

Önemli Noktalar

  • Tek taraflı çıkış, bir yangın merdivenidir, kapı değildir. 253 paket, her zincir için paket başına bir blok, haftalarla ölçülen bir zaman kilidi ve 100k-sat’lık bir cüzdanda ayrım gözetmeksizin uygulandığında bakiyenin %79’unu tüketecek olan ücretler. Ekonomik önceliklendirme sayesinde, bakiyenin yaklaşık %90’ı hedefine ulaştı. Spark’ta kendi kendine saklama gerçektir, ancak çıkış yolu yapısı gereği pahalı ve yavaştır; boyut beklentilerinizi buna göre ayarlayın.
  • Gereksiz yapraklar bir yük oluşturur.22 yapraktan 18’i, 1 sat/vB gibi bir değerde bile çıkmaya değmezdi. Bu kurtarma işleminden bu yana, araç, çıkmadan önce yaprakları (operatörlere ulaşılabildiği sürece işbirliğine dayalı takaslar yoluyla) çıkış açısından en uygun birimlere birleştiriyor; böylece gelecekteki kurtarma işlemlerinde terk edilen yaprak sayısı çok daha az oluyor.
  • Paketin güncellik ve eksiksizliği her şeyin anahtarıdır. Eksiksiz ve güncel bir kurtarma paketi olmadan, çıkılacak bir şey kalmaz. Araçlar şu anda her çalıştırmada uygun fırsatları değerlendirerek paketi yeniliyor; bir sonraki adım, Blink uygulamasına otomatik yenileme özelliğini entegre etmektir.
  • TRUC’a saygı gösterin. Her zincirde bir adet doğrulanmamış ebeveyn+çocuk çifti. Çıkış araçları, “doğrula ve devam et” modunda çalışmalı ve hataları tolere etmelidir TRUC ihlali ve eksik girdiler normal sıralama sinyalleri olarak değerlendirin ve bir paket grubunu asla “gönder ve unut” olarak ele almayın.
  • Her şey tohumdan kaynaklanır. Paket yenileme, ücret fonlaması, CPFP imzalaması ve son toplama işlemlerinin tümünde cüzdanın mevcut tohum bilgisi kullanıldı — yedeklenecek ayrı anahtarlar yoktu ve fonlama adresi bir xpub üzerinden yalnızca izleme amaçlı olarak takip edilebiliyordu.

Outlook: Uygulamaya entegre edilmiş çıkış özelliği

Yukarıda bahsedilen her şey, açık kaynaklı araçlar kullanılarak manuel olarak gerçekleştirildi. Bu, bunu kanıtlamak için doğru yer; ancak çoğu kullanıcının bulunduğu ortam değil. Hedeflediğimiz yön, kullanıcının hiçbir zaman hazırlık yapması gerekmeyecek bir çıkış yoludur.

Somut olarak: Blink uygulaması, her durum değişikliğinden sonra — her işlemden sonra — kurtarma paketini otomatik olarak yenileyecek ve kalıcı hale getirecek; bunu yerel cihaz depolama alanına ve kullanıcının ayarladığı durumlarda kendi bulut depolama alanına şifreli olarak kaydedecektir. Bu paket herhangi bir harcama yetkisi taşımaz; anahtarlar değil, çıkış verileridir; dolayısıyla otomatik olarak yedeklenmesi, saldırı yüzeyini genişletmeden çıkış penceresini genişletir. Tohum, tıpkı bugün olduğu gibi, korunması gereken tek gizli bilgi olarak kalır.

Mesele şu ki, “istediğiniz zaman çıkabilirsiniz” ifadesinin herhangi bir hazırlık gerektirmemesi gerekir. Son işlem ne olursa olsun, bu fonları tekrar Bitcoin’e geri aktarmak için gereken veriler zaten kaydedilmiştir. Spark’a erişilemiyorsa, çıkış işlemi Blink uygulamasının içinden ya da aynı paket üzerinde çalışan açık kaynaklı araç aracılığıyla gerçekleştirilir — artık ortada olmayabilecek operatörlerden durum bilgisini almak için telaşlanmaya gerek kalmaz.

Bu, bu vaka çalışmasının ortaya koyduğu eksikliği giderir: Araç seti sistemden çıkarılabilir, ancak yalnızca eksiksiz ve güncel bir paketle karşılaştırıldığında. Yenileme işlemini otomatikleştirerek her zaman güncel ve yedeklenmiş olmasını sağlamak, öncelikle kendiniz oluşturmanız gereken bir acil çıkış yolunu, hazırda bulunan bir acil çıkış yoluna dönüştürür.

‍Burada kullanılan tümaraçlar açık kaynaklıdır ve her komut ile işlem kimliğinin yer aldığı teknik vaka çalışması, kodun hemen yanında bulunmaktadır:

İhtiyacınız olmadan önce kendi cüzdanınızdaki paket üzerinde deneyin. Asıl mesele de bu.

Bunu değerli buldunuz mu? Yazara bahşiş verin!

Bunu değerli buldunuz mu? Yazara bahşiş verin!

Sosyal Paylaşım Bileşeni

Blink'i İndir

Şimdi bitcoin almaya ve göndermeye başlayın

Topluluk