Úvod do Lightning network
Lightning network je p2p platební síť umožňující teoreticky neomezené množství velmi rychlých bitcoinových plateb. Jedná se o druhou vrstvu (chcete-li nadstavbu) nad základní, „blockchainovou“, vrstvou bitcoinových transakcí. Aby byl Bitcoin skutečně decentralizovanou sítí, je nezbytné udržet blockchain relativně kompaktní tak, aby si co nejvíce běžných lidí mohlo dovolit provoz vlastního bitcoinového uzlu (full node). Proto je jeden blok omezen na 4 miliony váhových jednotek. Samoregulační mechanismus težby zajišťuje vytěžení bloku (zapsání bloku do blockchainu) průměrně jednou za deset minut. Tím je však omezen počet zapisovaných transakcí do blockchainu asi na 10 za sekundu (v závislosti na typu a velikosti transakcí).
Lightning network umožnuje trustless (tzn. nevyžadující důvěru v druhou či třetí stranu) provádění plateb bez nutnosti zapsání každé platby jako samostatné transakce do blockchainu zvlášť. Zavádí protokol, díky kterému dvě strany (tvořící platební kanál) mohou mezi sebou provádět platby (měnit účetní stav kanálu), přičemž obě strany v každém okamžiku drží platnou a podepsanou bitcoinovou transakci, která odráží poslední stav platebního kanálu a může být v případě potřeby kdykoliv vyslána do sítě, čímž dojde k vypořádání (a uzavření) kanálu na základní vrstvě. V bitcoinovém skriptovacím jazyce zapsaný tzv. chytrý kontrakt (smart contract) dává oběma stranám možnost potrestat protistranu v případě, kdy by se pokusila vyslat do sítě některou z předešlých, již „odvolaných“ transakcí, která by neodrážela poslední stav kanálu.
Aby nebylo nutné mít vlastní platební kanál s každým potenciálním příjemcem naší platby (stejně, jako není nutné mít vlastní síťový kabel ke každému webovému serveru, jehož stránky si chceme prohlédnout), je v Lightning network umožněno „směrování“ (chcete-li přeposílání, routouvání, forwardování, …) plateb. Naše platba může ke svému příjemci procházet cizími platebními kanály (opět bez nutnosti důvěry v operátory těchto kanálů), dokonce může být i rozdělena na několik menších částí, které projdou různými cestami, přes různé platební kanály.
Jakkoliv se jedná o trustless řešení, nic nám nebrání tuto vlastnost v různé míře vyměnit za více pohodlí. Můžeme se tak naprosto svěřit do rukou např. provozovatelů custodial „peněženky“ Bluewallet, kteří nám umožní disponovat jejich bitcoiny a provádět s nimi LN platby (v takovém případě bitcoiny skutečně nevlastníme, vlastníme pouze pohlédávku vůči provozovateli peněženky, podobně jako v případě bankovního fiat účtu). Můžeme zvolit i řešení „na půli cesty“, jako je např. peněženka Phoenix. V takovém případě budeme mít na svém zařízení „odlehčený“ LN uzel, který nám umožní otevírat vlastní platební kanály s plným uzlem provozovatele Phoenixu (ACINQ). Prostřednictvím takového kvalitně propojeného uzlu můžeme přijímat a odesílat platby prakticky do celé sítě. Přestože jsme v tomto případě, co se funkčnosti týče, plně závislí na provozovateli, zde jsme již vlastníky svých bitcoinů. Kdykoliv můžeme provést konečné vypořádání svých bitcoinů z platebního kanálu na základní vstvu (zápisem transakce do blockchainu). Ultimátní řešení je pak provozování vlastního bitcoinového a lightningového uzlu (lightningový je na tom bitcoinovém závislý). Nejen, že budeme výhradními vlastníky našich bitcoinů, ale také nezávislými účastníky sítě, kteří nemusí věřit a spoléhat na nikoho, jen na vlastní zařízení a na něm běžící kód.
Existuje několik implementací lightnigového uzlu (lnd, c-lightning, eclair, ...). Také existuje mnoho „distribucí“, usnadňujících přístup k celému setu bitcoinového uzlu, lightnigového uzlu a dalších aplikací umožnujících snazší správu uzlu, či příjímání plateb:
- Výhradně pro x86-64 platformu:
- cryptoanarchy-deb-repo-builder (Github)
- Mnohem rozšířenější jsou však ARM distribuce, typicky pro zařízení Raspberry Pi:
Otevření platebního kanálu
Máme-li svůj spuštěný a synchronizovaný LN uzel, naším druhým krokem bude nejspíš (po zapsání si seedu a „nabití“ peněženky on-chain transakcí) otevření platebního kanálu. K tomu budeme potřebovat platební protistranu, jiný LN uzel. Uzel je jednoznačně identifikován svým neměnným veřejným klíčem a IP, resp. TOR adresou, ve formátu klíč@adresa:port. Uzel může být označen i libovolným aliasem, ten však může být kdykoliv měněn a také být shodný pro více uzlů, proto je právě třeba při otevírání kanálu záhodno alespoň zběžně kontrolovat veřejný klíč. Před samotným otevřením kanálu je nutné s protistranou navázat přímé spojení (direct peer). Toto přímé spojení je pak udržováno ideálně po celou dobu trvání platebního kanálu, neboť v případě jeho přerušení není možné přijímat, ani odesílat platby. Nyní může kterákoliv ze stran navhrnout protistraně otevření nového kanálu a jeho parametry, z nichž nejdůležitější je kapacita kanálu. Ta určuje maximální objem platby, která může kanálem najednou projít. Stejná částka bude i výstupem tzv. otevírací transakce, ve které navrhovatel uzamkne bitcoiny ve prospěch multisig adresy 2 ze 2, tedy vznikne takový výstup, který bude možné utratit pouze s podpisem obou stran kanálu. Financovat nově otevíraný kanál lze prozatím pouze jednostraně, podaří-li se ho otevřít, bude tak celá jeho kapacita na straně navrhovatele. Ten ji bude moci odeslat, ale nebude schopen v úvodním stavu tímto kanálem platbu přijmout – na druhé straně v úvodu nebude žádná likvidita.
Pokud protistrana souhlasí s parametry navrhovaného kanálu, odešle navrhovateli odpověď, na základě které bude schopen sestavit dvě transakce. Jednak již popsanou otevírající, kterou však zatím nesmí vyslat do sítě. Jednak řekněme únikovou transakci, nebo také závazek (commitment) – tedy transakci, která v případě problémů odemkne výstup otevírácí transakce a utratí jej dle posledního stavu kanálu (ke kterému se strany v unikové transakci zavazují). V případě úvodního stavu po otevření, kdy ještě neproběhla žádná platba, posílá úniková transakce vše zpět navrhovateli. Když navrhovatel kanálů oznámí protistraně hash této transakce a označí index inkriminovaného výstupu otevírací transakce, může protistrana poskytnou svůj podpis únikové transakce. Nyní se navrhovatel nemusí bát zveřejnit otevírací transakci a počkat na její zatěžení (resp. dosažení požadované hloubky zatěžení, zejména v případě větších kapacit kanálu). I kdyby protistrana v tomto okamžiku zmizela se světa, navrhovatel drží podepsanou únikovou transakci, kterou může zveřejnit a po uplynutí smluvené čekací doby (to_self_delay) získá zpět svůj vklad uzamčený otevírací transakcí.
Aktualizace platebního kanálu
Má-li dojít ke změně stavu platebního kanálu, ať už jedna strana platila přímo druhé, nebo svým kanálem přenesli platbu jiného účastníka LN, musí si strany společně s tím navzájem podepsat nové únikové transakce, zohledňující nový účetní stav. Zároveň dochází k jakémusi odvolání předchozí iterace únikových transakcí. Právě k zajištění této „odvolatelnosti“ drží každá ze stran vlastní – asymetrickou – verzi únikové transakce. Pokud byste teď chtěli namítnout, že podepsaná a platná bitcoinová transakce je přeci neodvolatelná, a to dokonce už před svým zapsáním do blockchainu, tak máte standardně pravdu. Ne však u únikové LN transakce. Každá ze stran drží takovou únikovou transakci, která odemkne 2 ze 2 výstup otevírací transakce a vytvoří dva (nevypořádané HTLC nyní zanedbejme) nové výstupy – ve prospěch protistrany bez dalšího uzamkne její část zůstatku kanálu (ta může takový výstup ihned dále utratit), výstup ve prospěch držitele je však uzamčen skriptem. Ten lze okamžitě utratit tzv. revokačním klíčem nebo až po uplynutí čekací doby – určeného počtu bloků (od zatěžení; na tomto počtu se strany dohodly při otevření kanálu) vlastním klíčem držitele. Právě tyto revokační klíče, resp. tajemství nutné k jejich výrobě, si strany vyměňují při podepisování nových únikových transakcí, čímž tedy prakticky dochází k odvolání předchozí iterace únikových transakcí. Zde je nutné si uvědomit, že každá ze stran drží privátní revokační klíč protistrany, svůj vlastní zná pouze veřejný, který vyrábí tzv. naslepo. Těmito revokačními klíči lze tedy odemykat výstup(y) odvolané únikové transakce protistrany, nikoliv své vlastní.
Pokud by se např. navrhovatel kanálu pokusil po 2 platbách protistranu podvést a zveřejnil by první verzi únikové transakce, která vyplácí celou kapacitu kanálu zpět navrhovateli, hrozí, že ho protistrana potrestá, a před uplynutím čekací doby – určené počtem bloků – si odemkne výstup této staré únikové transakce revokačním klíčem, který si vyrobila na základě tajemství obdrženém při první platbě (změně stavu kanálu). I pokud by podvodník dovedl zajistit, že protistrana bude v době podvodu odpojena od sítě, mohla protistrana již hotovou „trestnou“ transakci (resp. body nutné k její výrobě a podpisu) poskytnout jiným uzlům (těm, které se výhradně odhalováním podvodů zabývají, se říká watchtowers), které ji zveřejní místo něj, pokud v blockchainu uvidí odvolanou únikovou transakci.
Uzavření platebního kanálu
Tohle je nejjednodušší. Uzavření proběhne buď zveřejněním a zatěžením popsané únikové transakce. Nebo se uzly ideálně dohodnou na aktuálním stavu a podepíšou si prostou uzavírací transakci, která bez dalších podmínek rozdělí výstup otevírací transakce oběma stranám. Takové uzavření je výhodnější i z pohledu poplatků, který si strany mohou stanovit podle aktuálního stavu mempoolu na rozdíl od únikové transakce, která již po svém podpisu nemůže přizpůsobit poplatek stavu mempoolu v době svého zveřejnění a tak bývá pro jistotu předražená.
Přeposílání plateb
Představme si, že provozujete vlastní uzel A a chcete zaplatit uzlu D, se kterým ale nemáte přímý kanál. Máte však kanál s uzlem B, který má kanál s uzlem C a ten má kanál k uzlu D. Jak ale zajistit, aby uzly B a C měly incentivu vaši platbu přeposlat a zároveň ji nemohly defraudovat? V LN je incentivizace přeposílat cizí platbu řešena možností stanovit si poplatek za použití kanálu.
Zatímco při onchain transakci stanovuje poplatek odesilatel, který následně čeká, až jeho transakce zaujme těžaře, který ji zatěží, v LN poplatek stanovuje operátor uzlu pro každý svůj kanál a následně čeká, až jeho kanál někdo využije. Navíc je poplatek v LN dvojsložkový – skládá se z tzv. base fee a fee rate. Base fee 2000 msats znamená, že za každé přesměrování platby si operátor uzlu žádá 2 satoshi. Ano, nejmenší jednotkou LN je msat – millisatoshi, tedy tisícina satoshi. Při sestavování onchain transakcí pak dochází k zaokrouhlování na celé satoshi. Fee rate 50 ppm znamená, že je za každý přesměrovaný milion satoshi požadováno dalších 50 satů (50000 msats). Pro přesměrování 300 000 satů by tedy celkový poplatek činil 2000 + (0,3 × 50000) = 17000, tj. 17 satů.
Hashed Time Lock Contract
Před defraudací naší platby při přesměrování přes cizí uzly nás pak chrání HTLC. To je zkratka pro hashed time lock contract. Česky by to mohl být hashový kontrakt s časovým zámkem. Zopakujme, že LN je trustless koncept – není založena na důvěře, naopak stojí na nedůvěře. V systému založeném na důvěře by místo HTLC bylo něco jako jistotní účet, nebo notářská úschova, anglicky escrow, kde důvěryhodná třetí strana vyplatí druhé straně prostředky, pokud v časovém limitu splní zadanou podmínku, jinak vrátí prostředky zpět první straně. V LN je však důvěra ve třetí stranu nahrazena chytrým kontraktem zapsaným v jazyce Script. Ten by v běžné řeci mohl být vyjádřen např. takto „získáš 300 021 satů, když před uplynutím 120 bloků získáš a odhalíš platební předobraz, tj. takový vstup funkce SHA256, který vygeneruje hash H = 6c672...59“. Po marném uplynutí stanoveného počtu bloků se prostředky navrací odesílateli. Jak již víme, hashování je jednosměrná funkce. Snadno spočítáme hash libovolného vstupu, je však prakticky nemožné z hashe zjistit, jaký byl vstup (předobraz). Pokud tedy konečný příjemce platby vygeneruje nějaké náhodné (256bitové) číslo, spočte jeho hash, který předá prostřednictvím invoice odesílateli platby jako platební hash, může odesílatel zajistit přesměrování platby přes cizí uzly za použítí HTLC. Nabídne uzlu B HTLC „když do 120 bloků odhalíš předobraz pro tento platební hash H, získáš nárok na 300 021 satů“. Pokud B HTLC přijme, přidají si ho obě strany jako další výstup do svých únikových (commitment) transkací, které si i podepíší. Aby B získal předobraz, musí nyní nabídnou podobné HTLC uzlu i C (o tom, jak ví, že zrovna C, si snad povíme více v pojednání o samotném trasování a routování) – „když do 80 bloků odhalíš předobraz pro tento platební hash H, získáš nárok na 300 017 satů“. A konečně C nabídne HTLC uzlu D – „když do 40 bloků odhalíš předobraz pro tento platební hash H, získáš nárok na 300 000 satů“. Pozorný čtenář si všiml, že se jednak zkracuje délka časového zámku (vyjádřená v blocích) a jednak se snižuje i částka; jen platební hash zůstává ve všech třech případech shodný. 4, resp. 17 satů tvořící rozdíl mezi částkami je poplatek náležící uzlu B, resp. C. Zkrácování časového zámku je pak nutné proto, aby měl např. B dostatek času vypořádat své HTLC i v případě, že mu C odhalí předobraz platebního hashe až na poslední chvíli. Jediný, kdo doposud zná předobraz platebního hashe je D – to on ho náhodně vygeneroval a pak spočetl jeho hash, který v invoice spojil s požadovanou částkou 300 000 satů. Když má nyní s C uzavřený HTLC na tuto částku a požadující předobraz tohoto hashe, stačí, aby odhalil uzlu C onen předobraz o požádal o vypořádání HTLC. To proběhne standardně tak, jak je popsáno v odstavci Aktualizace platebního kanálu – C ověří, že přeobraz skutečně generuje platební hash, pak si strany aktualizují své únikové transakce – odstraní z nich vypořádavané HTLC a zaznamenají nový účetní stav kanálu. Pokud by C přestal před, či během vypořádáním odpovídat, musí D dokončit vypořádání HTLC před uplynutím stanoveného počtu bloků onchain zveřejněním únikové transakce obsahující tento HTLC, který si následně i odemkne, protože zná předobraz platebního hashe. Úplně stejným způsobem následně proběhne vypořádání i mezi C a B, a konečně i mezi B a A. Díky získanému předobrazu platebního hashe si A může být jist, že jeho platba dorazila v pořádku až k D. Ačkoliv to není nezbytné, používá se z důvodu zachování jednolitosti HTLC i v případě přímé platby mezi uzly bez prostředníků.
Krátce o payment invoice
A právě platební hash – základ HTLC – je důvod, proč je v LN zpravidla nutné pro každou jednotlivou platbu generovat novou invoice. To je datová struktura zakódovaná – podobně jako onchain adresa – v bech32 s prefixem lnbc a lidsky čitelnou částkou. Uvnitř se pak kromě platbního hashe vyskytuje typicky opět částka, hlavní veřejný klíč přijímajícího uzlu, čas vystavení, čas expirace, popisek, payment secret (neplést s předobrazem pro platební hash!), či feature bits (indikující např. možnost rozdělit platbu na několik částí). Zpravidla nechybí ani kryptografický podpis hlavním soukromým klíčem. Invoice může také obsahovat informace o neveřejných kanálech, kterými by mohla být platba routována.
Drby, trasování a cibulové routování
V Lightning network funguje něco, čemu se říká gossip protokol. Uzly do sítě šíří „drby“ o sobě a svých kanálech a zároveň poslouchají (a dál přeposílají) drby o ostatních uzlech a jejich kanálech. Na základě těchto zpráv si pak sestavují graf sítě. Díky němu je pak platící uzel schopen naplánovat trasu (nebo i více možných variant tras) pro svojí platbu. Takto sestavil trasu platby uzel A k uzlu D přes uzel B a C ve výše užitém příkladu, přestože si nemohl být jist, jestli tato trasa bude úspěšná, jelikož neznal účetní stav jednotlivých kanálů. Pokud by např. byla mezi uzly C a D veškerá likvidita na straně D, nebyla by platba úspěšná a bylo by nutné zkusit jinou trasu.
Ke slovu nyní přichází něco, čemu se říká onion routing. Cibule má vrstvy a stejně tak i paket s lightning platbou má vrstvy. S každou přidanou vrstvou dochází k zašifrování celého paketu tak, aby jen další uzel v pořadí mohl „sloupnout“ a rozšifrovat pouze svojí nejsvrchnější vrstvu. Z té se dozví typicky pouze id následujícího kanálu, částku a číslo bloku, při kterém dojde k vypršení časového zámku HTLC kontraktu, který má uzavřít s následujícím uzlem. Platební hash nemusí být zašifrován ve vrstvách onion paketu, ten je znám z již uzavřeného HTLC od předchozího uzlu. Víc směrující uzel (nazývaný také hop) neví a ani nepotřebuje vědět. Neví, je‐li přechozí uzel původcem platby, nebo taky jen hopem. Neví ani, je‐li následující uzel konečným příjemcem platby, nebo jen dalším hopem. Nemůže to ani tušit, neboť paket je v každém okamžiku své cesty stále stejně velký (před předáním dalšímu uzlu je jakoby vyfutrován zevnitř na konstatní velikost). Teprve až ve vrstvě, kterou si rozšifruje konečný uzel, se nalézá dříve zmiňovaný payment secret. Konečný uzel tak má jistotu, že obdržel paket sestavený skutečným původním plátcem, neboť jen on se payment secret dozvěděl z invoce. Žádný hop nemůže sestavit vlastní paket pro následující uzel tak, jako kdyby měl být následující uzel tím posledním a tím ho odhalit jako konečného příjemce platby v případě, že by jím doopravdy byl. Dojde‐li takto platba v pořádku až ke svému konečnému příjemci, může se opačnou cestou vydat platební předobraz vypořádající uzavřené HTLC, jak bylo naznačeno v o nich pojednávajícím odstavci.