Как создавать приложения для обеспечения приватности в Эфириуме с использованием доказательств с нулевым разглашением

Эфириум по своей архитектуре радикально публичен. Каждый адрес, баланс, транзакция, вызов контракта и событие видны любому, у кого есть обозреватель блоков. Эта прозрачность полезна, когда вам нужна проверяемость. Но это становится проблемой, когда пользователям нужно проголосовать, востребовать токены, осуществить вывод или доказать членство, не связывая каждое действие с одним и тем же кошельком.
Анонимное членство — это переиспользуемый шаблон, который лежит в основе большого класса приложений для обеспечения приватности в Эфириуме. Сначала люди регистрируются, а затем доказывают свою принадлежность к группе, не раскрывая, кем именно из участников они являются. Доказательство с нулевым разглашением — это мост между кошельком регистрации и кошельком, выполняющим действие, и этот мост не раскрывает, кто по нему прошел.
Окружающий продукт меняется, но скелет приватности остается прежним.
Шаблон на примере анонимного голосования
Шаблон состоит из трех частей. Коммитмент регистрирует каждого участника. Дерево Меркла превращает эти коммитменты в толпу. Доказательство и нуллификатор позволяют одному участнику совершить действие один раз, не раскрывая, кто именно его совершил.
Шаг первый: регистрация
Каждый голосующий создает два приватных значения офчейн: секрет и нуллификатор. Голосующий хеширует эти значения в публичный коммитмент, а затем регистрирует этот коммитмент ончейн.
Коммитмент — это публичная запись о регистрации. Секрет и нуллификатор — это приватная заметка, которая понадобится голосующему позже. Если потерять эту заметку, голосующий не сможет доказать членство. Если произойдет ее утечка, кто-то другой сможет проголосовать вместо пользователя.
Поскольку коммитмент представляет собой хеш, наблюдатели не могут восстановить скрытые в нем приватные значения. Коммитмент говорит о том, что «кто-то зарегистрировался», не раскрывая, кто именно позже воспользуется этой регистрацией.
Шаг второй: формирование толпы
По мере регистрации новых голосующих приложение собирает их коммитменты в дерево Меркла. Дерево Меркла сжимает длинный список значений в один хеш, называемый корнем. Если изменить любое значение в списке, хеш изменится, поэтому корень действует как защищенная от несанкционированного доступа сводка всего набора.
Это дерево и есть ваш набор анонимности. Если в дереве десять пользователей, наблюдатель может сузить круг лиц, совершивших последующее действие, до одного из этих десяти. Если в дереве десять тысяч пользователей, связать действие с одним человеком гораздо сложнее. Приватное приложение с крошечным набором анонимности обычно не является по-настоящему приватным, даже если криптография реализована верно.
Шаг третий: анонимное действие
Когда открывается голосование, голосующий не должен голосовать с того же кошелька, с которого был зарегистрирован коммитмент. Голосование с кошелька регистрации напрямую свяжет голос с регистрантом и сведет на нет всю работу по обеспечению приватности. Вместо этого голосующий создает доказательство с нулевым разглашением. Утверждение кодируется в виде схемы, которая гласит: «Я знаю приватные значения, которые создают зарегистрированный коммитмент, и я раскрываю правильный хеш нуллификатора для этого голосования».
Доказательство убеждает контракт верификатора в том, что утверждение истинно. Оно не раскрывает ни секрет, ни нуллификатор, ни то, какой именно коммитмент был использован.
Нуллификатор — это то, что предотвращает двойное голосование. Вместе с доказательством голосующий публикует хеш нуллификатора. Контракт голосования сохраняет этот хеш после принятия голоса. Если та же приватная заметка будет использована снова для того же голосования, она выдаст тот же хеш нуллификатора, и контракт отклонит второй голос. В сочетании с доказательством это приводит к тому, что контракт знает лишь то, что какой-то зарегистрированный избиратель совершил действие один раз, но не знает, кто именно.
Универсальный шлюз
Та же самая пара из доказательства и нуллификатора работает не только для голосования. Если отбросить сценарий с голосованием, вы получите шлюз приватности для функций смарт-контракта.
Перед выполнением функции контракт проверяет корень Меркла, верифицирует доказательство, подтверждает, что хеш нуллификатора не был использован, и привязывает публичные входные данные к нужному приложению, цепи, голосованию, востребованию или выводу. Если эти проверки проходят успешно, он помечает нуллификатор как использованный и выполняет оставшуюся часть функции.
Поставьте этот шлюз перед голосованием, и вы получите анонимное голосование. Поставьте его перед востребованием эирдропа, и вы получите анонимные востребования. Поставьте его перед функцией вывода, и вы получите основу процесса вывода в стиле миксера. То же дерево коммитментов, та же идея нуллификатора, тот же шаблон доказательства. Меняется лишь тело функции и окружающая логика приложения.
Что и где выполняется
Приватная работа обычно происходит офчейн. Пользователь хранит заметку, а клиентское приложение создает свидетеля и запускает прувер для создания доказательства. Индексатор отслеживает коммитменты и корни Меркла. Бандлер распространяет пользовательскую операцию (UserOperation) ончейн, а пеймейстер ERC-4337 спонсирует газ, поэтому новому кошельку не нужно предварительно получать ETH с известного кошелька пользователя.
Публичное принудительное исполнение происходит ончейн. Контракт верификатора проверяет доказательство. Контракт приложения проверяет действительные корни и неиспользованные нуллификаторы, сохраняет хеш нуллификатора и выполняет публичное действие.
Чувствительной частью пользовательского опыта (UX) является обращение с заметкой. Относитесь к секрету и нуллификатору как к ключам. Не помещайте их в аналитику, журналы, URL-адреса, отчеты об ошибках или обычную серверную телеметрию. Как только произойдет утечка заметки, приватность исчезнет, независимо от того, насколько надежно доказательство.
Инструментарий достиг нужного уровня
Вам не нужно писать базовую криптографию вручную. Обычный путь — написать схему на высокоуровневом языке с нулевым разглашением, сгенерировать верификатор на Solidity и вызвать этот верификатор из контракта приложения.
Подходящий стек зависит от задачи. Circom с snarkjs — это давно зарекомендовавший себя путь для схем на уровне приложений. Noir с Barretenberg — более новый и удобный для разработчиков путь. Halo2 и gnark — это библиотеки схем более низкого уровня. zkVM, такие как RISC Zero или SP1, доказывают обычные программы, но их доказательство может быть дороже, чем у небольшой пользовательской схемы.
Для анонимного членства воспользуйтесь существующим протоколом, прежде чем писать собственную схему. Semaphore упаковывает групповое членство и предотвращение двойного использования на основе нуллификаторов в контракты и библиотеки JavaScript. Для приватного голосования и управления специализированным путем является MACI, поскольку он добавляет свойства защиты от сговора. Зрелые протоколы часто безопаснее новых схем.
Одного доказательства недостаточно
Даже идеальное доказательство потерпит неудачу, если процесс работы с кошельком выдаст связь. Зарегистрируйтесь с кошелька A, а затем совершите действие с кошелька A, и любой наблюдатель сможет связать эти транзакции. Пополните кошелек B с кошелька A прямо перед действием, и эта транзакция пополнения создаст ту же проблему.
Вот почему важны бандлеры и пеймейстеры. Кошелек, выполняющий действие, должен быть новым, и ему не должно требоваться получение ETH с кошелька, который пользователь пытается отделить от этого действия.
Та же проблема существует и офчейн. Отправка транзакций регистрации и действия с одного и того же IP-адреса, RPC-провайдера или сессии может ослабить приватность, обеспечиваемую схемой. Фронтенды могут допускать утечки через аналитику, локальное хранилище и журналы поддержки. Доказательство с нулевым разглашением скрывает значения внутри самого доказательства. Оно не скрывает все, что окружает транзакцию.
Публичные входные данные — еще одно место, где приложения для обеспечения приватности терпят неудачу. Все, что отмечено как публичное в схеме, выпущено как событие, включено в данные вызова (calldata) или сохранено контрактом, является видимым. Проверяйте публичные входные данные так же тщательно, как и контроль доступа в смарт-контракте на Solidity.
Что это меняет для разработчиков
Приватность в Эфириуме готова к внедрению. Разработчики могут собирать эти элементы в реальные приложения. Стек состоит из схемы для приватного утверждения, верификатора для проверки доказательства, контракта приложения для публичных правил, индексатора для данных Меркла, а также бандлера и пеймейстера для несвязываемой отправки и спонсирования газа.
Самое сложное — это дизайн продукта, управление ключами, гигиена метаданных, аудиты и увеличение набора анонимности. Ошибитесь в любом из этих пунктов, и приватность, которую давало доказательство, исчезнет.
Дополнительная литература
- Доказательства с нулевым разглашением (ethereum.org) (opens in a new tab)
- Документация Semaphore (opens in a new tab)
- Документация MACI (opens in a new tab)
- Документация Circom (opens in a new tab)
- Документация Noir (opens in a new tab)
- Книга по Halo2 (opens in a new tab)
- Документация gnark (opens in a new tab)
- Документация RISC Zero (opens in a new tab)
- Документация SP1 (opens in a new tab)
- EIP-4337: Абстракция учетной записи через контракт EntryPoint (opens in a new tab)
Последнее обновление страницы: 28 мая 2026 г.