Un programa aritmético cuadrático es un circuito aritmético, específicamente un Sistema de Restricciones de Rango 1 (R1CS) representado como un conjunto de polinomios. Se deriva utilizando la interpolación de Lagrange en un Sistema de Restricciones de Rango 1. A diferencia de un R1CS, un Programa Aritmético Cuadrático (QAP) puede evaluarse para comprobar su igualdad en tiempo O(1) mediante el Lema de Schwartz-Zippel.
Ideas clave
En el capítulo sobre el Lema de Schwartz-Zippel, vimos que podemos comprobar si dos vectores son iguales en tiempo O(1) convirtiéndolos en polinomios y luego ejecutando la prueba del Lema de Schwartz-Zippel sobre los polinomios. (Para aclarar, la prueba se ejecuta en tiempo O(1), convertir los vectores a polinomios genera una sobrecarga).
Dado que un Sistema de Restricciones de Rango 1 está compuesto en su totalidad por operaciones vectoriales, nuestro objetivo es comprobar si
La∘Ra=?Oa
se cumple en tiempo O(1) en lugar de tiempo O(n) (donde n es el número de filas en L, R y O).
Pero antes de hacer eso, necesitamos entender algunas propiedades clave de la relación entre los vectores y los polinomios que los representan.
Para todas las matemáticas aquí presentadas, asumimos que estamos trabajando en un campo finito, pero omitiremos la notación modp por motivos de concisión.
Homomorfismos entre la suma de vectores y la suma de polinomios
La suma de vectores es homomórfica a la suma de polinomios
Si tomamos dos vectores, los interpolamos con polinomios y luego sumamos los polinomios resultantes, obtenemos el mismo polinomio que si sumáramos los vectores entre sí y luego interpoláramos el vector suma.
Expresado de forma más matemática, sea L(v) el polinomio resultante de la interpolación de Lagrange sobre el vector v utilizando (1,2,...,n) como los valores de x, donde n es la longitud de v. Lo siguiente es cierto:
L(v+w)=L(v)+L(w)
En otras palabras, la suma de los polinomios resultantes de interpolar los vectores v y w es igual al polinomio resultante de interpolar la suma de los vectores v+w.
Ejemplo resuelto
Sean f1(x)=x2 y f2(x)=x3. f1 interpola (1,1),(2,4),(3,9) o el vector [1,4,9] y f2 interpola [1,8,27].
La suma de los vectores es [2,12,36] y está claro que x3+x2 interpola eso. Sea f3(x)=f1(x)+f2(x)=x3+x2.
f3(1)f3(2)f3(3)=1+1=2=8+4=12=27+9=36
Probando las matemáticas en Python
Hacer pruebas unitarias de una identidad matemática propuesta no la hace verdadera, pero ilustra lo que está sucediendo. Se anima al lector a probar con algunos vectores diferentes para comprobar que la identidad se cumple.
Sea λ un escalar (específicamente, un elemento del campo en un campo finito). Entonces
L(λv)=λL(v)
Ejemplo resuelto
Supongamos que nuestros 3 puntos son [3,6,11]. El polinomio que interpola eso es f(x)=x2+2. Si multiplicamos el vector por 3 obtenemos [9,18,33]. El polinomio que interpola eso es
from scipy.interpolate import lagrangex_values = [1, 2, 3]y_values = [9, 18, 33]print(lagrange(x_values, y_values))# 2# 3 x + 6
La multiplicación por un escalar es en realidad suma de vectores
Cuando decimos “multiplicar un vector por 3” en realidad estamos diciendo “sumar el vector consigo mismo tres veces”. Dado que solo estamos trabajando en campos finitos, no nos preocupamos por la interpretación de escalares como “0.5”
Podemos pensar tanto en los vectores bajo la suma de elementos uno a uno (en un campo finito) como en los polinomios bajo la suma (también en un campo finito) como grupos.
La conclusión más importante de este capítulo es
El grupo de vectores bajo la suma en un campo finito es homomórfico al grupo de polinomios bajo la suma en un campo finito.
Esto es fundamental porque comprobar la igualdad de vectores toma un tiempo O(n), pero comprobar la igualdad de polinomios toma un tiempo O(1).
Por lo tanto, mientras que comprobar la igualdad de un R1CS tomaba tiempo O(n), podemos aprovechar este homomorfismo para comprobar la igualdad de los R1CSs en tiempo O(1).
Esto es lo que es un Programa Aritmético Cuadrático.
Un Sistema de Restricciones de Rango 1 en Polinomios
Consideremos que la multiplicación de matrices entre una matriz rectangular y un vector puede escribirse en términos de suma de vectores y multiplicación por un escalar.
Por ejemplo, si tenemos una matriz A de 3×4 y un vector v de 4 dimensiones, entonces podemos escribir la multiplicación de la matriz como
Hemos expresado la multiplicación de matrices entre A y v puramente en términos de suma de vectores y multiplicación por un escalar.
Dado que establecimos anteriormente que el grupo de vectores bajo la suma en un campo finito es homomórfico al grupo de polinomios bajo la suma en un campo finito, podemos expresar el cálculo anterior en términos de polinomios que representan a los vectores.
Comprobando sucintamente que Av1=Bv2
Supongamos que tenemos las matrices A y B tales que
A=[6437]B=[31296]
y los vectores v1 y v2
v1=[24]v2=[22]
Queremos comprobar si
Av1=Bv2
es cierto.
Obviamente, podemos llevar a cabo la aritmética matricial, pero la comprobación final requerirá n comparaciones, donde n es el número de filas en A y B. Queremos hacerlo en tiempo O(1).
Primero, convertimos la multiplicación de matrices Av1 y Bv2 al grupo de vectores bajo la suma:
AB=[64],[37]=[312],[96]
Ahora queremos encontrar el equivalente homomórfico de
[64]⋅2+[37]⋅4=?[312]⋅2+[96]⋅2
en el grupo de polinomios.
Convirtamos cada uno de los vectores a polinomios sobre los valores de x[1,2]:
La declaración assert final es capaz de comprobar si Av1=Bv2 realizando una sola comparación en lugar de n.
De R1CS a QAP: Comprobando sucintamente que La∘Ra=Oa
Dado que sabemos cómo comprobar si Av1=Bv2 de forma sucinta, ¿podemos también comprobar si La∘Ra=Oa sucintamente?
Las matrices tienen m columnas, así que dividamos cada una de las matrices en m vectores columna y procedamos a interpolarlos en (1,2,...,n) para producir m polinomios cada uno.
Sean u1(x),u2(x),...,um(x) los polinomios que interpolan los vectores columna de L.
Sean v1(x),v2(x),...,vm(x) los polinomios que interpolan los vectores columna de R.
Sean w1(x),w2(x),...,wm(x) los polinomios que interpolan los vectores columna de O.
Sin pérdida de generalidad, digamos que tenemos 4 columnas (m=4) y tres filas (n=3).
Dado que multiplicar un vector columna por un escalar es homomórfico a multiplicar un polinomio por un escalar, cada uno de los polinomios puede multiplicarse por el elemento respectivo en el witness.
Observa que el resultado final es un solo polinomio con un grado máximo de n−1, ya que cada u1(x),…,un(x) tiene un grado máximo de n−1.
Esto se deduce de cómo los construimos: cada columna de L tiene n entradas, y al interpolar a través de n puntos mediante la interpolación de Lagrange se produce un polinomio de grado como máximo n−1.
En el caso general, La puede escribirse como
i=1∑maiui(x)
después de convertir cada una de las m columnas en polinomios.
Siguiendo los mismos pasos anteriores, cada producto matriz-witness en el R1CS La∘Ra=Oa puede transformarse como
Debido a los homomorfismos L(v1)+L(v2)=L(v1+v2) y L(λv)=λL(v), si calculamos u(x) como L(La) obtenemos el mismo resultado que si aplicamos la interpolación de Lagrange a las columnas de L y luego multiplicamos cada uno de los polinomios por el elemento respectivo en a sumando el resultado.
Dicho de otra manera,
i=1∑maiui(x)=L(La)∣ui(x) es la interpolacioˊn de Lagrange de la columna i de L
Entonces, ¿por qué no calcular simplemente una sola interpolación de Lagrange en lugar de m?
Necesitamos hacer una distinción sobre quién está usando el QAP. El verificador (y el trusted setup que cubriremos más adelante) no conocen el witness a y, por lo tanto, no pueden calcular L(La). Esta es una optimización que el probador (prover) puede hacer, pero las demás partes en el protocolo ZK no pueden hacer uso de ella.
Todas las partes involucradas necesitan tener un acuerdo común sobre el QAP —las interpolaciones polinómicas de las matrices— antes de que se realice cualquier prueba o verificación.
Desequilibrio en los grados de los polinomios
Sin embargo, no podemos simplemente expresar el resultado final como
u(x)v(x)=w(x)
porque los grados no coincidirán.
Multiplicar dos polinomios entre sí da como resultado un polinomio producto cuyo grado es la suma de los grados de los dos polinomios que se están multiplicando.
Debido a que cada u(x), v(x) y w(x) tendrá un grado n−1, u(x)v(x) generalmente tendrá un grado 2n−2 y w(x) tendrá un grado n−1, por lo que no serán iguales a pesar de que los vectores subyacentes que multiplicaron sí lo son.
Esto se debe a que los homomorfismos que establecimos anteriormente solo hacen afirmaciones sobre la suma de vectores, no sobre el producto de Hadamard.
Sin embargo, el vector que u(x)v(x) interpola, es decir
((1,u(1)v(1)),(2,u(2)v(2)),...,(n,u(n)v(n)))
es el mismo que el vector que w(x) interpola, es decir
Aunque los vectores “subyacentes” son iguales, los polinomios que los interpolan no lo son.
Ejemplo de igualdad subyacente
Supongamos que u(x) es el polinomio que interpola
(1,2),(2,4),(3,8)
y v(x) es el polinomio que interpola
(1,4),(2,2),(3,8)
Si consideramos que u(x) interpola el vector [2,4,8] y v(x) interpola el vector [4,2,8], entonces podemos ver que su polinomio producto interpola el producto de Hadamard de los dos vectores. El producto de Hadamard de [2,4,8] y [4,2,8] es [8,8,64].
Si multiplicamos u(x) y v(x) entre sí, obtenemos w(x)=4x4−18x3+36x2−42x+28.
Podemos ver en el gráfico de abajo que el polinomio producto interpola el producto de Hadamard [8,8,64] de los dos vectores.
Entonces, ¿cómo podemos “hacer” que w(x) sea igual a u(x)v(x) si interpolan los mismos valores de y sobre (1,2,...,n)?
Interpolando el vector 0
Si v1∘v2=v3, entonces v1∘v2=v3+0.
En lugar de interpolar 0 con la interpolación de Lagrange y obtener f(x)=0 (recuerda que la interpolación de Lagrange encuentra el polinomio interpolador de menor grado), podemos usar un polinomio de mayor grado que equilibrará el desajuste en los grados.
Por ejemplo, el polinomio negro (b(x)) en la imagen de abajo interpola [(1,0),(2,0),(3,0)]:
Ahora, dado que 4x4−18x3+8x2+42x−36 es una interpolación válida de [0,0,0], podemos escribir nuestro original
u(x)v(x)=w(x)+b(x)
¡y la ecuación estará equilibrada!
b(x) se calculó simplemente como u(x)v(x)−w(x) (el polinomio azul menos el polinomio rojo)
Sin embargo, no podemos dejar que el probador elija cualquierb(x), de lo contrario, podría elegir un b(x) que equilibre u(x)v(x) y w(x) incluso si no interpolan el mismo vector ([8,8,64] en nuestro ejemplo). El probador tiene demasiada flexibilidad al elegir b(x). Específicamente, queremos exigir que b(x) tenga raíces en x=1,2,…,n —es decir, que interpole el vector 0. De esa manera, la transformación polinómica de v1∘v2=v3+0 sigue respetando los vectores subyacentes.
Para restringir su elección de b(x), podemos utilizar el siguiente teorema:
La unión de raíces del producto de polinomios
Teorema: Si h(x)=f(x)g(x) y f(x) tiene un conjunto de raíces {rf} y g(x) tiene un conjunto de raíces {rg}, entonces h(x) tiene como raíces {rf}∪{rg}.
Ejemplo
Sean f(x)=(x−3)(x−4) y g(x)=(x−5)(x−6). Entonces h(x)=f(x)g(x) tiene como raíces {3,4,5,6}.
Podemos usar el teorema anterior para obligar a que b(x) tenga raíces en x=1,2,…,n.
Forzando a que b(x) sea el vector cero
Descomponemos b(x) en b(x)=h(x)t(x) donde t(x) es el polinomio
t(x)=(x−1)(x−2)…(x−n)
entonces cualquier polinomio multiplicado con t(x) también será el vector cero, ya que debe tener raíces en x=1,2,…,n.
Por lo tanto, reemplazaremos b(x) por h(x)t(x) en nuestra ecuación.
Así, nuestra igualdad se convertirá en
u(x)v(x)=w(x)+h(x)t(x)
Podemos calcular h(x) usando álgebra básica:
h(x)=t(x)u(x)v(x)−w(x)
QAP de principio a fin
Supongamos que tenemos un R1CS con las matrices L, R y O, y el vector witness a.
La∘Ra=Oa
Las matrices tienen n columnas y m filas donde n=4 y m=3.
Donde ui(x), vi(x) y wi(x) son polinomios que interpolan las columnas de L, R y O respectivamente, t(x) es (x−1)(x−2)...(x−n), donde n es el número de filas en L, R y O, y h(x) es
Pruebas de conocimiento cero sucintas con Programas Aritméticos Cuadráticos
Supongamos que tuviéramos una forma de que el verificador enviara un valor aleatorio τ al probador y este respondiera con
ABC=u(τ)=v(τ)=w(τ)+h(τ)t(τ)
El verificador podría comprobar que AB=C y aceptar que el probador tiene un witness a válido que satisface tanto el R1CS como el QAP.
Sin embargo, esto requeriría que el verificador confíe en que el probador está evaluando los polinomios correctamente, y no tenemos un mecanismo para obligar al probador a hacerlo.
En el próximo capítulo, mostraremos código en Python para convertir un R1CS en un QAP en base a nuestra discusión en este capítulo.
Luego discutiremos los trusted setups para comenzar a abordar el problema de cómo conseguir que el probador evalúe los polinomios de forma honesta.