Logo
Nuevos usuarios de RPC: 35% de descuento el primer mesVer oferta
OnFinality Learn
Guías de Red y Protocolo11 min de lectura

¿Qué es una prueba de conocimiento cero? Guía práctica de los sistemas de pruebas ZK

Un recorrido técnico por las pruebas de conocimiento cero: el modelo probador-verificador, completitud, solidez, conocimiento cero, protocolos interactivos vs no interactivos, y cómo verificar una prueba ZK de principio a fin.

TL;DR

Una prueba de conocimiento cero (ZKP) es un protocolo criptográfico en el que un probador convence a un verificador de que una afirmación es verdadera sin revelar nada más allá de esa verdad. Toda ZKP útil debe cumplir tres propiedades: completitud, solidez y conocimiento cero. Esta guía explica el modelo mental, contrasta las pruebas interactivas y no interactivas, recorre un flujo de verificación estilo Schnorr ejecutable y muestra cómo diagnosticar la verificación de pruebas en un endpoint RPC de blockchain.

Definición y alcance de una prueba de conocimiento cero

Una prueba de conocimiento cero es un protocolo entre dos partes. El probador posee un testigo secreto y quiere convencer al verificador de que una afirmación pública es verdadera. El verificador solo aprende que la afirmación es verdadera, no el testigo, ni las entradas utilizadas para derivarlo, ni ninguna información lateral que permita al verificador reproducir la prueba para un tercero.

El marco clásico proviene del artículo de 1985 The Knowledge Complexity of Interactive Proof Systems de Goldwasser, Micali y Rackoff. El matiz importante es que una ZKP no es solo una prueba que oculta datos; es una prueba que no filtra ningún conocimiento más allá de la verdad de la afirmación. Esa distinción separa las ZKP del cifrado, el hashing o los compromisos simples.

Este artículo cubre la mecánica del protocolo, las propiedades que debes probar y un flujo de verificación reproducible. No recomienda un servicio de prueba ZK específico ni un proveedor RPC específico; para la selección de endpoints, utiliza el Asistente RPC después de entender qué necesita tu verificador.

  • Afirmación: la declaración pública que se prueba, por ejemplo, 'Conozco x tal que g^x = y'.
  • Testigo: la entrada secreta que conoce el probador, por ejemplo, x.
  • Prueba: el mensaje o artefacto que el verificador comprueba.
  • Verificador: el algoritmo que emite aceptar o rechazar.

Las tres propiedades que toda prueba ZK debe cumplir

Un protocolo es una prueba de conocimiento cero solo si cumple tres propiedades simultáneamente. Probar cada propiedad por separado es la forma más fiable de evaluar un sistema ZK.

Completitud significa que un probador honesto con un testigo válido siempre puede convencer a un verificador honesto. Si tu implementación rechaza pruebas válidas, la completitud está rota. Solidez significa que un probador deshonesto no puede convencer al verificador de una afirmación falsa, excepto con probabilidad despreciable. Conocimiento cero significa que el verificador puede simular la transcripción sin el testigo, por lo que la prueba no revela nada más allá de la verdad de la afirmación.

Una cuarta propiedad, la sucintitud, no es necesaria para una ZKP pero es lo que hace prácticos muchos sistemas ZK de blockchain: la prueba es pequeña y rápida de verificar en relación con el cómputo que certifica. Los argumentos de conocimiento sucintos no interactivos (SNARKs) y las variantes transparentes (STARKs) son las familias comunes que encontrarás.

  • Completitud: un testigo válido siempre es aceptado.
  • Solidez: un testigo inválido es rechazado con probabilidad abrumadora.
  • Conocimiento cero: la transcripción es simulable sin el testigo.
  • Sucintitud (opcional): prueba corta, verificación barata.

Pruebas ZK interactivas versus no interactivas

En una prueba interactiva, el probador y el verificador intercambian múltiples mensajes. El verificador envía desafíos aleatorios y el probador responde de una manera que solo alguien con el testigo podría. Los ejemplos de la cueva de Alí Babá y el amigo daltónico ilustran esto: la repetición reduce la probabilidad de que un probador tramposo acierte.

En una prueba no interactiva, el probador produce una única prueba que cualquiera puede verificar sin más comunicación. La heurística de Fiat-Shamir convierte muchas pruebas interactivas en no interactivas reemplazando el desafío aleatorio del verificador por un hash de la afirmación y el compromiso. Esta es la forma utilizada en blockchains, porque un contrato inteligente no puede ejecutar un ida y vuelta en vivo con un probador.

Para la verificación en cadena, el verificador suele ser un contrato precompilado o un contrato verificador que comprueba una prueba basada en emparejamiento o hash. La prueba se envía como calldata y el contrato devuelve verdadero o falso. Eso significa que tu flujo de verificación depende de que el endpoint RPC de la cadena devuelva un estado y registros consistentes.

Requisitos previos y supuestos para el recorrido

Los ejemplos siguientes asumen que tienes Node.js 18 o posterior, Python 3.10 o posterior, y acceso a un endpoint RPC compatible con EVM. Reemplaza RPC_URL con tu propio endpoint; no codifiques endpoints públicos en producción. Si necesitas un endpoint gestionado, compara opciones a través del servicio RPC y revisa los precios de RPC antes de comprometerte con un proveedor.

El ejemplo de Schnorr es una implementación didáctica, no criptografía de producción. Utiliza un campo primo pequeño para que puedas ejecutarlo localmente. Los sistemas reales utilizan curvas elípticas o esquemas de compromiso polinómico y bibliotecas auditadas. El objetivo es observar directamente el comportamiento de completitud, solidez y conocimiento cero.

pip install ecdsa requests
# or for the JS example
npm init -y && npm install ethers

Modelo mental: compromisos, desafíos y respuestas

La mayoría de los protocolos ZK siguen un patrón de tres movimientos llamado protocolo sigma. El probador primero envía un compromiso que oculta el testigo pero lo vincula a él. El verificador envía un desafío aleatorio. El probador envía una respuesta que satisface una ecuación que solo un poseedor del testigo puede satisfacer. El verificador comprueba la ecuación.

En el protocolo de Schnorr, la afirmación es que el probador conoce x tal que y = g^x mod p. El probador elige r aleatorio, envía t = g^r. El verificador envía el desafío c. El probador envía s = r + c*x mod (p-1). El verificador comprueba g^s = t * y^c mod p. Si el probador no conociera x, producir s que satisfaga la ecuación para un c aleatorio es tan difícil como resolver el logaritmo discreto.

El conocimiento cero se cumple porque el verificador podría simular la transcripción eligiendo primero s y c y calculando t = g^s * y^(-c). Dado que la transcripción simulada es indistinguible de una real, el verificador no aprende nada sobre x.

Verificación Schnorr ejecutable en Python

El siguiente script implementa una sola ronda del protocolo de Schnorr sobre un campo primo pequeño. Ejecútalo para ver una prueba válida aceptada y una prueba manipulada rechazada. Esto es un diagnóstico para entender las matemáticas, no una biblioteca de producción.

Resultado esperado: la primera verificación imprime True, y la prueba manipulada imprime False. Si ambas imprimen True, tu ecuación de desafío o respuesta es incorrecta. Si ambas imprimen False, tu aritmética modular o generador es incorrecto.

import random

p = 23          # small prime for demonstration only
g = 5           # generator of a subgroup
x = 6           # secret witness
y = pow(g, x, p)

r = random.randint(1, p - 2)
t = pow(g, r, p)
c = random.randint(1, p - 2)
s = (r + c * x) % (p - 1)

# Verifier checks g^s == t * y^c mod p
valid = pow(g, s, p) == (t * pow(y, c, p)) % p
print('valid proof accepted:', valid)

# Tamper with the response
tampered = (s + 1) % (p - 1)
print('tampered proof accepted:', pow(g, tampered, p) == (t * pow(y, c, p)) % p)

Verificar una prueba ZK a través de un endpoint RPC

Los verificadores ZK en cadena exponen una función de vista como verifyProof(bytes proof, uint256[] inputs) returns (bool). Puedes llamarla con eth_call sin gastar gas. El siguiente ejemplo utiliza ethers.js y una dirección de verificador de marcador de posición. Reemplaza VERIFIER_ADDRESS, PROOF_HEX e INPUTS con valores de tu sistema de prueba.

Resultado esperado: la llamada devuelve true para una prueba válida y false o un revert para una inválida. Si la llamada hace revert, comprueba el ABI, la longitud del array de entrada y si el verificador espera una codificación de prueba diferente.

const { ethers } = require('ethers');

const provider = new ethers.JsonRpcProvider('RPC_URL');
const abi = ['function verifyProof(bytes proof, uint256[] inputs) view returns (bool)'];
const verifier = new ethers.Contract('VERIFIER_ADDRESS', abi, provider);

async function main() {
  const ok = await verifier.verifyProof('PROOF_HEX', ['INPUT_1', 'INPUT_2']);
  console.log('proof valid:', ok);
}

main().catch(console.error);

Procedimiento de tabla de resultados para comparar el comportamiento del verificador

Cuando pruebes múltiples codificaciones de prueba o múltiples endpoints RPC, registra los resultados en una tabla para poder comparar sin adivinar. No rellenes números que no hayas medido. Utiliza las siguientes columnas y ejecuta cada fila al menos tres veces para detectar comportamientos intermitentes del endpoint.

Caso de pruebaCodificación de pruebaEndpointResultado de eth_callLatencia (ms)Motivo del revert
Prueba válidacomprimidaRPC_URL_A
Prueba válidasin comprimirRPC_URL_A
Prueba manipuladacomprimidaRPC_URL_A
Prueba válidacomprimidaRPC_URL_B

La tabla es una plantilla de medición, no un conjunto de resultados publicados. Tu latencia y motivos de revert dependerán de tu endpoint, cadena y contrato verificador. Si operas tu propio nodo, consulta la guía de nodo dedicado para aislamiento y planificación de recursos.

Solución de problemas comunes de verificación ZK

La mayoría de los fallos de verificación se engloban en un pequeño número de categorías. Revísalos en orden antes de asumir que la criptografía es incorrecta.

Desajuste de codificación. Las pruebas SNARK a menudo se serializan como dos puntos de emparejamiento de 32 bytes más dos escalares. Si tu verificador espera un orden o endianness diferente, las pruebas válidas hacen revert. Compara el formato de salida de tu probador con la documentación ABI del verificador.

Desajuste de entrada pública. El verificador comprueba que la prueba se compromete a las mismas entradas públicas que pasas. Si el orden del array de entrada difiere del orden de señales del circuito, la verificación falla aunque la prueba sea válida. Estado obsoleto. Si la prueba hace referencia a una altura de bloque o raíz de Merkle, verifica contra el mismo bloque. Utiliza eth_call con una etiqueta de bloque explícita cuando la reproducibilidad importe.

Inconsistencia del endpoint. Un nodo RPC retrasado puede devolver un estado de verificador más antiguo o fallar al decodificar registros. Compara resultados entre endpoints y revisa la configuración de red de la cadena antes de reportar un error.

  • Comprueba el orden de bytes de la prueba y la codificación de elementos del campo.
  • Confirma que el orden de las entradas públicas coincide con el circuito.
  • Fija la etiqueta de bloque para una verificación reproducible.
  • Compara al menos dos endpoints RPC antes de concluir que una prueba es inválida.

Limitaciones y compensaciones de las pruebas ZK

Las pruebas de conocimiento cero son potentes pero no gratuitas. Probar suele ser mucho más costoso que verificar, por lo que los sistemas ZK trasladan el coste del verificador al probador. Para uso en blockchain, eso significa infraestructura de prueba fuera de la cadena y contratos de verificación en la cadena.

Los supuestos de confianza varían según el esquema. Los SNARKs a menudo requieren una ceremonia de configuración confiable; los STARKs lo evitan pero producen pruebas más grandes. Las configuraciones transparentes reducen el riesgo de la ceremonia pero aumentan el tamaño de la prueba y el gas de verificación. Las pruebas recursivas pueden comprimir muchas afirmaciones en una, pero añaden complejidad al circuito y dificultad de depuración.

Finalmente, conocimiento cero no significa anónimo por defecto. Una prueba ZK puede ocultar el testigo mientras sigue vinculada a una identidad o dirección pública. La privacidad depende de lo que revelen la afirmación y las entradas públicas, no solo del sistema de prueba.

Próximos pasos: de la comprensión a la integración

Una vez que puedas verificar una prueba localmente y mediante eth_call, el siguiente paso es integrar la prueba en tu aplicación. Comienza con un circuito pequeño, genera una prueba y verifícala contra un nodo local antes de pasar a un endpoint gestionado. Para la selección de endpoints, utiliza el Asistente RPC para adaptarte a las necesidades de cadena y latencia de tu verificador.

Si estás evaluando infraestructura para un rollup ZK o una aplicación de privacidad, revisa los precios de RPC y el soporte de redes para confirmar la cobertura de cadena y métodos que necesitas. Para equipos que ejecutan su propia infraestructura de verificador, los nodos dedicados proporcionan aislamiento de los endpoints públicos compartidos.

Una ruta de aprendizaje razonable es: implementar Schnorr localmente, verificar una prueba SNARK con un verificador de prueba, y luego medir la latencia de verificación entre endpoints usando la tabla de resultados anterior. Ten en cuenta las tres propiedades en cada paso, porque una prueba que es rápida pero no sólida es peor que no tener prueba alguna.

Nunca te preocupes por la infraestructura nuevamente

OnFinality elimina la carga pesada de DevOps para que puedas construir de forma más inteligente y rápida.

Comenzar