Вступ:
Недавно Виталик та кілька вчених спільно опублікували нову статтю, в якій доторкаються до того, як Tornado Cash реалізує свою схему протидії відмиванню грошей (забезпечуючи можливість вилучення для доведення того, що їх історія депозитів належить до набору, який не містить забруднених коштів). Однак у статті бракувало складного пояснення бізнес-логіки та принципів Tornado Cash, що залишило деяких читачів лише з поверхневим розумінням.
Варто зазначити, що проекти, подібні до Tornado, які представляють конфіденційні підприємства, дійсно використовують аспект нуль-знань алгоритму ZK-SNARK. Тим часом більшість рішень, які мають прапорець ZK, такі як Rollups, просто використовують стислість ZK-SNARK. Часто люди схильні сплутувати Доказ Правильності з ZK, і Tornado служить відмінним прикладом для пояснення практичного застосування ZK.
Автор цього статті написав статтю про принципи Торнадо ще у 2022 році для дослідження Web3Caff. Сьогодні ми витягли і розширили деякі розділи оригінальної роботи, щоб забезпечити систематичне розуміння Tornado Cash.
Посилання на оригінальну статтю:https://research.web3caff.com/zh/archives/2663?ref=157
Tornado Cash використовує докази з нульовим відкриттям як свій протокол змішування. У той час як його старша версія була запущена у 2019 році, бета-версія оновленої моделі була випущена наприкінці 2021 року. Ранішня версія Tornado досягла високого рівня децентралізації завдяки тому, що у цілому контракти були відкриті для перегляду та були вільні від контролю багато-підписових операцій. Крім того, код фронтенду був відкритим та зберігався в мережі IPFS. Через простоту старої версії Tornado ця стаття зосереджена на її поясненні.
Основний підхід Tornado полягає в тому, щоб змішати численні операції збереження та виведення разом. Після того як Токени було внесено в Tornado, депоненти представляють ZK Proof, щоб перевірити свій попередній депозит, а потім здійснюють виведення за допомогою нової адреси, тим самим руйнуючи зв'язок між адресами депозиту та виведення.
Щоб сказати коротко, уявіть Торнадо як скляний ящик, заповнений монетами (Coins), які внесли багато людей. Ми бачимо, хто вніс монети, але ці монети дуже однорідні. Якщо хтось незнайомий взяв би монету з коробки, було б важко відслідкувати, хто спочатку поклав цю монету туди.
(джерело зображення: rareskills)
Такі сценарії здаються звичайними. Коли ми обмінюємо кілька ETH з пулу Uniswap, неможливо визначити, чиї ETH ми отримали, враховуючи велику кількість постачальників ліквідності для Uniswap. Однак відмінність полягає в процесі. З Uniswap, обмін токенів вимагає інший токен на еквівалентну вартість, і кошти не можуть бути "приватно" перекладені. На відміну від цього, міксер просто вимагає від забирача пред'явити свій квиток про внесення.
Щоб зробити вигляд однорідними дії з внесення та зняття коштів, пул Tornado зберігає послідовність сум внесків та зняттів. Наприклад, якщо в пулі є 100 внесення та 100 вилучень, хоча дії є загальнодоступними, здається, що між ними немає зв'язку. Усі вносять та знімають однакову суму, що ускладнює відстеження руху коштів. Очевидно, це надає вроджену перевагу для відмивання грошей.
Виникає ключове питання: як підтвердити свій попередній депозит при виведенні? Адреса, що ініціює виведення, не пов'язана з жодною адресою депозиту, тому як підтвердити право на виведення? Найбільш прямий метод - це засвідчення виведенням свого депозитного запису, але це викрило б їхню особистість. Ось де відбуваються докази знання.
З допомогою ZK Proof вивідник може підтвердити, що у нього є запис про депозит в контракті Tornado, і цей депозит ще не був виведений. Краса доказів з нульовим знанням полягає в тому, що вони зберігають конфіденційність. Громадськість знає лише те, що вивідник справді зробив депозит, але не може визначити його конкретну особу.
Щоб довести, що «Я здійснив депозит у басейні Торнадо», можна перекласти як «Мій запис про депозит можна знайти в контракті Торнадо». Якщо Cn позначає запис про депозит, то, з урахуванням набору записів про депозит Торнадо як {C1, C2,…C100…}, Боб повинен довести, що він використовував свій приватний ключ для створення запису в цьому наборі, не розголошуючи, який саме Cn це. Це використовує унікальні властивості доказу Меркля.
Всі записи про депозити Tornado агрегуються в побудоване на ланцюжку даних дерево Меркля. Більшість цих листків (близько 2^20, понад 1 мільйон) залишаються порожніми (з початковим значенням). Кожен новий депозит оновлює відповідний комітмент-листок, а потім корінь дерева.
Наприклад, якщо депозит Боба був десятитисячним в історії Торнадо, пов'язане значення Cn буде десятитисячним листом дерева, тобто C10000 = Cn. Після цього контракт автоматично обчислить новий корінь.
(джерело: RareSkills)
Доказ Меркле сам по собі є лаконічним та ефективним. Щоб довести, що транзакція TD існує в Мерклівському дереві, потрібно лише надати пов'язане доказ Меркле, який залишається компактним навіть якщо Мерклівське дерево велике.
Щоб підтвердити, що транзакція, скажімо, H3, дійсно включена в дерево Меркла, потрібно довести, що за допомогою H3 та інших даних з дерева Меркла можна згенерувати корінь. Ці дані (включаючи Td) складають Мерклів доказ. Коли Боб хоче зняти гроші, йому потрібно перевірити дві речі:
·Cn знаходиться в дереві Меркла, побудованому на ланцюжку блоків Tornado, для якого він може скласти доказ Меркла, що містить Cn;
·Cn пов'язано з депозитним ваучером Боба.
У фронтенд-коді інтерфейсу користувача Tornado було попередньо реалізовано численні функціональності. Коли вкладник відкриває веб-сторінку Tornado Cash та натискає кнопку внесення, прикріплений фронтенд-код генерує два випадкових числа, K та r, локально. Потім він обчислює значення Cn=Hash(K, r) та передає Cn (що називається зобов'язанням на діаграмі нижче) в контракт Tornado для включення в його дерево Меркля. Просто кажучи, K та r виступають як приватні ключі. Вони є критичними, тому користувачам рекомендується зберігати їх безпечно, оскільки вони знову знадобляться під час процесу зняття коштів.
Зашифрована нотатка - це необов'язкова функція, яка дозволяє користувачам зашифрувати облікові дані K та r за допомогою приватного ключа та зберегти їх у ланцюжку, щоб уникнути забуття.
Важливо, що всі вищезазначені операції відбуваються офлайн, що означає, що ані контракт Tornado, ані будь-які зовнішні спостерігачі не знають про K та r. Якщо K та r будуть викриті, це схоже на те, що приватний ключ гаманця був вкрадений.
Отримавши депозит користувача та обчисливши Cn=Hash(K, r), контракт Tornado розміщує Cn на базовому рівні дерева Меркля, перетворюючи його на новий листок, а потім оновлює значення кореня. Проте важливо зрозуміти, що листки цього дерева Меркля не включені в стан контракту, а лише записані як параметри подій у минулих блоках. Контракт Tornado записує лише корінь Меркля. Під час виведення користувачі можуть довести, за допомогою доказу Меркля, що запис депозиту відповідає поточному кореню Меркля, концепція якої дещо нагадує зняття легкого клієнта через міст між ланцюжками. Цей дизайн розкриває винахідливість Tornado: для зекономлення газових витрат повний обсяг дерева Меркля не записується в стані контракту, записується лише його корінь. Листки дерева просто записані в історичних блоках, механізм який дещо схожий на принцип зекономлення газу Rollup (хоча деталі відрізняються).
Під час процесу виведення вивідник вводить облікові дані/приватні ключі (випадкові числа K та r, згенеровані під час депозиту) на веб-сторінці фронтенду. Код фронтенду Tornado Cash використовує K та r, Cn=Hash(K, r), та доказ Меркла, відповідний Cn, для генерації доказу ZK, тим самим підтверджуючи, що Cn відповідає запису про депозит в Мерклівському дереві, та що K та r є дійсними обліковими даними для Cn. Цей крок суттєво доводить знання ключів запису про депозит в Мерклівському дереві. Коли доказ ZK подається до контракту Tornado, всі чотири параметри приховані, забезпечуючи незнання сторонніми особами, включаючи сам контракт Tornado, тим самим забезпечуючи конфіденційність користувача.
Цікавою деталлю є те, що операція депозиту використовує два випадкових числа, K та r, для генерації Cn замість одного, оскільки одне випадкове число може бути недостатньо безпечним і потенційно його можна брутфорсити.
Щодо символу "A" на ілюстрації, він представляє адресу отримання виведення та надається тим, хто виводить кошти. Тим часом "nf" - це ідентифікатор, встановлений для запобігання атак на повторне відтворення, його значення визначається як nf=Hash(K), де K - одне з двох випадкових чисел (K та r), які використовуються під час поповнення для генерації Cn. Таким чином, кожен Cn має відповідний nf, і вони унікально пов'язані.
Чому потрібно запобігати атакам повторення? У зв'язку з особливостями дизайну міксера під час виведення неясно, якому депозиту у дереві Меркла відповідають зняті кошти. Оскільки зв'язок між депозитарієм та знятими сумами залишається невизначеним, зловживаючі користувачі можуть використовувати це і повторно знімати кошти з міксера, висушуючи пул токенів.
Тут ідентифікатор nf працює аналогічно лічильнику транзакцій 'nonce', що властивий кожній адресі Ethereum, створений для запобігання повторних транзакцій. При запиті на виведення користувачам необхідно надати nf. Система перевіряє, чи цей nf вже використовувався раніше: якщо так, виведення анулюється; якщо ні, виведення відбувається, і nf записується, забезпечуючи, що його подальше використання призведе до анулювання.
Деякі можуть запитати: Чи може хтось вигадати nf, який контракт не зафіксував? Це малоймовірно. Під час генерації доказу ZK важливо забезпечити, що nf=Hash(K), а випадкове число K пов'язане з записом депозиту Cn. Якщо хтось довільно створить nf, воно не буде відповідати жодному з зафіксованих депозитів, що ускладнить генерацію дійсного доказу ZK, і внаслідок цього зупинить процес виведення коштів.
Інші можуть запитати: Чи є спосіб обійти використання nf? Оскільки вивідники повинні надати доказ ZK, який підтверджує їх зв'язок з певним Cn, чи не буде достатньо перевірити, чи вже був зареєстрований відповідний доказ ZK на ланцюжку? Однак витрати, пов'язані з таким підходом, є надзвичайно великими, оскільки контракт Tornado Cash не постійно зберігає раніше надані докази ZK, щоб уникнути втрати простору. Порівнювати кожен новий доказ ZK з наявними, щоб забезпечити послідовність, вимагає набагато більше ресурсів, ніж просто реєструвати компактний ідентифікатор, подібний до nf.
Згідно з прикладом коду функції виведення, необхідні параметри та бізнес-логіка виглядають наступним чином: користувачі надсилають доказ ZK, nf (NullifierHash) = Hash(K), та вказують адресу отримувача для виведення. Доказ ZK приховує значення Cn, K, та r, забезпечуючи нездатність зовнішньому світу визначити ідентичність користувача. Зазвичай отримувачі вказують чисту, нову адресу, щоб уникнути розголошення особистої інформації.
Проте виникає невелике виклик: коли користувачі виводять кошти, на користь ненаслідовності, вони часто використовують нові адреси для ініціювання транзакції зняття. У такі моменти ці нові адреси не мають ETH для покриття комісій за газ. Тому під час виведення адреса повинна явно заявити релею, щоб покрити витрати на газ. Після цього контракт змішування відраховує частину від зняття користувача для компенсації релею.
Підсумовуючи, Tornado Cash може приховати зв'язок між вкладниками та тими, хто виводить кошти. Коли є велика база користувачів, це схоже на злочинця, який зливається з галасливим натовпом, що ускладнює відстеження для влади. У процесі відкликання використовується ZK-SNARK, при цьому прихована частина «свідка» містить ключову інформацію про того, хто відкликає. Це, мабуть, найважливіша функція мікшера. В даний час Tornado може бути одним з найрозумніших додатків, пов'язаних з ZK.
مشاركة
Вступ:
Недавно Виталик та кілька вчених спільно опублікували нову статтю, в якій доторкаються до того, як Tornado Cash реалізує свою схему протидії відмиванню грошей (забезпечуючи можливість вилучення для доведення того, що їх історія депозитів належить до набору, який не містить забруднених коштів). Однак у статті бракувало складного пояснення бізнес-логіки та принципів Tornado Cash, що залишило деяких читачів лише з поверхневим розумінням.
Варто зазначити, що проекти, подібні до Tornado, які представляють конфіденційні підприємства, дійсно використовують аспект нуль-знань алгоритму ZK-SNARK. Тим часом більшість рішень, які мають прапорець ZK, такі як Rollups, просто використовують стислість ZK-SNARK. Часто люди схильні сплутувати Доказ Правильності з ZK, і Tornado служить відмінним прикладом для пояснення практичного застосування ZK.
Автор цього статті написав статтю про принципи Торнадо ще у 2022 році для дослідження Web3Caff. Сьогодні ми витягли і розширили деякі розділи оригінальної роботи, щоб забезпечити систематичне розуміння Tornado Cash.
Посилання на оригінальну статтю:https://research.web3caff.com/zh/archives/2663?ref=157
Tornado Cash використовує докази з нульовим відкриттям як свій протокол змішування. У той час як його старша версія була запущена у 2019 році, бета-версія оновленої моделі була випущена наприкінці 2021 року. Ранішня версія Tornado досягла високого рівня децентралізації завдяки тому, що у цілому контракти були відкриті для перегляду та були вільні від контролю багато-підписових операцій. Крім того, код фронтенду був відкритим та зберігався в мережі IPFS. Через простоту старої версії Tornado ця стаття зосереджена на її поясненні.
Основний підхід Tornado полягає в тому, щоб змішати численні операції збереження та виведення разом. Після того як Токени було внесено в Tornado, депоненти представляють ZK Proof, щоб перевірити свій попередній депозит, а потім здійснюють виведення за допомогою нової адреси, тим самим руйнуючи зв'язок між адресами депозиту та виведення.
Щоб сказати коротко, уявіть Торнадо як скляний ящик, заповнений монетами (Coins), які внесли багато людей. Ми бачимо, хто вніс монети, але ці монети дуже однорідні. Якщо хтось незнайомий взяв би монету з коробки, було б важко відслідкувати, хто спочатку поклав цю монету туди.
(джерело зображення: rareskills)
Такі сценарії здаються звичайними. Коли ми обмінюємо кілька ETH з пулу Uniswap, неможливо визначити, чиї ETH ми отримали, враховуючи велику кількість постачальників ліквідності для Uniswap. Однак відмінність полягає в процесі. З Uniswap, обмін токенів вимагає інший токен на еквівалентну вартість, і кошти не можуть бути "приватно" перекладені. На відміну від цього, міксер просто вимагає від забирача пред'явити свій квиток про внесення.
Щоб зробити вигляд однорідними дії з внесення та зняття коштів, пул Tornado зберігає послідовність сум внесків та зняттів. Наприклад, якщо в пулі є 100 внесення та 100 вилучень, хоча дії є загальнодоступними, здається, що між ними немає зв'язку. Усі вносять та знімають однакову суму, що ускладнює відстеження руху коштів. Очевидно, це надає вроджену перевагу для відмивання грошей.
Виникає ключове питання: як підтвердити свій попередній депозит при виведенні? Адреса, що ініціює виведення, не пов'язана з жодною адресою депозиту, тому як підтвердити право на виведення? Найбільш прямий метод - це засвідчення виведенням свого депозитного запису, але це викрило б їхню особистість. Ось де відбуваються докази знання.
З допомогою ZK Proof вивідник може підтвердити, що у нього є запис про депозит в контракті Tornado, і цей депозит ще не був виведений. Краса доказів з нульовим знанням полягає в тому, що вони зберігають конфіденційність. Громадськість знає лише те, що вивідник справді зробив депозит, але не може визначити його конкретну особу.
Щоб довести, що «Я здійснив депозит у басейні Торнадо», можна перекласти як «Мій запис про депозит можна знайти в контракті Торнадо». Якщо Cn позначає запис про депозит, то, з урахуванням набору записів про депозит Торнадо як {C1, C2,…C100…}, Боб повинен довести, що він використовував свій приватний ключ для створення запису в цьому наборі, не розголошуючи, який саме Cn це. Це використовує унікальні властивості доказу Меркля.
Всі записи про депозити Tornado агрегуються в побудоване на ланцюжку даних дерево Меркля. Більшість цих листків (близько 2^20, понад 1 мільйон) залишаються порожніми (з початковим значенням). Кожен новий депозит оновлює відповідний комітмент-листок, а потім корінь дерева.
Наприклад, якщо депозит Боба був десятитисячним в історії Торнадо, пов'язане значення Cn буде десятитисячним листом дерева, тобто C10000 = Cn. Після цього контракт автоматично обчислить новий корінь.
(джерело: RareSkills)
Доказ Меркле сам по собі є лаконічним та ефективним. Щоб довести, що транзакція TD існує в Мерклівському дереві, потрібно лише надати пов'язане доказ Меркле, який залишається компактним навіть якщо Мерклівське дерево велике.
Щоб підтвердити, що транзакція, скажімо, H3, дійсно включена в дерево Меркла, потрібно довести, що за допомогою H3 та інших даних з дерева Меркла можна згенерувати корінь. Ці дані (включаючи Td) складають Мерклів доказ. Коли Боб хоче зняти гроші, йому потрібно перевірити дві речі:
·Cn знаходиться в дереві Меркла, побудованому на ланцюжку блоків Tornado, для якого він може скласти доказ Меркла, що містить Cn;
·Cn пов'язано з депозитним ваучером Боба.
У фронтенд-коді інтерфейсу користувача Tornado було попередньо реалізовано численні функціональності. Коли вкладник відкриває веб-сторінку Tornado Cash та натискає кнопку внесення, прикріплений фронтенд-код генерує два випадкових числа, K та r, локально. Потім він обчислює значення Cn=Hash(K, r) та передає Cn (що називається зобов'язанням на діаграмі нижче) в контракт Tornado для включення в його дерево Меркля. Просто кажучи, K та r виступають як приватні ключі. Вони є критичними, тому користувачам рекомендується зберігати їх безпечно, оскільки вони знову знадобляться під час процесу зняття коштів.
Зашифрована нотатка - це необов'язкова функція, яка дозволяє користувачам зашифрувати облікові дані K та r за допомогою приватного ключа та зберегти їх у ланцюжку, щоб уникнути забуття.
Важливо, що всі вищезазначені операції відбуваються офлайн, що означає, що ані контракт Tornado, ані будь-які зовнішні спостерігачі не знають про K та r. Якщо K та r будуть викриті, це схоже на те, що приватний ключ гаманця був вкрадений.
Отримавши депозит користувача та обчисливши Cn=Hash(K, r), контракт Tornado розміщує Cn на базовому рівні дерева Меркля, перетворюючи його на новий листок, а потім оновлює значення кореня. Проте важливо зрозуміти, що листки цього дерева Меркля не включені в стан контракту, а лише записані як параметри подій у минулих блоках. Контракт Tornado записує лише корінь Меркля. Під час виведення користувачі можуть довести, за допомогою доказу Меркля, що запис депозиту відповідає поточному кореню Меркля, концепція якої дещо нагадує зняття легкого клієнта через міст між ланцюжками. Цей дизайн розкриває винахідливість Tornado: для зекономлення газових витрат повний обсяг дерева Меркля не записується в стані контракту, записується лише його корінь. Листки дерева просто записані в історичних блоках, механізм який дещо схожий на принцип зекономлення газу Rollup (хоча деталі відрізняються).
Під час процесу виведення вивідник вводить облікові дані/приватні ключі (випадкові числа K та r, згенеровані під час депозиту) на веб-сторінці фронтенду. Код фронтенду Tornado Cash використовує K та r, Cn=Hash(K, r), та доказ Меркла, відповідний Cn, для генерації доказу ZK, тим самим підтверджуючи, що Cn відповідає запису про депозит в Мерклівському дереві, та що K та r є дійсними обліковими даними для Cn. Цей крок суттєво доводить знання ключів запису про депозит в Мерклівському дереві. Коли доказ ZK подається до контракту Tornado, всі чотири параметри приховані, забезпечуючи незнання сторонніми особами, включаючи сам контракт Tornado, тим самим забезпечуючи конфіденційність користувача.
Цікавою деталлю є те, що операція депозиту використовує два випадкових числа, K та r, для генерації Cn замість одного, оскільки одне випадкове число може бути недостатньо безпечним і потенційно його можна брутфорсити.
Щодо символу "A" на ілюстрації, він представляє адресу отримання виведення та надається тим, хто виводить кошти. Тим часом "nf" - це ідентифікатор, встановлений для запобігання атак на повторне відтворення, його значення визначається як nf=Hash(K), де K - одне з двох випадкових чисел (K та r), які використовуються під час поповнення для генерації Cn. Таким чином, кожен Cn має відповідний nf, і вони унікально пов'язані.
Чому потрібно запобігати атакам повторення? У зв'язку з особливостями дизайну міксера під час виведення неясно, якому депозиту у дереві Меркла відповідають зняті кошти. Оскільки зв'язок між депозитарієм та знятими сумами залишається невизначеним, зловживаючі користувачі можуть використовувати це і повторно знімати кошти з міксера, висушуючи пул токенів.
Тут ідентифікатор nf працює аналогічно лічильнику транзакцій 'nonce', що властивий кожній адресі Ethereum, створений для запобігання повторних транзакцій. При запиті на виведення користувачам необхідно надати nf. Система перевіряє, чи цей nf вже використовувався раніше: якщо так, виведення анулюється; якщо ні, виведення відбувається, і nf записується, забезпечуючи, що його подальше використання призведе до анулювання.
Деякі можуть запитати: Чи може хтось вигадати nf, який контракт не зафіксував? Це малоймовірно. Під час генерації доказу ZK важливо забезпечити, що nf=Hash(K), а випадкове число K пов'язане з записом депозиту Cn. Якщо хтось довільно створить nf, воно не буде відповідати жодному з зафіксованих депозитів, що ускладнить генерацію дійсного доказу ZK, і внаслідок цього зупинить процес виведення коштів.
Інші можуть запитати: Чи є спосіб обійти використання nf? Оскільки вивідники повинні надати доказ ZK, який підтверджує їх зв'язок з певним Cn, чи не буде достатньо перевірити, чи вже був зареєстрований відповідний доказ ZK на ланцюжку? Однак витрати, пов'язані з таким підходом, є надзвичайно великими, оскільки контракт Tornado Cash не постійно зберігає раніше надані докази ZK, щоб уникнути втрати простору. Порівнювати кожен новий доказ ZK з наявними, щоб забезпечити послідовність, вимагає набагато більше ресурсів, ніж просто реєструвати компактний ідентифікатор, подібний до nf.
Згідно з прикладом коду функції виведення, необхідні параметри та бізнес-логіка виглядають наступним чином: користувачі надсилають доказ ZK, nf (NullifierHash) = Hash(K), та вказують адресу отримувача для виведення. Доказ ZK приховує значення Cn, K, та r, забезпечуючи нездатність зовнішньому світу визначити ідентичність користувача. Зазвичай отримувачі вказують чисту, нову адресу, щоб уникнути розголошення особистої інформації.
Проте виникає невелике виклик: коли користувачі виводять кошти, на користь ненаслідовності, вони часто використовують нові адреси для ініціювання транзакції зняття. У такі моменти ці нові адреси не мають ETH для покриття комісій за газ. Тому під час виведення адреса повинна явно заявити релею, щоб покрити витрати на газ. Після цього контракт змішування відраховує частину від зняття користувача для компенсації релею.
Підсумовуючи, Tornado Cash може приховати зв'язок між вкладниками та тими, хто виводить кошти. Коли є велика база користувачів, це схоже на злочинця, який зливається з галасливим натовпом, що ускладнює відстеження для влади. У процесі відкликання використовується ZK-SNARK, при цьому прихована частина «свідка» містить ключову інформацію про того, хто відкликає. Це, мабуть, найважливіша функція мікшера. В даний час Tornado може бути одним з найрозумніших додатків, пов'язаних з ZK.