Folytatjuk a Monero blokkláncának működéséről szóló cikksorozatunkat, és a mai cikk a RingCT (Ring Confidential Transactions) protokollal foglalkozik, amely titkos tranzakciókat és új gyűrűs aláírásokat mutat be. Sajnos az interneten nagyon kevés információ található arról, hogyan működik, és mi megpróbáltuk pótolni ezt a hiányosságot.

Beszélni fogunk arról, hogyan rejti el a hálózat az átutalások összegét e protokoll segítségével, miért mondtak le a klasszikus cryptonote gyűrűs aláírásokról, és hogyan fog fejlődni ez a technológia a jövőben.
Mivel ez a protokoll a Monero egyik legbonyolultabb technológiája, az olvasónak alapvető ismeretekre van szüksége a blokklánc működéséről és felületes ismeretekre a elliptikus görbék kriptográfiájáról (a tudás felfrissítésére elolvashatja a korábbi cikkünk első fejezeteit a ).
RingCT protokollról
Az egyik lehetséges támadás a cryptonote valuták ellen a blokklánc elemzése, amely az átutalás összegének és idejének ismeretén alapul. Ez lehetővé teszi a potenciálisan érdekes kimenetek keresési területének jelentős szűkítését. A Moneróban a titkos tranzakciók protokollját vezették be az ilyen elemzés elleni védelem érdekében, amely teljesen elrejti az átutalások összegét a hálózaton.
Érdemes megjegyezni, hogy az összegek elrejtésének ötlete nem új. Az elsőt Greg Maxwell, a Bitcoin Core fejlesztője írta le a A RingCT jelenlegi megvalósítása a gyűrűs aláírások használatának lehetőségével egy módosított verziója ennek, és ezért kapta a Ring Confidential Transactions nevet.
Ezen kívül a protokoll segít megszüntetni a poros kimenetek keveredésével kapcsolatos problémákat - a kicsi összegű kimeneteket (amelyek általában a tranzakciókból származó visszajáró összegként jelentkeznek), amelyek több problémát okoztak, mint amennyit értek.
2017 januárjában a Monero hálózatán kemény forkot hajtottak végre, amely lehetővé tette a titkos tranzakciók opcionális használatát. Már 2017 szeptemberében a 6-os verzió kemény forkjával az ilyen tranzakciók lettek az egyetlen engedélyezett típus a hálózaton.
A RingCT több mechanizmust használ: többrétegű összekapcsolt spontán névtelen csoportos aláírások (Multilayered Linkable Spontaneous Anonymous Group Signature, a továbbiakban MLSAG), elkötelezési séma (Pedersen Commitments) és range proofs (ennek a kifejezésnek magyar megfelelője nincs).
A RingCT protokoll kétféle névtelen tranzakciót vezet be: simple és full. Az előbbit a pénztárca generálja, amikor a tranzakció több mint egy bemenetet használ, az utóbbira az ellenkező helyzetben kerül sor. Ezek különböznek a tranzakciók összegének validálásában és az MLSAG aláírással aláírt adatokban (erről alább beszélünk). Ráadásul a full típusú tranzakciók bármennyi bemenettel generálhatók, lényegében nincs különbség. A "Zero to Monero" című könyv ezzel kapcsolatban azt írja, hogy a full tranzakciók egy bemenetre korlátozásának döntését gyorsan hozták meg, és ez a jövőben változhat.
MLSAG aláírás
Emlékezzünk, mi is képezi a tranzakció aláírandó bemeneteit. Minden tranzakció pénzeszközöket költ el és generál. A pénzeszközök generálása a tranzakció kimeneteinek létrehozásával történik (közvetlen analógia — bankjegyek), a kimenet, amelyet a tranzakció költ (hiszen a valós életben mindig a bankjegyeket költjük), belépés lesz (itt nagyon könnyű összezavarodni).
A bemenet több kimenetre hivatkozik, de csak egyet költ el, így "füstfelhőt" teremt, hogy megnehezítse a tranzakciók történetének elemzését. Ha a tranzakciónak több mint egy bemenete van, ezt a struktúrát egy mátrix formájában lehet bemutatni, ahol a sorok a bemenetek, az oszlopok pedig az érintett kimenetek. A hálózat bizonyítása érdekében, hogy a tranzakció ténylegesen a saját kimeneteit költi el (ismeri azok titkos kulcsait), a bemeneteket gyűrűs aláírással írják alá. Ez az aláírás garantálja, hogy az aláíró tudta az összes oszlop bármelyik elemének titkos kulcsát.
A titkos tranzakciók nem használják többé a klasszikus, gyűrűs aláírásokat, helyette az MLSAG érkezett — a több bemenetre adaptált változata az analóg egyrétegű gyűrűs aláírásoknak, .
Többrétegűek, mivel egyszerre több bemenetet írnak alá, mindegyik több másikkal keveredik, tehát egy mátrixot írnak alá, nem csupán egy sort. Mint később látni fogjuk, ez segít csökkenteni az aláírás méretét.
Nézzük meg, hogyan alakul a gyűrűs aláírás egy tranzakció példáján, amely 2 valódi kimenetet költ el, és m - 1 véletlenszerű kimenetet használ a blokkláncból. Jelöljük a költött kimenetek nyilvános kulcsait, mint
, és a hozzájuk tartozó key images-t:
Így egy 2 x mméretű mátrixot kapunk. Először ki kell számítanunk az úgynevezett challenges értékeket minden kimenet párra:

A számításokat a felhasznált kimenetek nyilvános kulcsaival kezdjük:
és a véletlenszámokkal.
Végül az alábbi értékeket kapjuk:
, amelyeket a következő kimenet párhoz tartozó challenge kiszámításához használunk.
A következő kimenet pár challenge-jét a körök formái szerint számítjuk ki, amelyeket az első ábrán bemutattunk. Az utolsó challenge a valódi kimenetek párjára számítódik ki.
Ahogyan látjuk, minden oszlopban, a valódi kimeneteket tartalmazó oszlopon kívül, véletlenszerűen generált számokat használunk,
. A π-ik oszlopra szükségünk van. Átalakítjuk a
-t s-re:
A tényleges aláírás ezeknek az értékeknek a tuple-je:

Ezek az adatok a tranzakcióba kerülnek.
Mint láthatjuk, az MLSAG-nak csak egy challenge-e van: c0, ami lehetővé teszi, hogy megtakarítsunk a méretén (amely egyébként is sok helyet foglal el). Ezután bármely ellenőr, a rendelkezésre álló adatok felhasználásával, visszaállítja a c1,…, cm értékeket és ellenőrzi, hogy a
. Így a gyűrűnk bezárult, és az aláírás sikeresen átment az ellenőrzésen.
A RingCT teljes típusú tranzakciók esetén egy további sort adnak a kevert kimenetek mátrixához, de erről később fogunk beszélni.
Pedersen Commitments
Kötelező sémák
(a gyakran angol nyelvű kifejezést — commitments — használják, hogy egy fél bizonyítani tudja, hogy tud egy titkot (szám), anélkül, hogy azt ténylegesen felfedné. Például, dobsz egy számot a kockákon, kiszámítod a commitment-et, és átadod a vizsgáló félnek. Így, amikor a titkos számot felfeded, a vizsgáló önállóan kiszámítja a commitment-et, így megbizonyosodik arról, hogy nem csaltál meg őt.)
A Monero kötelezettségek az átutalások összegének elrejtésére szolgálnak, és a legelterjedtebb változatot használják – Pedersen kötelezettségek. Érdekes tény, hogy a fejlesztők kezdetben a szokásos keveréssel próbálták eltitkolni az összegeket, azaz véletlenszerű összegek hozzáadásával, hogy bizonytalanságot hozzanak létre, de később a kötelezettségekre tértek át (ez nem biztos, hogy csökkentette a tranzakciók méretét, ahogyan azt alább látni fogjuk).
Általános esetben a kötelezettség a következőképpen néz ki:
Ahol C — a kötelezettség értéke, a — a rejtett összeg, H — egy fix pont az elliptikus görbén (további generátor), és x — egy véletlenszerűen generált maszk, rejtett tényező. A maszk arra szolgál, hogy harmadik fél ne tudja egyszerű próbálkozásokkal kitalálni a kötelezettség értékét.
Új kimenet generálásakor a pénztárca kiszámítja a kötelezettséget, és a felhasználásakor vagy a generáláskor kiszámított értéket veszi, vagy újraszámítja attól függően, hogy milyen típusú tranzakcióról van szó.
RingCT egyszerű
Egyszerű RingCT tranzakciók esetén ahhoz, hogy garantáljuk, hogy a tranzakció kimenetei összege megegyezzen a bemenetek összegével (nem generálunk pénzt a levegőből), szükséges, hogy az első és második kötelezettségek összege azonos legyen, azaz:

A jutalék kötelezettségeit kicsit másképp számítják – maszk nélkül:
, ahol a — a jutalék összege, amely nyilvánosan hozzáférhető.
Ez a megközelítés lehetővé teszi, hogy a vizsgálatra jogosult fél számára bizonyítsuk, hogy azonos összegeket használunk anélkül, hogy ezeket felfednénk.
Hogy minden érthetőbbé váljon, nézzünk egy példát. Tegyük fel, hogy a tranzakció két kimenetet (azaz ezek bemenetekké válnak) költ el, 10 és 5 XMR értékben, és három kimenetet generál, amelyek összege 12 XMR: 3, 4 és 5 XMR. Eközben 3 XMR jutalékot fizet. Így a kiadott pénz összege plusz a generált összeg és a jutalék egyenlő 15 XMR-rel. Próbáljuk meg kiszámítani a kötelezettségeket, és nézzük meg az összegek különbségét (emlékezzünk a matematikára):

Itt láthatjuk, hogy ahhoz, hogy az egyenlet helyesen működjön — a bemenetek és kimenetek maszkjainak összegeinek azonosnak kell lenniük. Ehhez a pénztárca véletlenszerűen generálja x1, y1, y2 és y3, a maradékot pedig x2 így számítja ki:
![]()
Ezeknek a maszkoknak a használatával bármely ellenőrnek bizonyíthatjuk, hogy nem generálunk több eszközt, mint amennyit költünk, anélkül, hogy felfednénk az összegeket. Eredeti, ugye?
RingCT teljes
A full RingCT tranzakciók esetében a pénzátutalások összegeinek ellenőrzése kissé bonyolultabb. Ezekben a tranzakciókban a pénztárca nem számolja újra a bemenetek kötelezettségeit, hanem azokat használja, amelyeket a generáláskor számoltak ki. Ebből következően azt kell feltételeznünk, hogy a különbség összegét már nem kapjuk meg nullának, hanem ehelyett:

Itt z — a bemenetek és kimenetek maszkjainak különbsége. Ha ezt tekintjük zG mint nyilvános kulcsot (amely de facto ilyen), akkor z — ez a privát kulcs. Így tudjuk a nyilvános és a hozzá tartozó privát kulcsokat. Ezekkel az adatokkal felhasználhatjuk őket az MLSAG gyűrűs aláírásban, a keveredett kimenetek nyilvános kulcsaival együtt:

Ezért egy érvényes gyűrűs aláírás garantálja, hogy tudjuk az egyik oszlop összes privát kulcsát, míg az utolsó sor privát kulcsát csak akkor tudjuk, ha a tranzakció nem generál olyan összeget, amely meghaladná a költést. Egyébként itt a válasz arra a kérdésre, hogy miért nem vezet a kötelezettségek összegeinek különbsége nullához — ha zG = 0, akkor felfedjük a valódi kimenetek oszlopát.
De hogyan tudja a pénz átvevője, mennyi pénzt küldtek neki? Itt minden egyszerű — a tranzakció küldője és a fogadó kulcsokat cserélnek a Diffie-Hellman protokollon keresztül, a tranzakciókulcs és a fogadó nézetkulcs használatával közös titkot számítanak. A küldő rögzíti a tranzakció speciális mezőiben a kimenetek összegeit, titkosítva ezzel a közös kulccsal.
Range proofs
Mi történik, ha a kötelezettségekben a költségként negatív számot használunk? Ez további érmék generálásához vezethet! Ilyen kimenetel nem megengedett, ezért garancia szükséges arra, hogy a használt összegek nem negatívak (anélkül, hogy ezek az összegek nyilvánvalóvá válnának, természetesen, különben az összes munka hiábavaló lenne). Más szavakkal, bizonyítanunk kell, hogy az összeg az alábbi intervallumban van: [0, 2n — 1].
Ehhez minden kimenet összegét bitjeire osztjuk, és minden bithez külön kötelezettséget számítunk. Jobb, ha egy példán keresztül vizsgáljuk meg, hogyan történik ez.
Feltételezve, hogy az összegeink kicsik és 4 bitbe férnek (a gyakorlatban ez 64 bit), és mi 5 XMR összegű kimenetet hozunk létre. Számítunk kötelezettségeket minden bithez és az összes kötelezettséget az összeghez:
Ezután minden kötelezettséget keverünk egy szürke (Ci-2iH) és páronként aláírja a Borromeo gyűrűs aláírással (még egy gyűrűs aláírás), amelyet Greg Maxwell javasolt 2015-ben (többet erről lehet olvasni ):
Ezt együtt range proofnak nevezik, és lehetővé teszi, hogy garantálja, hogy a commitmentsben összegek szerepelnek egy intervallumban. [0, 2n — 1].
Mi következik?
A jelenlegi megvalósításban a range proofs nagyon sok helyet foglalnak el - 6176 byte egy kimenetre. Ez nagy tranzakciókhoz és így magasabb díjakhoz vezet. A tranzakciók méretének csökkentésére a Monero fejlesztői a Borromeo aláírások helyett bulletproofs-t vezetnek be - a range proof mechanizmust bit-alapú commitments nélkül. , képesek akár 94%-kal csökkenteni a range proof méretét. Egyébként július közepén a technológia átment a Kudelski Security cégtől, amely nem talált lényeges hiányosságokat sem a technológiában, sem annak megvalósításában. A technológia már alkalmazásra került a teszthálózaton, és a következő hard fork révén valószínűleg átkerül a fő hálózatba.
Kérdéseket tehet fel, új cikkek témáit javasolhatja a kriptovaluták technológiájában, valamint iratkozzon fel csoportunkra a , hogy naprakészen követhesse eseményeinket és publikációinkat.
Forrás: habr.com
