/ home / newsletters /
Zpravodaj „Bitcoin Optech” č. 345
Zpravodaj tento týden nahlíží na analýzu P2P provozu typického plného uzlu, shrnuje výzkum hledání cest v LN a popisuje nový přístup ve vytváření pravděpodobnostních plateb. Též nechybí naše pravidelné rubriky se souhrnem sezení Bitcoin Core PR Review Clubu, oznámeními nových vydání a popisem významných změn v populárních bitcoinových páteřních projektech.
Novinky
-
● Analýza P2P provozu: vývojář Virtu zaslal do fóra Delving Bitcoin příspěvek s analýzou síťového provozu odeslaného a přijatého jeho uzlem ve čtyř různých režimech: úvodní stahování bloků (initial block download, IBD), bez serveru (pouze odcházející spojení), se serverem bez archivování (ořezaný uzel) a se serverem s archivováním. Ačkoliv výsledky jediného uzlu nemusí být ve všech případech reprezentativní, některá jeho zjištění jsou zajímavá:
-
● Archivující uzel se serverem s vysokým provozem bloků: Virtuův uzel fungující jako neořezaný uzel se serverem odeslal ostatním uzlům každou hodinu několik gigabajtů bloků. Velká část byly starší bloky, které si spojení vyžádala během jejich IBD.
-
● Nearchivující uzel se serverem s vysokým provozem inv: kolem 20 % celkového provozu byly zprávy
inv
před tím, než aktivoval posílání starších bloků. Erlay by mohl výrazně snížit tento podíl, což představuje zhruba 100 megabajtů za den. -
● Skupina přicházejících spojení jsou zřejmě slídilové: „Zajímavé je, že jedna skupina příchozích spojení vymění s uzlem pouze 1 MB dat, což je příliš málo (když pro srovnání použiju provoz mých odchozích spojení) na to, aby to byla pravidelná spojení. Ty uzly jen dokončí P2P handshake a pak slušně odpovídají na ping zprávy. Jinak jen hltají naše
inv
zprávy.”
Virtuův příspěvek obsahuje další podrobnosti a několik grafů ilustrujících provoz, kterému byl tento uzel vystaven.
-
-
● Výzkum hledání cest s jedinou částí v LN: Sindura Saraswathi zaslala do fóra Delving Bitcoin příspěvek o výzkumu, který podnikla spolu s Christianem Kümmerlem. Předmětem bylo hledání optimálních cest mezi LN uzly pro posílání plateb s jedinou částí. Její příspěvek popisuje strategie, které jsou v současnosti používané v Core Lightning, Eclair, LDK a LND. Autoři dále použili osm upravených a neupravených LN uzlů v simulované síti (založené na snapshotech skutečné sítě) a testovali hledání cest. Během experimentu vyhodnocovali kritéria, jako jsou nejvyšší míra úspěšných dokončení, nejnižší poměr poplatků (nejnižší náklady), nejkratší celkový časový zámek (nejméně špatná doba čekání v nejhorším případě) a nejkratší cesta (nejméně pravděpodobně skončí zaseknutím). Žádný algoritmus nebyl ve všech případech lepší než ostatní. Saraswathi navrhuje, aby implementace nabízely lepší váhové funkce, aby mohli uživatelé volit kompromisy, které u různých plateb preferují (např. u malých osobních nákupů můžete upřednostnit vysokou úspěšnost, ale u větších měsíčních účtů, na jejichž zaplacení máte ještě několik týdnů, budete raději volit nízký poplatek). Dále dodává: „i když to nebylo předmětem studie, poznamenáváme, že znalosti získané touto studií jsou též relevantní pro budoucí vylepšení algoritmů hledání cest pro platby s více částmi.”
-
● Pravděpodobnostní platby pomocí různých hašovacích funkcí a XOR funkce: Robin Linus přidal svou reakci do vlákna ve fóru Delving Bitcoin o pravděpodobnostních platbách. V ní představuje koncepčně jednoduchý skript, který dvěma stranám umožní zavázat se libovolnému množství entropie, která může být později odhalena a xorována dohromady. Tím vznikne hodnota, pomocí které lze určit, kdo obdrží platbu. Uvádíme mírně rozšířený příklad z Linusova příspěvku:
-
Alice tajně vybere hodnoty
1 0 0
a nonce. Bob tajně vybere hodnoty1 1 0
a svůj nonce. -
Každá strana následně svá nonce zahašuje funkcemi určenými výše uvedenými hodnotami. Pokud je hodnota na vrcholu zásobníku
0
, použije opkódHASH160
. Pokud je hodnota0
, použijeSHA256
. V Alicině případě bude provedenosha256(hash160(hash160(alice_nonce)))
, v Bobověsha256(sha256(hash160(bob_nonce)))
. Tím každý z nich vyprodukuje závazek (commitment), který si spolu vymění (své hodnoty a nonce ponechají tajné). -
Po sdílení závazků vytvoří onchain zakládající transakci se skriptem, který validuje vstupy používající
OP_IF
k určení hašovací funkce a který umožní jedné ze stran platbu nárokovat. Pokud je například součet jejich dvou xorovaných hodnot 0 nebo 1, platba připadne Alici. Pokud je 2 nebo 3, peníze obdrží Bob. Kontrakt může dále obsahovat expiraci a větev pro prostorově efektivní kooperativní urovnání. -
Po dostatečném potvrzení zakládající transakce odhalí Alice a Bob navzájem své hodnoty a nonce.
1 0 0
XOR1 1 0
je0 1 0
, což dává součet1
. Platbu může tedy nárokovat Alice.
-
Bitcoin Core PR Review Club
V této měsíční rubrice shrnujeme nedávné sezení Bitcoin Core PR Review Club a vyzdvihujeme některé z důležitých otázek a odpovědí. Klikněte na otázku a odpověď se vám odhalí.
Striktnější nakládání s nevalidními bloky je PR od vývojáře mzumsande, které vylepšuje správnost dvou validačních polí, která nejsou kritická pro konsenzus, ale jsou náročná na výpočet. Tato pole byla dříve aktualizována později z důvodu šetření zdroji, po začlenění PR budou pole aktualizována hned, jakmile je blok označen za nevalidní. Změnu je možné nyní provést, neboť díky Bitcoin Core #25717 by útočník potřeboval vynaložit mnohem více úsilí.
Konkrétně toto PR zajistí, aby m_best_header
v ChainstateManager
vždy
ukazoval na hlavičku s největší vykonanou prací a neznámou validitou a aby
byl nStatus
s hodnotou BLOCK_FAILED_CHILD
vždy správný.
-
Jaký účel(y) má
ChainstateManager::m_best_header
?m_best_header
představuje hlavičku bloku s nejvíce PoW, kterou uzel zatím viděl, ale jehož validitu nemůže zaručit. Jeho hlavním účelem je posloužit jako cíl, ke kterému může uzel postoupit svůj nejlepší řetězec. Dále se používá pro odhad aktuálního času a odhad výšky nejlepšího řetězce během stahování chybějících hlaviček od spojení. Celistvější přehled lze nalézt v šest let starém pull requestu Bitcoin Core #16974. ➚ -
Která z těchto tvrzení byla pravdivá před tímto PR? 1)
CBlockIndex
s NEVALIDNÍM předchůdcem má VŽDYnStatus
s hodnotouBLOCK_FAILED_CHILD
. 2)CBlockIndex
s VALIDNÍM předchůdcem nemá NIKDYnStatus
s hodnotouBLOCK_FAILED_CHILD
.Tvrzení 1) je nepravdivé a je přímo adresováno tímto PR. Před tímto PR označil
AcceptBlock()
nevalidní blok jako nevalidní, ale z důvodu výkonnosti nenastavil jeho potomky jako nevalidní okamžitě. Účastníci sezení nemohli přijít s žádným scénářem, ve kterém by 2) bylo nepravdivé. ➚ -
Jedním z cílů tohoto PR je zajistit, aby byly
m_best_header
anStatus
následníků nevalidního bloku vždy nastaveny na správnou hodnotu. Které funkce jsou přímo zodpovědné za aktualizování těchto hodnot?SetBlockFailureFlags()
je zodpovědná za aktualizovánínStatus
. V normálním provozu jem_best_header
většinou nastaven pomocí výstupního argumentu vAddToBlockIndex()
, ale může být spočítán i nastaven pomocíRecalculateBestHeader()
. ➚ -
Většina logiky v commitu
4100495
validace: v invalidateblock počítej m_best_header okamžitě
implementuje hledání nové nejlepší hlavičky. Co nám zde brání v prostém voláníRecalculateBestHeader()
?RecalculateBestHeader()
prochází celým_block_index
, což je nákladná operace. Commit4100495
to optimalizuje kešováním a procházením množiny kandidátů s vysokým PoW. ➚ -
Kdybychom byli schopni projít strom bloků směrem vpřed (tedy od genesis bloku), potřebovali bychom stále keš
cand_invalid_descendants
? Jaké výhody a nevýhody by měl tento přístup oproti tomuto PR?Pokud by objekty
CBlockIndex
držely reference na všechny své potomky, nemuseli bychom pro zneplatnění potomků procházet celým_block_index
a nepotřebovali bychom tedy kešcand_invalid_descendants
. Tento přístup by však měl velké nevýhody. Zaprvé by měl každý objektCBlockIndex
vyšší paměťové náklady, neboť musí být drženy v paměti pro celým_block_index
. Zadruhé by logika procházení byla i tak složitá, neboť i když má každýCBlockIndex
právě jednoho předka, může mít libovolný počet potomků. ➚
Vydání nových verzí
Vydání nových verzí oblíbených páteřních bitcoinových projektů. Prosíme, zvažte upgrade či pomoc s testováním.
- ● Eclair v0.12.0 je hlavním vydáním tohoto LN uzlu. Vedle jiných vylepšení a oprav chyb „přidává podporu pro vytváření a správu BOLT12 nabídek a nový protokol zavírání podporující RBF. Dále přidává podporu pro ukládání malého množství dat pro naše spojení” (peer storage). Poznámky k vydání zmiňují aktualizace některých hlavních závislostí, což si od uživatelů vyžádá provést jejich aktualizaci před nasazením nové verze Eclair.
Významné změny kódu a dokumentace
Významné změny z tohoto týdne v Bitcoin Core, Core Lightning, Eclair, LDK, LND, libsecp256k1, Hardware Wallet Interface (HWI), Rust Bitcoin, BTCPay Server, BDK, Bitcoin Improvement Proposals (BIPs), Lightning BOLTs, Lightning BLIPs, Bitcoin Inquisition a repozitáři BINANA.
-
● Bitcoin Core #31407 přidává podporu pro ověřování macOS balíčků a binárek ve skriptu
detached-sig-create.sh
. Skript nově také podepisuje samostatné macOS a Windows binárky. Pro tyto úkoly je používán nedávno aktualizovaný nástroj signapple. -
● Eclair #3027 přidává při generování BOLT12 faktur hledání cest uzly podporujícími pouze zaslepené cesty. Za tímto účelem byla přidána nová funkce
routeBlindingPaths
. Zaslepená cesta je poté začleněná do faktury. -
● Eclair #3007 přidává do zprávy
channel_reestablish
nový TLV parametrlast_funding_locked
, který vylepší synchronizaci po ztrátě spojení během splicingu. Opravuje tím souběh, kdy uzel po obdrženíchannel_reestablish
pošlechannel_update
ještě předsplice_locked
. U běžných kanálů to nepředstavuje problém, avšak může způsobit problémy u jednoduchých taprootových kanálů, které vyžadují výměnu noncí mezi spojeními. -
● Eclair #2976 přidává příkaz
createoffer
, čímž umožní vytvářet nabídky bez potřeby dodatečných pluginů. Příkazu lze předat volitelné parametry popisu, částky, doby expirace, vydavatele a úvodního uzlu zaslepené cesty. PR dále přidává příkazydisableoffer
alistoffers
pro správu existujících nabídek. -
● LDK #3608 mění definici a hodnotu konstanty
CLTV_CLAIM_BUFFER
, nově reprezentuje dvojnásobek očekávaného maximálního počtu bloků vyžadovaných pro potvrzení transakce. Přizpůsobuje se tím anchor kanálům, kde transakce nárokující HTLC jsou zpožděny pomocíOP_CHECKSEQUENCEVERIFY
(CSV) časového zámku o jeden blok. Dříve byla hodnota nastavena na maximální počet konfirmací, což bylo pro neanchorové kanály dostatečné. Jako bázová hodnota této konstanty slouží nová konstantaMAX_BLOCKS_FOR_CONF
. -
● LDK #3624 přináší rotaci zakládajících klíčů po úspěšném splicu. Výpočet klíčů následuje BOLT3 specifikaci, avšak používá txid zakládající transakce splicu namísto
per_commitment_point
a používárevocation_basepoint
pro omezení derivace klíčů na účastníky kanálu. -
● LDK #3016 umožňuje externím projektům spouštět funkční testy a přitom nahradit komponenty jako podepisování. K tomuto účelu bylo přidáno makro
xtest
, globální proměnnáMutGlobal
, abstraktníDynSigner
aTestSignerFactory
pro jejich vytváření. Testy jsou schovány za příznakem_externalize_tests
. -
● LDK #3629 zlepšuje logování vzdálených chyb, které nemohou být nikomu přisouzeny nebo interpretovány. PR upravuje
onion_utils.rs
pro logování takových chyb a přináší funkcidecrypt_failure_onion_error_packet
pro dešifrování. Dále opravuje chybu související s nečitelných chybami, ale validními autentizačními kódy (HMAC). Díky tomu bude také možné vyhýbat se uzlům, které inzerují vysokou dostupnost, ale tento slib neplní. -
● BDK #1838 přináší jasnější implementaci úplného skenování. Do
SyncRequest
aFullScanRequest
přidává povinný parametrsync_time
a používá ho jakoseen_at
u nepotvrzených transakcí. Nekanonické transakce (viz zpravodaj č. 335) nemusíseen_at
obsahovat.TxUpdate::seen_ats
je nověHashSet<(Txid, u64)>
, aby mohla mít jedna transakce více časových razítekseen_at
.TxUpdate
je nově#[non_exhaustive]
.