Конфіденційні транзакції до Monero, або як перекласти невідомо що невідомо куди

Ми продовжуємо наш цикл про пристрій блокчейну Monero, і сьогоднішня стаття буде присвячена протоколу RingCT (Ring Confidential Transactions), в якому представлені конфіденційні транзакції та нові кільцеві підписи. На жаль, в інтернеті мало інформації про те, як він працює, і ми спробували заповнити цю прогалину.

Конфіденційні транзакції до Monero, або як перекласти невідомо що невідомо куди

Ми поговоримо про те, як за допомогою цього протоколу мережа приховує суми переказів, чому відмовилися від класичних для cryptonote кільцевих підписів і як ця технологія розвиватиметься далі.

Оскільки цей протокол — одна з найскладніших технологій у Monero, читачеві знадобляться базові знання про влаштування цього блокчейну та поверхневі знання у криптографії на еліптичних кривих (щоб освіжити ці знання, можна прочитати перші розділи нашої попередньої статті про мультипідписи).

Протокол RingCT

Одна з можливих атак на криптонот-валюти - аналіз блокчейна, заснований на знанні суми і часу відправленої транзакції. Це дозволяє значно звузити область пошуку зловмисника виходів, що цікавлять. Для захисту від такого аналізу Monero було впроваджено протокол анонімних транзакцій, який повністю приховує суми переказів у мережі.

Варто зазначити, що ідея приховування сум не нова. Одним із перших її описав розробник Bitcoin Core Грег Максвелл у своїй статті Confidential Transactions. Нинішня реалізація RingCT виступає її модифікацією з можливістю використання кільцевих підписів (куди вже без них), і так і отримала свою назву Ring Confidential Transactions.

Крім іншого, протокол допомагає позбутися проблем із замішуванням пилових виходів — виходів на маленьку суму (зазвичай виходять у вигляді здачі від транзакцій), які створювали проблем більше, ніж коштували самі.

У січні 2017 року відбувся Хардфорк мережі Monero, що дозволяє опціонально використовувати конфіденційні транзакції. А вже у вересні того ж року з Хардфорку версії 6 такі транзакції стали єдиними дозволеними в мережі.

RingCT використовує відразу кілька механізмів: багатошарові пов'язані спонтанні анонімні групові підписи (Multilayered Linkable Spontaneous Anonymous Group Signature, далі — MLSAG), схема зобов'язань (Pedersen Commitments) і range proofs (усталеного перекладу російською мовою цього терміну немає).

Протокол RingCT вводить два типи анонімних транзакцій: simple та full. Перші гаманець генерує, коли транзакція використовує більше одного входу, другі - у зворотній ситуації. Відрізняються вони валідацією сум транзакцій та підписуваними MLSAG-підписом даними (докладніше про це поговоримо нижче). Причому транзакції типу full можна генерувати з будь-яким числом входів, принципової різниці немає. У книзі "Zero to Monero" З цього приводу йдеться, що рішення обмежити повну транзакцію одним входом було прийнято нашвидкуруч і в майбутньому може змінитися.

MLSAG-підпис

Згадаймо, що з себе представляють входи транзакції, що підписуються. Кожна транзакція витрачає якісь кошти та генерує. Генерація коштів відбувається шляхом створення виходів транзакції (пряма аналогія — купюри), а вихід, який транзакція витрачає (адже у реальному житті витрачаємо саме грошові купюри), стає входом (обережно, тут дуже легко заплутатися).

Вхід посилається на кілька виходів, але витрачає лише один, таким чином створюючи «димову завісу», щоб утруднити аналіз історії перекладів. Якщо транзакція має більше одного входу, то таку структуру можна представити у вигляді матриці, де рядки - це входи, а стовпці - виходи, що замішуються. Щоб довести мережу, що транзакція витрачає саме свої виходи (знає їхні секретні ключі), входи підписують кільцевим підписом. Такий підпис дає гарантію, що підписуючий знав секретні ключі від усіх елементів якогось зі стовпців.

Конфіденційні транзакції більше не використовують класичні для криптонота кільцеві підписи, на зміну їм прийшли MLSAG — адаптована для кількох входів версія аналогічних одношарових кільцевих підписів, LSAG.

Багатошаровими вони називаються тому, що підписують відразу кілька входів, кожен із яких замішаний з кількома іншими, тобто підписується матриця, а не один ряд. Як побачимо далі, це допомагає заощадити на розмірі підпису.

Давайте розглянемо, як формується кільцевий підпис, на прикладі транзакції, яка витрачає 2 реальні виходи та використовує для замішування m - 1 випадкових з блокчейну. Позначимо публічні ключі виходів, які витрачаємо як
Конфіденційні транзакції до Monero, або як перекласти невідомо що невідомо куди, а key images для них відповідно: Конфіденційні транзакції до Monero, або як перекласти невідомо що невідомо куди Таким чином, у нас виходить матриця розміром 2 х m. Для початку нам потрібно обчислити так звані challenges для кожної пари виходів:
Конфіденційні транзакції до Monero, або як перекласти невідомо що невідомо куди
Обчислення починаємо з виходів, які витрачаємо, використовуючи їхні публічні ключі:Конфіденційні транзакції до Monero, або як перекласти невідомо що невідомо кудита випадкові числаКонфіденційні транзакції до Monero, або як перекласти невідомо що невідомо кудиУ результаті отримуємо значення:
Конфіденційні транзакції до Monero, або як перекласти невідомо що невідомо куди, які використовуємо для обчислення challenge
Конфіденційні транзакції до Monero, або як перекласти невідомо що невідомо кудинаступної пари виходів (щоб було простіше зрозуміти, що куди підставляємо, ми виділили ці значення різними кольорами). Всі наступні значення розраховуються по колу за формулами, наведеними на першій ілюстрації. Останнім обчислюється challenge для пари реальних виходів.

Як бачимо, у всіх стовпцях, крім що містить реальні виходи, використовуються випадково згенеровані числаКонфіденційні транзакції до Monero, або як перекласти невідомо що невідомо куди. Для π-го стовпця вони нам теж знадобляться. ПеретворюємоКонфіденційні транзакції до Monero, або як перекласти невідомо що невідомо кудиу s:Конфіденційні транзакції до Monero, або як перекласти невідомо що невідомо куди
Сам підпис являє собою кортеж усіх цих значень:

Конфіденційні транзакції до Monero, або як перекласти невідомо що невідомо куди

Далі ці дані записуються у транзакцію.

Як бачимо, MLSAG містить лише один challenge c0, що дозволяє заощадити на розмірі підпису (які і так вимагають багато місця). Далі будь-який перевіряючий, використовуючи даніКонфіденційні транзакції до Monero, або як перекласти невідомо що невідомо куди, відновлює значення c1,…, cm та перевіряє, щоКонфіденційні транзакції до Monero, або як перекласти невідомо що невідомо куди. Таким чином, наше кільце замкнулося і підпис пройшов перевірку.

Для RingCT транзакцій типу full додається ще один рядок до матриці із замішаними виходами, але про це ми розповімо нижче.

Зобов'язання Педерсена

Схеми зобов'язань (частіше використовують англомовний термін - commitments) використовуються для того, щоб одна сторона могла довести, що знає якийсь секрет (число), фактично не розкриваючи його. Наприклад, ви викидаєте на кістках деяке число, вважаєте commitment і передаєте його стороні, що перевіряє. Таким чином, у момент розкриття секретного числа перевіряючий самостійно вважає commitment, тим самим переконуючись, що ви його не обдурили.

У Monero commitments використовуються для приховування сум переказів та застосовують найпоширеніший варіант – Pedersen commitments. До речі, цікавий факт — спочатку розробники пропонували приховувати суми звичайним замішуванням, тобто додавати виходи на довільні суми, щоб внести невизначеність, але потім перейшли на commitments (при цьому не факт, що зекономили на транзакції, як ми побачимо нижче).
У загальному випадку commitment виглядає так:
Конфіденційні транзакції до Monero, або як перекласти невідомо що невідомо кудиДе C - Значення самого commitment, a - приховувана сума, H - фіксована точка на еліптичній кривій (додатковий генератор), а x - Якась довільна маска, що приховує фактор, що генерується випадковим чином. Маска тут потрібна для того, щоб третій бік не зміг простим перебором підібрати значення commitment.

При генерації нового виходу гаманець розраховує йому commitment, а при витрачанні бере або розраховане при генерації значення, або перераховує його заново — залежно від типу транзакції.

RingCT simple

У випадку simple RingCT транзакцій для того, щоб гарантувати, що транзакція створила виходи на суму, рівну сумі входів (не виробила гроші з повітря) потрібно, щоб сума commitments перших і других була однаковою, тобто:
Конфіденційні транзакції до Monero, або як перекласти невідомо що невідомо куди
Commitment комісії вважають трохи інакше – без маски:
Конфіденційні транзакції до Monero, або як перекласти невідомо що невідомо куди, Де a - Сума комісії, вона публічно доступна.

Такий підхід дозволяє довести стороні, що перевіряє, що ми використовуємо однакові суми, не розкриваючи їх.

Щоб усе стало зрозуміліше, розглянемо приклад. Припустимо, транзакція витрачає два виходи (тобто вони стають входами) на 10 та 5 XMR та генерує три виходи на суму 12 XMR: 3, 4 та 5 XMR. При цьому сплачує комісію 3 XMR. Таким чином, сума витрачених грошей плюс сума згенерованих і комісія дорівнюють 15 XMR. Давайте спробуємо розрахувати commitments і подивимося на різницю їх сум (згадаймо математику):

Конфіденційні транзакції до Monero, або як перекласти невідомо що невідомо куди
Тут ми бачимо, щоб рівняння зійшлося – суми масок входів та виходів нам потрібні однаковими. Для цього гаманець генерує випадковим чином x1, y1, y2 та y3, а решта x2 розраховує так:
Конфіденційні транзакції до Monero, або як перекласти невідомо що невідомо куди
Використовуючи ці маски, ми можемо довести будь-якому перевіряльнику, що ми не генеруємо більше коштів, ніж витрачаємо, не розкриваючи суми. Оригінально, правда?

RingCT full

У full RingCT транзакціях перевірка сум переказів проходить дещо більш вигадливо. У цих транзакціях гаманець не перераховує commitments для входів, а використовує розраховані при їх генерації. При цьому слід вважати, що різницю сум ми вже не отримаємо рівної нулю, а натомість:
Конфіденційні транзакції до Monero, або як перекласти невідомо що невідомо куди
Тут z - Різниця масок входів і виходів. Якщо розглядати zG як публічний ключ (чим він де-факто і є), то z - Це приватний ключ. Таким чином, ми знаємо публічний та відповідний йому приватний ключі. Маючи ці дані, ми можемо використовувати їх у кільцевому підписі MLSAG поряд з публічними ключами виходів, що замішуються:
Конфіденційні транзакції до Monero, або як перекласти невідомо що невідомо куди
Таким чином, валідний кільцевий підпис гарантуватиме, що ми знаємо всі приватні ключі одного зі стовпців, а приватний ключ в останньому рядку ми можемо знати лише якщо транзакція не генерує коштів більше, ніж витрачає. До речі, тут же відповідь на запитання «чому тут різниця сум commitments не призводять до нуля» — якщо zG = 0, то ми розкриємо стовпець із реальними виходами.

А як же отримувач коштів дізнається скільки грошей йому надіслали? Тут все просто – відправник транзакції та одержувач обмінюються ключами за протоколом Діффі-Хеллмана, використовуючи ключ транзакції та view-ключ одержувача та обчислюють загальний секрет. Відправник записує у спеціальні поля транзакції дані суми виходів, зашифровані цим загальним ключем.

Range proofs

А що буде, якщо як сума в commitments використовувати негативне число? Це може призвести до створення додаткових монет! Такий результат неприпустимий, тому потрібна гарантія, що використовувані нами суми не негативні (без розкриття цих сум, зрозуміло, інакше стільки праці і даремно). Іншими словами, ми маємо довести, що сума перебуває в інтервалі [0, 2n - 1].

Для цього сума кожного виходу розбивається на двійкові розряди та вважається commitment по кожному розряду окремо. Як це відбувається, краще розглянути на прикладі.

Припустимо, що суми у нас невеликі і поміщаються в 4 біти (на практиці це 64 біти), а ми створюємо вихід на суму 5 XMR. Вважаємо commitments для кожного розряду та загальний commitment на всю суму:Конфіденційні транзакції до Monero, або як перекласти невідомо що невідомо куди
Далі кожний commitment замішується з сурогатним (Ci-2iH) і попарно підписується кільцевим підписом Борромео (ще один кільцевий підпис), запропонованим Грегом Максвеллом у 2015 році (докладніше про нього можна почитати тут):
Конфіденційні транзакції до Monero, або як перекласти невідомо що невідомо кудиВсе разом це називається range proof і дозволяє гарантувати, що у commitments використовуються суми в інтервалі [0, 2n - 1].

Що далі?

У поточній реалізації range proofs займають багато місця — 6176 байт на один вихід. Це веде до великих транзакцій та, відповідно, вищих комісіям. Щоб знизити розмір транзакції Monero, розробники вводять замість підписів Борромео bulletproofs — механізм range proof без побітових commitments. За деякими оцінками, вони здатні скоротити розмір range proof до 94%. До речі, у середині липня технологія пройшла аудит від компанії Kudelski Security, яка не виявила істотних недоліків як у самій технології, так і її реалізації. Технологія вже застосовується у тестовій мережі, а з новим хардфорком, ймовірно, може переїхати і до основної мережі.

Задавайте свої питання, пропонуйте теми для нових статей про технології в області криптовалют, а також підписуйтесь на нашу групу Facebook, щоб бути в курсі наших подій та публікацій.

Джерело: habr.com

Додати коментар або відгук