Смарт-контракт с использованием zk-SNARKs
Например, у нас есть секретная информация, скажем, пароль. Мы хотим доказать другому человеку, что у нас есть этот пароль, но не хотим раскрывать сам пароль. С использованием zk-SNARKs, мы сможем сгенерировать доказательство, подтверждающее, что у нас есть знание о пароле, но при этом сам пароль будет оставаться скрытым. Это обеспечит доказуемую аутентификацию без необходимости раскрывать секретную информацию.
Поскольку смарт-контракты могут раскрывать значения, а нам необходимо хранить пароль в секрете. Для этого обратимся к ZoKrates.
ZoKrates - набор инструментов которые упрощает разработку и развертывание программ доказательства с нулевым разглашением, специально разработанных для использования на Ethereum.
- Плагин в Remix IDE предоставляет создание и верификацию zk-SNARKs.
- ZoKrates Playground - веб-игровая площадка, где разработчики могут писать и компилировать программы онлайн. Playground включает в себя редактор кода, компилятор и инструменты для создания и проверки доказательств.
- Установить ZoKrates локально с помощью менеджеров пакетов, таких как npm, или загрузив двоичный файл непосредственно из репозитория ZoKrates GitHub.
- Контейнер Docker: ZoKrates также предоставляет контейнер Docker, который можно использовать для запуска программ ZoKrates в виртуализированной среде. Эта опция полезна для разработчиков, которые не хотят устанавливать ZoKrates локально и предпочитают использовать стандартизированную среду.
docker run -ti zokrates/zokrates /bin/bash
- ZoKrates — использует программы на предметно-ориентированном языке (DSL) высокого уровня.
- ZoKrates DSL похож на язык программирования C (Си) включает переменные, циклы и условные операторы.
- Использует libsnark, библиотеку C++ zkSNARKs, для генерации доказательств и ключей проверки.
- Поддерживает криптографию на основе эллиптических кривых, модульную арифметику, хеш-функции и другие криптографические операции.
- Использует систему доказательств Groth16 для быстрого и эффективного создания и проверки ZKP.
- Имеет лицензию MIT и представляет собой проект с открытым исходным кодом.
Журнал изменений ZoKrates
Рассмотрим пример, где у нас есть секретное значение x а у нашего товарища Жака такое хэш-значение: y = H(x)
При использовании 256-битного хэш, практически нет шансов, что мы когда-либо узнаем значение x, зная только значение y. Таким образом, x может быть паролем. Итак, посмотрим, сможем ли мы доказать x, зная H(x) и запустить смарт-контракт.
1) В ZoKrates Playground напишем следующий код:
import "hashes/sha256/512bitPacked" as sha256packed;
def main(private field a, private field b, private field c, private field d) -> field[2] {
field[2] h = sha256packed([a, b, c, d]);
return h;
}Первая строка импортируетsha256packedфункцию из стандартной библиотеки ZoKrates.sha256packed— это реализация SHA256, оптимизированная для использования в ZoKrates DSL. Вот как это работает: мы хотим передать 512 бит входных данных в SHA256. Однакоfieldзначение может содержать только 254 бита из-за размера основного поля, которое мы используем. Как следствие, мы используем четыре элемента поля, каждый из которых кодирует 128 бит, для представления наших входных данных. Затем четыре элемента объединяются в ZoKrates и передаются в SHA256. Учитывая, что длина полученного хеша составляет 256 бит, то он делится на две части и возвращает каждое значение как 128-битное число.
Переходим во вкладку Execute и нажимаем Run
[ "71860681579908444993719277659355514616", "203894998809118867442052767119280883826" ]2) Создадим доказательство с нулевым разглашением.
2.1) В Remix IDE cоздадим фаил main.zok и напишем следующий код:
import "hashes/sha256/512bitPacked" as sha256packed;
def main(private field a, private field b, private field c, private field d) {
field[2] h = sha256packed([a, b, c, d]);
assert(h[0] == 71860681579908444993719277659355514616);
assert(h[1] == 203894998809118867442052767119280883826);
return;
}Код использует библиотеку sha256packed для вычисления хеша SHA-256 от четырех приватных полей a, b, c и d. Затем программа проверяет, что вычисленный хеш совпадает с ожидаемыми значениями, и возвращает ошибку, если это не так. В данном случае программа проверяет, что вычисленный хеш (полученный ранее в п.1) равен 71860681579908444993719277659355514616 для h0 и 203894998809118867442052767119280883826 для h1. Если это условие выполняется, то программа завершается успешно, иначе возникает ошибка.
2.2) Добавим плагин ZoKrates в Remix IDE
2.3) Компиляция: на левой боковой панели кнопка компиляции. Если ошибки нет, можем двигаться дальше.
2.4) Вычисление свидетеля для которого предоставлены действительные частные значения (наш пароль) Уже на этой стадии пароль изменить не сможем т.к. хеш к этому паролю скомпилирован.
Свидетель – представляет собой набор данных, который подтверждает истинность скрытой информации, не раскрывая конфиденциальности. Необходим для доказательства, что держатель этой информации обладает знанием о ней, но не раскрывает саму информацию.
К примеру удаляем одну цифру - Execution failed
2.5) Run Setup (cоздать доказательство). Используем свидетель для создания доказательства, которое демонстрирует достоверность вычислений без раскрытия частных входных данных. После вычисления мы можем сгенерировать проверочный и подтверждающий ключ. Это может занять больше минуты, но выполняется только один раз. Эти ключи получены из источника случайности, обычно называемого «токсичными отходами». Мы увидим, что создался файл с именем verification_key.json, который содержит все эти данные.
2.6) Generate Proof - имея ключи верификатора, а также свидетель, мы теперь можем сгенерировать наше доказательство:
Теперь у нас есть проверяющее доказательство (proof.js)
{
"scheme": "g16",
"curve": "bn128",
"proof": {
"a": [
"0x0ac917308a7b8db29288c028109c8617f910f6b6843c975a736374ddbc276797",
"0x1960e7c91c4bb774e6308c418615d566280679a5b7c18b45f89ab64098187bdf"
],
"b": [
[
"0x2df5af53473f2343c58091e657898f92b5b7f0b88a6ea7514c9952a47e07f444",
"0x0121a9c22c2abafb7dee637ef4f743a4d62798835350d042d55c708d2481fe3d"
],
[
"0x1e46763eeacc9f85215740e3d3f7eaddc2fca5c8115c282be1e60157740bcec8",
"0x23d8a13843a39d8f37b8a0ef6da31281b7ee2c61d16079a48f2620b9f6ef9aa0"
]
],
"c": [
"0x2f990abf7f96daee712f3ca282e7e304370ac70d633b6156a41b91f140e6cb41",
"0x0e619f6d20fc6c39fa3fa0320c795e57218824f1f11ee90b0d7edf3a306de8fd"
]
},
"inputs": []
}[["0x0ac917308a7b8db29288c028109c8617f910f6b6843c975a736374ddbc276797","0x1960e7c91c4bb774e6308c418615d566280679a5b7c18b45f89ab64098187bdf"],[["0x2df5af53473f2343c58091e657898f92b5b7f0b88a6ea7514c9952a47e07f444","0x0121a9c22c2abafb7dee637ef4f743a4d62798835350d042d55c708d2481fe3d"],["0x1e46763eeacc9f85215740e3d3f7eaddc2fca5c8115c282be1e60157740bcec8","0x23d8a13843a39d8f37b8a0ef6da31281b7ee2c61d16079a48f2620b9f6ef9aa0"]],["0x2f990abf7f96daee712f3ca282e7e304370ac70d633b6156a41b91f140e6cb41","0x0e619f6d20fc6c39fa3fa0320c795e57218824f1f11ee90b0d7edf3a306de8fd"]]
2.7) Export Verifier - генерирует контракт Solidity, который включает ключ проверки. Этот контракт предоставляет общедоступную функцию для проверки решений скомпилированной программы. Это обеспечивает независимую проверку правильности и повышает прозрачность в системах с нулевым разглашением данных.
3) Проверка доказательства с нулевым разглашением.
3.1) Компилируем verifier.sol После развертывания контракт верификатора можно использовать для проверки решений скомпилированной программы.
3.2) Развертывание смарт-контракта verifier.sol
[["0x0ac917308a7b8db29288c028109c8617f910f6b6843c975a736374ddbc276797","0x1960e7c91c4bb774e6308c418615d566280679a5b7c18b45f89ab64098187bdf"],[["0x2df5af53473f2343c58091e657898f92b5b7f0b88a6ea7514c9952a47e07f444","0x0121a9c22c2abafb7dee637ef4f743a4d62798835350d042d55c708d2481fe3d"],["0x1e46763eeacc9f85215740e3d3f7eaddc2fca5c8115c282be1e60157740bcec8","0x23d8a13843a39d8f37b8a0ef6da31281b7ee2c61d16079a48f2620b9f6ef9aa0"]],["0x2f990abf7f96daee712f3ca282e7e304370ac70d633b6156a41b91f140e6cb41","0x0e619f6d20fc6c39fa3fa0320c795e57218824f1f11ee90b0d7edf3a306de8fd"]]
ZoKrates может генерировать большие ключи подтверждений и проверки, особенно для более сложных вычислений. Размер доказательств, может потенциально достигать нескольких мегабайт.
3.3) Вставляем доказательство в поле, а затем протестируем: должно быть написано «0»: «bool: r true». Это означает, что транзакция успешно подтверждена.
Но если мы воспользуемся неверным доказательством, мы получим ложный результат: errored: Error occured: invalid opcode.
4) Развернем смарт-контракт в тестовой сети и проверим наше доказательство.
4.1) Создан новый смарт-контракт в сети Sepolia:
https://sepolia.etherscan.io/tx/0x0a555af118bc0961984947432ee28e20ff33e8f8525cf0b9fc31080a45c61566
4.3) Контракт необходимо верифицировать.
4.3.2) В новом окне необходимо вставить код нашего контракта verifier.sol
4.3.3) Подтверждаем верификацию.
4.4) Переходим в Read Contract
4.5) В строку proof (tuple) вставляем наше доказательство.
[["0x0ac917308a7b8db29288c028109c8617f910f6b6843c975a736374ddbc276797","0x1960e7c91c4bb774e6308c418615d566280679a5b7c18b45f89ab64098187bdf"],[["0x2df5af53473f2343c58091e657898f92b5b7f0b88a6ea7514c9952a47e07f444","0x0121a9c22c2abafb7dee637ef4f743a4d62798835350d042d55c708d2481fe3d"],["0x1e46763eeacc9f85215740e3d3f7eaddc2fca5c8115c282be1e60157740bcec8","0x23d8a13843a39d8f37b8a0ef6da31281b7ee2c61d16079a48f2620b9f6ef9aa0"]],["0x2f990abf7f96daee712f3ca282e7e304370ac70d633b6156a41b91f140e6cb41","0x0e619f6d20fc6c39fa3fa0320c795e57218824f1f11ee90b0d7edf3a306de8fd"]]
https://sepolia.etherscan.io/address/0xe38f6eebf205303e417525bf52638290ffee7d08#readContract
При помощи инструментов ZoKrates сгенерировали доказательство zk-SNARKs и подтвердили истинность нашего значения х которое было сохранено в хеш и разделено на две части. Как видим смарт-контракты с нулевым разглашением (ZK) предполагают внедрение системы, которая позволяет сторонам доказывать подлинность определенной информации, не раскрывая деталей этой информации.
Этот подход обеспечивает хорошую защиту от кражи персональных данных, похитители не могут украсть то, чего не видят, что значительно затрудняет реализацию мошеннических действий.
ZoKrates делает создание zk-SNARKs доступным, предоставляя простой язык для написания функций. Также существует обширный набор примеров, демонстрирующий все возможности языка. Потенциал использования: в системах идентификации, сохраняя конфиденциальность, в различных голосованиях, финансах, оракулах, приложениях DeFi и т.д.