Advertencia
Esta caja ha sido archivada. El desarrollo se ha trasladado al repositorio zksync-crypto. Úselo en su lugar.
zkSync Era es un paquete acumulativo de capa 2 que utiliza pruebas de conocimiento cero para escalar Ethereum sin comprometer la seguridad o la descentralización. Dado que es compatible con EVM (Solidity/Vyper), el 99% de los proyectos de Ethereum se pueden volver a implementar sin refactorizar ni volver a auditar una sola línea de código. zkSync Era también utiliza un compilador basado en LLVM que eventualmente permitirá a los desarrolladores escribir contratos inteligentes en C++, Rust y otros lenguajes populares.
El propósito de esta biblioteca es trabajar con una aritmetización muy específica con suposiciones adicionales sobre el tamaño del campo. Aproximadamente, esperamos tener un campo F
con |F| ~ 64 bits (el tamaño de una palabra de máquina) (la suposición sobre el tamaño del campo no es importante para la estrategia de aritmetización y colocación de puertas, pero se afirma en implementaciones de dispositivos para funciones particulares que dependen de un tamaño de campo específico).
El sistema tiene una jerarquía de funciones lógicas (dispositivos), puertas (entidades que pueden inscribirse en una traza) y evaluadores (relaciones entre polinomios). Los evaluadores están escritos en forma de un rasgo que nos permite luego componer automáticamente funciones para verificar la satisfacibilidad y calcular pruebas, así como sintetizar verificadores simples y recursivos. Las puertas tienen herramientas adicionales adjuntas que les permiten a las puertas mismas rastrear la lógica de dónde deben ubicarse en el rastro. Tenga en cuenta que confiamos en las restricciones de copia de Plonk y trabajamos en las entidades lógicas copiables de "variables" para componer una declaración final demostrable. El sistema no está diseñado para la aritmetización AIR y no permite expresar restricciones que abarquen varias filas del seguimiento.
En general, la traza contiene pocos tipos de columnas. La principal separación es entre:
Además, el seguimiento le permite agregar un argumento de búsqueda, que también puede usar columnas especializadas para albergar las entradas de las tablas de búsqueda, o simplemente usar columnas de propósito general. Las tablas están codificadas como un solo conjunto de polinomios por ahora, por lo que la longitud total del seguimiento debe ser mayor que el número total de entradas en las tablas.
Tenga en cuenta que cada "puerta" (como tipo Rust) es única, por lo que una puerta solo se puede colocar en columnas especializadas o de uso general, pero no en ambas. Si se necesita dicha funcionalidad, entonces es posible crear un contenedor de nuevo tipo.
Las funciones lógicas de nivel superior (como descomposiciones booleanas, comprobaciones de rango, comprobaciones de cero, etc.) se utilizan para hacer que un circuito se inscriba internamente de diferentes maneras dependiendo de si algunas puertas están permitidas o no en la instancia particular del CS. Las instancias de CS con diferentes conjuntos de puertas se consideran un tipo diferente desde la perspectiva de Rust, y confiamos en algún trabajo de compilación, accesorios constantes y en línea para reducir la ramificación en saltos estáticos.
|F|
y por lo tanto tenemos que repetir los argumentos), pero esto se cambiará para que nos movamos al campo de extensión como lo más rápido posible después de comprometerse con el testigo para evitar una posibilidad bastante "grande" de obtener ceros en el denominador. El efecto sobre el gasto computacional en la prueba es bastante insignificante. Usamos un argumento de búsqueda aplicado a través de las relaciones sum_i selector(x_i) / (witness(x_i) + beta) == sum_i multiplicity(x_i) / (table(x_i) + beta)
donde una búsqueda sobre columnas especializadas selector(x_i)
es solo una identidad. Tampoco codificamos las tablas como polinomio de menor grado para eliminar comprobaciones de límites de grado adicionales, sino que las rellenamos con ceros. Tenga en cuenta que las entradas de la tabla nunca contienen un elemento de (0,0,...,0)
ya que utilizamos columnas de ID separadas para los tipos de tablas en el caso de varias tablas (incluso en el caso de que solo se utilice una tabla), y un ID así comienza con 1.
Una característica interesante de un argumento de búsqueda como este es que, debido a su naturaleza aditiva, si realizamos búsquedas en múltiples polinomios witness
en la misma tabla, en lugar de repetir el argumento para cada (tupla de) polinomio(s) (lo que requeriría una columna de multiplicidad separada, así como algunos polinomios intermedios más adelante), podemos "sumar" multiplicidades y transformar el argumento en algo como sum_i selector_0(x_i) / (witness_0(x_i) + beta) + sum_i selector_1(x_i) / (witness_1(x_i) + beta) == sum_i total_multiplicity(x_i) / (table(x_i) + beta)
, de modo que el costo total de una búsqueda es solo 1 columna de multiplicidades y 2 polinomios intermedios (relacionados con el testigo) + 1 (relacionado con la tabla) para codificar el Relaciones izquierdas y derechas sobre las raíces de la unidad.
La exactitud de este argumento es clara. Para mayor solidez, utilizamos el argumento original como en el artículo "Cocientes en caché para búsquedas rápidas", Lema 2.4. Necesitamos demostrar que es suficiente comprometerse con la total_multiplicity
en lugar de con las multiplicidades de witness_0
y witness_1
por separado.
Supongamos que la ecuación sum_i selector_0(x_i) / (witness_0(x_i) + X) + sum_i selector_1(x_i) / (witness_1(x_i) + X) == sum_i total_multiplicity(x_i) / (table(x_i) + X)
sostiene. Necesitamos demostrar que witness_0
y witness_1
están contenidos en la tabla t
. Sea f = (witness_0 | witness_1)
, una concatenación de los valores. La ecuación anterior implica sum_i selector_i / (f_i + X) == sum_i total_multiplicity_i / (t_i + X)
(tenga en cuenta que la longitud del intervalo de i
en el LHS es el doble que el anterior). Por el Lema 2.4 obtenemos f subset t
: "subconjunto" en el sentido de que cada coordenada del vector f
es una coordenada de t
. En particular, witness_0, witness_1 subset f subset t
.
Tenga en cuenta que el argumento también es válido para varios witness_i
. El resto del argumento de solidez, para un beta
elegido, sigue directamente como en el trabajo anterior.
2^-40
de obtener 0
en denominadores. Hay puntos de referencia para 8kB de SHA256 utilizando lo que creemos que es una configuración algo óptima de puertas + tablas para el circuito SHA256. Tenga en cuenta que aunque el probador es algo rápido, no optimizamos adecuadamente la FFT y seguimos usando Poseidon (no Poseidon2) para configuraciones en las que esperamos que la prueba se use para recursividad. Dos scripts sha256_bench_recursive.sh
y sha256_bench_non_recursive.sh
le permiten ejecutar las pruebas correspondientes (si se espera que la prueba se use en recursividad o no), y debe buscar una línea Proving is done, taken ...
para ver el tiempo de prueba , porque el verificador que se ejecuta después es bastante detallado. Estos puntos de referencia utilizan un factor LDE de 8, aunque todas nuestras restricciones son de grado 4 o menos; sin embargo, es un parámetro que se utiliza en algunos otros puntos de referencia públicos. Tampoco usamos PoW en esas pruebas porque PoW para 20 bits es insignificante (30 ms) y todavía no admitimos PoW sobre hashes algebraicos (sin embargo, son solo ~2 veces más lentos, por lo que también son insignificantes). El nivel de seguridad es de aproximadamente 100
bits, pero la solidez de FRI se puede mejorar aumentando el número de consultas, y un aumento en el número de consultas no aumenta el tiempo de prueba (no debe confundirse con cambiar la tasa de FRI). La longitud del seguimiento es 2^16
y utiliza 60 columnas de uso general y 8 argumentos de búsqueda de ancho 4.
Nota: los puntos de referencia simplemente intentan compilarse en el arco nativo y, por ahora, normalmente solo el arco AArch64 (léase Apple M1) se prueba de un extremo a otro. Se probó la validez de las implementaciones aritméticas x86-64, pero no de un extremo a otro en pruebas completas. Tenga en cuenta que el rendimiento máximo x86-64 requiere indicadores de funciones de compilador adicionales además de cpu = native
(el compilador Rust no utiliza el conjunto AVX512 ni siquiera en CPU nativas)
El probador Boojum se distribuye según los términos de cualquiera de los dos
a tu elección.
zkSync Era ha pasado por muchas pruebas y auditorías. Aunque está activo, todavía está en estado alfa y pasará por más auditorías y programas de recompensas por errores. ¡Nos encantaría escuchar las opiniones y sugerencias de nuestra comunidad al respecto! Es importante señalar que bifurcarlo ahora puede provocar la pérdida de importantes actualizaciones de seguridad, funciones críticas y mejoras de rendimiento.
Este software incluye componentes de terceros. Para obtener una lista completa de estos componentes y sus licencias, consulte el archivo AVISOS DE TERCEROS.