Una prueba de rango en el contexto de los argumentos de producto interno es una prueba de que el escalar ha sido comprometido en y es menor que para algún número entero no negativo .
Este artículo muestra cómo el documento de Bulletproofs construye dicha prueba. La idea a alto nivel es que si podemos demostrar que un vector consiste solo de unos y ceros y que es la representación binaria de , entonces debe ser menor que . Esto es análogo a decir que un número que cabe en un entero sin signo de 8 bits debe ser menor que 256.
La ventaja de usar Bulletproofs para pruebas de rango es que la prueba de rango se puede construir directamente sin la necesidad de un circuito aritmético.
Monero utiliza las Pruebas de Rango de Bulletproofs (el algoritmo presentado aquí) para garantizar que la suma de las transacciones no sea negativa (en un campo finito, los números negativos son los elementos mayores que , ya que son los inversos aditivos de los elementos menores o iguales a , donde es el orden del campo).
Este artículo es parte de una serie sobre ZK Bulletproofs.
Notación
es un vector de dimensión de solo ceros.
es un vector de dimensión de solo unos.
es un vector de dimensión
es un vector de dimensión
es un vector de dimensión
Nota que .
Descripción general de la prueba de rango
Demostrar que es un compromiso a un escalar con un valor menor que requiere demostrar lo siguiente:
- es binario (solo contiene los valores y ).
- El producto interno .
El segundo punto es fácil de demostrar, hacemos una prueba de producto interno normal y luego revelamos que es uno de los vectores en el compromiso, o hacemos que el verificador construya el compromiso de por sí mismo. Sin embargo, demostrar que es binario sin un circuito aritmético requiere un par de trucos algebraicos.
Cuatro trucos útiles
El documento de Bulletproofs utiliza implícitamente cuatro trucos algebraicos que es mejor enseñar explícitamente antes de ver directamente el algoritmo de la prueba de rango.
1. Demostrar que es binario
La afirmación de que es binario es equivalente a las siguientes dos aseveraciones:
Por ejemplo, si entonces .
En este caso, porque
Ahora considera un caso donde no es binario, por ejemplo . será . El producto de Hadamard de y será .
De manera más general, si tiene una entrada no binaria, a esa entrada se le restará , y la entrada resultante en será distinta de cero. Cuando se calcula el producto de Hadamard, en ese índice particular, tanto como serán distintos de cero y el producto será distinto de cero, lo que significa que .
Sin embargo, si una entrada particular en es , entonces será en ese índice, por lo que el producto de Hadamard en ese índice también será cero.
Finalmente, si una entrada particular en es , entonces será en ese índice y su producto elemento por elemento seguirá siendo cero en ese índice.
Por lo tanto, si es binario y se calcula como , entonces .
2. Demostrar que un vector es todo ceros
Supongamos que deseamos demostrar que el compromiso de Pedersen contiene un vector cero. Creamos el compromiso de Pedersen y deseamos demostrarle a un verificador que .
Podría parecer suficiente enviar simplemente el término de cegado , pero para que nuestra solución sea más componible, no queremos revelar el término de cegado porque eso podría afectar otros compromisos que hemos creado.
En su lugar, el probador envía al verificador, y el verificador responde con un vector lleno de valores aleatorios . El probador ahora debe demostrar que
Nota que esta es una prueba probabilística. Es posible, con probabilidad insignificante, que para , pero no es posible que el probador falsifique tal porque no sabe de antemano cuál será .
Sin embargo, transmitir requiere una sobrecarga de comunicación , por lo que, en su lugar, el verificador solo envía un único elemento aleatorio y el probador calcula y utiliza como el vector aleatorio.
Luego, el probador demuestra que .
Aún no tenemos un mecanismo para demostrar que , ya que es un producto de Hadamard, no un producto interno. Sin embargo, afirmar que el vector es idénticamente es lo mismo que afirmar que . Según las reglas del producto interno, podemos mover al otro lado del producto interno y ahora tenemos .
El verificador recibirá compromisos para y , no para . Dependerá del verificador construir un compromiso para de modo que esté convencido de que el probador usó como el segundo vector en el producto interno.
El truco clave en el que confiamos es que el probador utiliza los vectores base y para comprometer sus vectores, pero el verificador usa y .
Cuando el probador envía la evaluación , el probador debe asegurarse de que los términos se cancelarán con en el vector base del verificador .
Específicamente, el probador construye los compromisos
Y envía al verificador. No es necesario comprometer y enviar porque en este caso es cero.
Los polinomios del probador serán
Crucialmente, el probador ha multiplicado con el producto de Hadamard a por . Anteriormente, se calculaba como (sin el ). Esto permitirá más adelante que todos los términos se cancelen cuando el verificador calcule el compromiso . Internamente, es , por lo que el se cancelará cuando el verificador calcule , es decir:
Sin embargo, el probador aún no puede calcular ni porque el verificador todavía no ha enviado . Por lo tanto, después de recibir , el verificador envía y el probador calcula y calcula el polinomio :
donde
El probador se compromete con los coeficientes y como
y envía al verificador. El verificador responde con y el probador evalúa los polinomios vectoriales y :
Nota que solo incluye los términos de cegado para y . En la implementación anterior, se calculaba como , donde es el término de cegado para , que también es el coeficiente constante del polinomio .
No hay término de cegado porque no hay compromiso con , es decir, no es secreto (es ). El probador envía y el verificador comprueba que:
La primera diferencia crucial es que el compromiso con se hace con respecto al vector base en lugar de por las razones discutidas anteriormente.
Segundo, no tiene un compromiso constante. Normalmente, la ecuación es , pero es un compromiso con en este caso.
En general, si contiene valores conocidos por el verificador, el verificador puede construir el compromiso con como mostramos en la siguiente sección.
4. Demostrar un producto interno cuando interviene una constante pública aditiva
Como se aludió en la sección anterior, el verificador puede reconstruir compromisos si conoce el vector subyacente.
Por ejemplo, supongamos que estamos demostrando que
donde y son vectores conocidos por el verificador y es un escalar conocido por el verificador de antemano. A diferencia de , estos vectores y escalar se conocen antes de que comience la prueba. Nota que en este ejemplo no está multiplicado por Hadamard con .
El probador aún se compromete solo a los valores secretos , y como de costumbre:
Como de costumbre, los polinomios y son tales que el término constante es el vector del producto interno original y los términos lineales son y . Al recibir del verificador, el probador calcula y crea, pero no evalúa, y :
Nota que no está multiplicado por Hadamard con , pero el término lineal sí lo está. Mostraremos cómo maneja esto el verificador más adelante.
Por ahora, calculamos como
donde
Nota que el término constante en es y no . Los compromisos se calculan como
y se envían al verificador, quien luego envía el valor aleatorio .
El probador calcula:
Nota que el término constante en es . El probador envía . Finalmente, el verificador calcula:
y contienen y respectivamente, pero y no. Por lo tanto, el verificador calcula compromisos para esos vectores y los suma a los compromisos y . En el caso de , el vector base hará que se convierta en , por lo que el compromiso debe calcularse con respecto a . Finalmente, el término de cegado contiene , pero no contiene . Por lo tanto, el probador debe multiplicar por .
Al calcular , y , el verificador puede estar seguro de que el cálculo del producto interno realmente incluyó esos términos.
Prueba de rango
Para demostrar que es un valor menor que tenemos tres cosas que probar:
- el producto interno , es decir, es la representación binaria de
Las dos últimas afirmaciones no están directamente en la forma de un producto interno. Sin embargo, podemos modificarlas ligeramente para lograr esto. Lo que realmente estamos diciendo es que los vectores
son ambos . Podemos usar el truco de una sección anterior para demostrar que son cero. Es decir, el probador necesita establecer que
y
donde es el vector aleatorio derivado del valor enviado por el verificador.
El documento original de Bulletproofs modifica ligeramente la primera afirmación de la siguiente manera para que podamos usar el tercer truco de la sección anterior:
Por lo tanto, el probador tiene tres productos internos que establecer:
Combinar tres productos internos en uno
Los tres productos internos se pueden combinar en uno solo usando una combinación lineal aleatoria con la aleatoriedad proporcionada por el verificador.
Con un poco de álgebra de producto interno muy pesada, podemos combinar todos los productos internos de la siguiente manera. Mostramos la derivación en el apéndice.
Los términos en los recuadros de abajo contienen valores conocidos por el verificador, por lo que construiremos nuestro algoritmo de verificación para comprobar explícitamente esos valores. Es decir, el verificador calculará los compromisos para los valores en los términos recuadrados, no el probador:
Para ahorrar espacio, el documento de Bulletproofs se refiere al término como , por lo que el producto interno se puede escribir como
Nota que es un valor que el verificador puede calcular.
Algoritmo de prueba de rango
El probador elige y su representación binaria y calcula .
Luego, el probador elige aleatoriamente el término de cegado y calcula el compromiso combinado de y usando los vectores base y como
Luego, el probador elige los términos lineales de los polinomios vectoriales que están por crearse, y , como y , y se compromete a ellos
El probador compromete el producto interno en con respecto a un de logaritmo discreto desconocido (no relacionado con ):
El probador envía al verificador.
El verificador responde con valores aleatorios que el probador utilizará para combinar los tres productos internos en uno solo.
La parte izquierda del producto interno será el término constante de y será el término constante de .
Por lo tanto, construimos como
y construimos como
Nota que multiplicamos elemento por elemento a con por las razones que discutimos en la parte 3 de la sección de prerrequisitos anterior.
El probador ahora puede construir con coeficiente constante , coeficiente lineal y coeficiente cuadrático como:
donde
El probador envía los compromisos de y como
No hay necesidad de comprometerse con ; observa que es exactamente el producto interno que estamos tratando de probar, por lo que el verificador ya tiene el compromiso como .
El verificador envía la aleatoriedad y el probador calcula
Nota que el término constante de se multiplica por para reflejar el término del producto interno original.
Luego, el verificador calcula un nuevo vector base y ejecuta las siguientes comprobaciones:
Recuerda que el probador no comprometió los vectores completos que usó para el lado izquierdo y derecho del producto interno, sino solo y . El resto de los vectores eran vectores públicos aditivos conocidos por el verificador, por lo que el verificador reconstruyó los compromisos con los vectores al construir compromisos para los términos constantes y sumándolos al compromiso de los vectores secretos suministrados por el probador.
A modo de recordatorio, aquí está el producto interno original con los valores conocidos por el verificador recuadrados:
Se anima al lector a verificar que los términos recuadrados (valores conocidos por el verificador) en el producto original fueron reconstruidos por el verificador en los términos recuadrados en el conjunto de comprobaciones de igualdad anteriores.
Al replicar una parte del cálculo del probador, el verificador asegura que el probador realmente llevó a cabo el cálculo tal como afirma.
Corrección del algoritmo de verificación
Ahora mostramos que las comprobaciones de verificación finales son idénticamente correctas si el probador fue honesto.
A continuación mostramos el álgebra exacta, pero intuitivamente el verificador está “reconstruyendo” el vector izquierdo en el producto interno , el vector derecho en el producto interno y la salida .
Al verificador no se le dan compromisos para ni para , sino para y . De manera similar, al verificador no se le da un compromiso para la salida , sino solo para .
Los términos aditivos y los términos multiplicados elemento por elemento con deben ser reconstruidos por el verificador.
Corrección de
Para la comprobación , esto es verdadero por definición, ya que así es como el probador calculó .
Corrección de los comprometidos y con respecto a y
Para
hacemos la siguiente sustitución:
Todos los términos se cancelan de la siguiente manera:
Los términos de cegado relacionados con se cancelan de la siguiente manera:
El se cancela con los términos :
Dividimos los productos internos:
Cancelamos los términos que aparecen a ambos lados de la ecuación:
Movemos al otro lado:
Corrección de la evaluación de
Para ver que
es correcta, podríamos sustituir los términos de la siguiente manera:
con , , , :
Sin embargo, tal álgebra sería extremadamente desordenada. En su lugar, observamos que es el término constante del producto interno del polinomio vectorial de . Para cancelar el término de cegado en , observa que contiene , por lo que esto se cancelará con el término gamma en .
Dado que los compromisos de Pedersen son aditivamente homomórficos, el verificador simplemente puede calcular y sumar a para calcular el compromiso al término constante del polinomio .
Prueba de rango de tamaño logarítmico
Podemos reducir el tamaño de la transmisión de datos enviando un compromiso a y y demostrando que los vectores comprometidos tienen un producto interno usando la prueba de tamaño logarítmico, y luego verificando que
y
con respecto a los vectores base y .
Uso del algoritmo de la prueba de rango para la suma de subconjuntos
El problema de la suma de subconjuntos pregunta, "dado un conjunto de números, ¿un subconjunto (posiblemente incluyendo todo el conjunto) suma ? Por ejemplo, si y el conjunto es la respuesta es sí porque . Sin embargo, si , entonces la respuesta es no.
El problema de la suma de subconjuntos es NP-Complete, lo que significa que, de manera similar a un circuito booleano o circuito aritmético, puede representar cualquier problema en NP. Es decir, cualquier problema en NP puede reescribirse (la palabra técnica es “reducirse”) a una instancia de suma de subconjuntos.
Al reemplazar por , podemos demostrar que conocemos una solución a una suma de subconjuntos sin revelar la respuesta. Específicamente, el probador sabría que si . En general, una entrada de uno en significa que incluimos ese elemento en el subconjunto y un cero significa que no está incluido en el subconjunto.
Por lo tanto, Bulletproofs son capaces de demostrar el conocimiento de cualquier testigo para cualquier problema en NP.
Apéndice: Derivación de la combinación de tres productos internos en uno
Comenzando con los tres productos internos
mostramos cómo derivar el resultado final
usando el álgebra de producto interno que aprendimos anteriormente.
- El término central se puede dividir en productos internos separados:
-
Podemos mover los términos constantes dentro de los productos internos:
-
Movemos los valores conocidos por el verificador a la derecha:
- Convertimos los términos para que ambos sean :
- Combinamos los términos en uno:
- Combinamos los dos términos a la izquierda:
- Dividimos el último término del lado izquierdo en dos productos internos:
- Combinamos los términos :
- Podemos usar la regla para combinar los términos que contienen . Aquí es , es , y es .
- Ahora descomponemos los términos del lado derecho:
- Sacamos los escalares de los productos internos de la derecha:
- Factorizamos :
Dado que , tenemos:
Esto completa la derivación.