Блокчейн

PLONK и универсальные ZK-системы

Groth16 - это Ferrari среди zk-SNARK: самый компактный proof, самая быстрая верификация. Но представьте, что для каждого обновления прошивки Ferrari нужно заново собирать весь двигатель с нуля, привлекая тысячи инженеров на специальную церемонию. Именно это происходит с per-circuit trusted setup: любое изменение ZK-схемы требует новой MPC ceremony. В 2019 году Gabizon, Williamson и Ciobotaru опубликовали PLONK - протокол с universal setup, где одна церемония обслуживает все схемы. Сегодня PLONKish системы (UltraPlonk, Halo2) работают внутри zkSync, Scroll, Aztec и Polygon zkEVM, обрабатывая миллионы транзакций. Вся мощь - в четырёх идеях: гибкое gate-уравнение, universal SRS, custom gates и lookup-таблицы.

  • **zkSync Era** - zkRollup от Matter Labs, использующий PLONKish arithmetization (boojum prover) для масштабирования Ethereum: ~$0.1 за транзакцию вместо ~$5 на L1
  • **Scroll** - zkEVM на базе Halo2 (PLONKish с custom gates и lookups), полностью EVM-эквивалентный, позволяющий деплоить Solidity-контракты без изменений
  • **Aztec** - privacy-focused zkRollup, где UltraPlonk позволяет скрывать не только суммы, но и вызываемые функции контрактов, создавая полностью приватные DeFi-транзакции

Предварительные знания

  • zk-SNARK: From Theory to Practice

PLONKish arithmetization: гибче, чем R1CS

В уроке про zk-SNARK мы разбирали R1CS - систему, где каждый constraint допускает ровно одно умножение: `a * b = c`. Это работает, но создаёт ограничения: для сложных операций (range check, побитовые операции, хеширование) приходится раскладывать всё на элементарные умножения, порождая тысячи constraints. **PLONK** (Permutations over Lagrange-bases for Oecumenical Noninteractive arguments of Knowledge, 2019) предлагает радикально другой подход - **универсальное gate-уравнение** с **selector-векторами**, которые «включают» и «выключают» нужные части.

Но как связать провода между строками? В R1CS все constraints работают с одним общим вектором witness. В PLONK каждая строка имеет свои `a, b, c`, и нужен способ сказать: «выход строки 3 - это вход строки 7». Для этого PLONK использует **copy constraints** через **permutation argument** - гибкий криптографический механизм, который доказывает, что значения в определённых позициях таблицы совпадают.

Статья PLONK вышла в 2019 году (авторы: Ariel Gabizon, Zachary Williamson, Oana Ciobotaru). Williamson - сооснователь **Aztec Protocol**, одного из ведущих zkRollup. Название расшифровывается как «Permutations over Lagrange-bases for Oecumenical Noninteractive arguments of Knowledge» - заглавные буквы подобраны, чтобы получилось запоминающееся слово. PLONK стал основой для целого семейства протоколов: TurboPlonk, UltraPlonk, Halo2, каждый из которых расширяет базовую систему custom gates и lookup-таблицами.

**R1CS vs PLONK в числах.** Для проверки ECDSA-подписи: R1CS требует ~300,000 constraints, а PLONKish arithmetization с custom gates - около ~15,000 строк. Для Poseidon hash (популярный ZK-friendly хеш): R1CS ~320 constraints на раунд, PLONKish ~35 строк на раунд с использованием wide gates. Чем сложнее операция, тем больше выигрыш от гибкости PLONK.

В PLONK gate-уравнении q_L·a + q_R·b + q_O·c + q_M·(a·b) + q_C = 0 нужно выразить constraint «a равно константе 7». Какие значения selectors корректны?

Universal SRS: одна церемония для всех схем

Вспомним главную проблему Groth16: **per-circuit trusted setup**. Каждый раз, когда схема меняется (добавили фичу в zkRollup, обновили логику контракта), нужно проводить новую Phase 2 ceremony. Для развивающихся проектов это катастрофа - обновление занимает недели координации. PLONK решает эту проблему через **Universal и Updateable Structured Reference String** (SRS) - параметры, которые генерируются один раз и подходят для **любой** схемы заданного размера.

Как это работает технически? PLONK использует **KZG polynomial commitments** (Kate-Zaverucha-Goldberg, 2010). KZG позволяет «закоммитить» полином и затем доказать его значение в любой точке, используя только SRS. Ключевое свойство: commitment не зависит от конкретного полинома - он зависит только от максимальной степени. Поэтому один SRS (набор `[τ⁰]₁, [τ¹]₁, ..., [τᴺ]₁` на эллиптической кривой) подходит для коммитментов к **любым** полиномам степени ≤ N.

Исторически первой масштабной церемонией Powers of Tau стал проект **Perpetual Powers of Tau** (начат в 2019), в который мог присоединиться любой участник. Результаты этой церемонии повторно используются множеством проектов: **Hermez** (ныне Polygon zkEVM), **Loopring**, **Semaphore** и другие. Ethereum провёл собственную KZG ceremony для EIP-4844 (proto-danksharding) с рекордными **141,416 участниками** - этот SRS теперь доступен всем проектам экосистемы.

**Размер SRS и практические ограничения.** SRS для N строк занимает примерно `48·N` байт (каждый элемент G₁ - 48 байт в BLS12-381). Для N = 2²⁰ (~1M строк): SRS ≈ 48 МБ. Для N = 2²⁸ (~256M строк): SRS ≈ 12 ГБ. Prover должен загрузить SRS в память, что ограничивает максимальный размер схемы. На практике zkRollup-проекты разбивают вычисления на блоки по ~2²⁰-2²² строк и агрегируют proofs.

В чём главное практическое преимущество universal SRS в PLONK по сравнению с per-circuit trusted setup в Groth16?

Custom gates: за пределами сложения и умножения

Базовое PLONK gate-уравнение `q_L·a + q_R·b + q_O·c + q_M·(a·b) + q_C = 0` уже гибче R1CS, но всё ещё ограничено: три провода, одно умножение, линейные селекторы. Что если нам нужно проверить принадлежность значения диапазону `[0, 2⁸)`? Или вычислить хеш Poseidon за минимум строк? **Custom gates** расширяют gate-уравнение, добавляя больше проводов, высокостепенные мономы и доступ к соседним строкам.

Почему custom gates так важны для производительности? В ZK-системах главный bottleneck - **количество строк**: чем больше строк, тем дольше prover вычисляет proof (time ~ O(N log N) для FFT/NTT операций). Custom gate, который кодирует сложную операцию в одну строку вместо десяти, ускоряет proving в ~10 раз для этой операции. Но есть трейдофф: каждый новый тип gate увеличивает **degree** gate-полинома, что влияет на размер proof и количество раундов протокола.

Архитектура **Halo2** заслуживает отдельного внимания. В ней circuit разбивается на **chips** - переиспользуемые модули с определённой конфигурацией custom gates. Chip для ECC-операций, chip для Poseidon hash, chip для range checks. Это напоминает аппаратный дизайн FPGA, где разные блоки выполняют специализированные операции. Halo2 используется в **Scroll** (zkEVM), **Taiko** (zkRollup), проектах **PSE** (Privacy and Scaling Explorations, подразделение Ethereum Foundation). Каждый из них компонует chips под свои задачи.

**Degree vs efficiency tradeoff.** Gate-полином степени d требует d+1 evaluation points в протоколе, что увеличивает proof size. Vanilla PLONK (d=2) - самый компактный proof. TurboPlonk с кубическими gates (d=3) - proof чуть больше, но constraints в 3-5x меньше. UltraPlonk с degree-5 gates и lookups - proof ещё больше, но число строк сокращается в 10-50x для типичных операций. На практике выигрыш от уменьшения числа строк многократно перевешивает рост proof size.

Для range check x ∈ [0, 255] в Vanilla PLONK нужно ~9 строк (8 булевых + 1 composition). С custom gate этот check занимает 1 строку. Почему это важно для prover'а?

Lookup-таблицы: plookup и LogUp

Custom gates ускоряют арифметические операции, но некоторые вычисления принципиально «неарифметичны»: побитовый XOR, range checks для произвольных диапазонов, таблицы SHA-256 round constants, EVM opcode dispatch. Проверять их через gate-уравнения мучительно дорого. **Plookup** (2020, Gabizon и Williamson) предлагает другой подход: предвычислить таблицу допустимых значений и доказать, что значение **содержится** в этой таблице, не раскрывая какое именно.

Стоимость lookup'а амортизируется: таблица «платится» один раз (добавляется к commitment'ам prover'а), а каждый отдельный lookup стоит примерно 1 строку. Для 10,000 XOR-операций: через gates - 500,000 строк, через lookup в таблицу из 65,536 записей - ~75,000 строк (таблица + lookups). Чем больше обращений к одной таблице, тем выгоднее lookup.

Как всё собирается вместе? Современный zkEVM (Scroll, Polygon zkEVM, Taiko) работает на **PLONKish arithmetization** с **universal SRS**, **custom gates** для арифметических операций и **lookup-таблицами** для всего остального. Prover берёт блок транзакций Ethereum, «исполняет» их в ZK-circuit, используя десятки специализированных таблиц и custom gates, и генерирует proof размером ~400-700 байт. Verifier на L1 проверяет этот proof за ~300K gas (~0.5 при 30 gwei). Это стало возможным именно благодаря комбинации всех четырёх техник из этого урока.

**Benchmark.** Scroll zkEVM (Halo2-based) использует ~28 типов lookup-таблиц и ~15 типов custom gates. Генерация proof для блока из ~100 транзакций занимает ~3-5 минут на GPU-кластере. Без custom gates и lookups время proving по оценкам составило бы дни, а не минуты. Polygon zkEVM (PIL/eSTARK-based) использует аналогичный подход с ~50 state machines, каждая со своими lookup-таблицами.

Lookup-таблицы нарушают zero-knowledge, потому что prover раскрывает, к каким строкам таблицы он обращается

Lookup argument доказывает только **факт принадлежности** значения таблице, не раскрывая конкретную строку. Plookup и LogUp используют случайные вызовы (challenges) β и γ, которые «перемешивают» информацию о позициях через grand product или сумму дробей. Verifier убеждается, что все значения witness'а содержатся в таблице, но не узнаёт, какое значение соответствует какой строке. Zero-knowledge property сохраняется за счёт blinding factors - случайных полиномов, добавляемых к commitment'ам.

Интуиция подсказывает, что «проверка по таблице» = «указать строку» (как index в массиве). Но lookup argument работает иначе: он доказывает мультимножественное включение (multiset containment), а не доступ по индексу. Это как доказать, что карта есть в колоде, не показывая её позицию - через криптографический протокол, а не через перебор.

zkEVM должен доказать корректность 10,000 операций XOR (8-бит) в одном блоке. Через PLONKish gates каждый XOR стоит ~50 строк. Через lookup в предвычисленную XOR-таблицу (256×256 = 65,536 записей) каждый XOR стоит ~1 строку. Какова примерная экономия строк при использовании lookups?

Итоги

  • **PLONKish arithmetization** использует универсальное gate-уравнение `q_L·a + q_R·b + q_O·c + q_M·(a·b) + q_C = 0` с selector-векторами, которые конфигурируют каждую строку. Copy constraints через permutation argument связывают значения между строками - всё без привязки к конкретной схеме
  • **Universal SRS** (Structured Reference String) генерируется одной Powers of Tau ceremony и подходит для любой схемы размером до N строк. KZG polynomial commitments делают proof ~400-700 байт. Помните «церемонию для каждого обновления прошивки» из начала урока? Universal SRS решает эту проблему: одна церемония навсегда
  • **Custom gates** расширяют базовое gate-уравнение: больше проводов, высокостепенные мономы, доступ к соседним строкам. TurboPlonk, UltraPlonk, Halo2 - каждый добавляет свои расширения, сокращая число строк в 5-50x для типичных операций
  • **Lookup-таблицы** (Plookup, LogUp) позволяют доказать принадлежность значения предвычисленной таблице за ~1 строку. Для zkEVM это критично: десятки таблиц (opcodes, memory, keccak) сокращают constraints с миллиардов до миллионов, превращая доказательство EVM-execution из теоретической идеи в работающую систему

Связанные темы

PLONK находится на пересечении теоретической криптографии и практической инфраструктуры zkRollup:

  • zk-SNARK: от теории к практике — R1CS и Groth16 - предшественники PLONK. PLONKish arithmetization заменяет R1CS более гибкой системой, а universal SRS решает проблему per-circuit trusted setup Groth16
  • zk-STARK: transparent proofs — STARK и PLONK - два доминирующих подхода к ZK. STARK использует FRI (transparent, post-quantum), PLONK - KZG (compact proofs, universal setup). Некоторые системы комбинируют оба: PLONK+FRI (Plonky2)
  • zkEVM: доказательство EVM-execution — zkEVM - главный потребитель PLONKish систем. Custom gates и lookup-таблицы из этого урока - строительные блоки, из которых собираются ZK-circuits для всех 140+ opcodes EVM
  • Recursive proofs: proofs of proofs — PLONK с KZG позволяет эффективно верифицировать один proof внутри другого. Recursive composition - ключевая техника для агрегации proofs в zkRollup и IVC (Incrementally Verifiable Computation)

Вопросы для размышления

  • Universal SRS размером 2²⁰ (~1M строк) занимает ~48 МБ, а 2²⁸ (~256M строк) - ~12 ГБ. Как ограничение на размер SRS влияет на архитектуру zkRollup? Почему проекты разбивают вычисления на блоки, а не генерируют один огромный SRS?
  • Custom gates повышают степень gate-полинома (degree), что увеличивает proof size и число раундов. Как найти баланс между «специализированностью» gates и универсальностью системы? Когда лучше использовать lookup вместо custom gate?
  • PLONK с KZG требует trusted setup, а PLONK с FRI (Plonky2) - нет, но proofs больше. Если квантовые компьютеры станут реальностью, KZG-based системы будут сломаны. Как индустрия готовится к этому переходу и какова цена миграции?

Связанные уроки

  • crypto-04-algebraic-structures
PLONK и универсальные ZK-системы

0

1

Войти