R1CS
Un Sistema de Restricciones de Rango 1 (R1CS) es el backend predeterminado en Achronyme. Representa la computación como un conjunto de ecuaciones que un probador debe satisfacer, habilitando pruebas de conocimiento cero Groth16.
La Idea Central
Sección titulada «La Idea Central»Cada restricción R1CS tiene la forma:
A * B = Cdonde A, B y C son combinaciones lineales de variables del circuito (cables). Una combinación lineal es una suma ponderada como 3x + 5y + 1.
La restricción clave es rango 1: cada restricción permite exactamente una multiplicación. Esto es lo que hace R1CS “suficientemente simple” para sistemas de pruebas eficientes, pero requiere que el compilador descomponga expresiones complejas en pasos de multiplicación única.
Cables y Disposición
Sección titulada «Cables y Disposición»Un circuito tiene tres tipos de cables:
| Cable | Índice | Descripción |
|---|---|---|
| ONE | 0 | Cable constante, siempre 1. Usado para codificar constantes en combinaciones lineales. |
| Entradas públicas | 1..N | Valores que el verificador ve. Declarados con public. |
| Testigo | N+1.. | Entradas privadas + valores intermedios. Declarados con witness o asignados por el compilador. |
Esta disposición es compatible con snarkjs — los archivos .r1cs y .wtns que Achronyme exporta funcionan directamente con las herramientas de snarkjs.
De Achronyme a Restricciones
Sección titulada «De Achronyme a Restricciones»El compilador traduce cada operación en combinaciones lineales y restricciones:
Operaciones gratis (0 restricciones)
Sección titulada «Operaciones gratis (0 restricciones)»La suma, resta, negación y multiplicación por una constante son todas operaciones lineales — solo combinan cables existentes sin necesitar nuevas restricciones:
// Estas son gratis:let sum = a + b // CL: a + blet diff = a - b // CL: a - blet scaled = a * 3 // CL: 3*alet neg = -a // CL: (-1)*aMultiplicación (1 restricción)
Sección titulada «Multiplicación (1 restricción)»Multiplicar dos variables requiere una restricción porque es la única operación no lineal:
let product = a * b// Emite: A=a, B=b, C=product → a * b = productDivisión (2 restricciones)
Sección titulada «División (2 restricciones)»La división por una variable requiere calcular el inverso modular:
let quotient = a / b// Restricción 1: b * b_inv = 1 (calcula inverso)// Restricción 2: a * b_inv = quotientLa división por una constante es gratis (multiplicar por el inverso de la constante).
Igualdad (1 restricción)
Sección titulada «Igualdad (1 restricción)»assert_eq(x, y)// Emite: x * 1 = yCombinaciones Lineales
Sección titulada «Combinaciones Lineales»Una LinearCombination se almacena como pares dispersos (variable, coeficiente):
3x + 5y + 7 = [(x, 3), (y, 5), (ONE, 7)]El sistema simplifica automáticamente: x - x se convierte en la CL vacía (cero), y 3x + 5x se convierte en 8x. Esta deduplicación previene la inflación de restricciones.
Cuando una combinación lineal necesita convertirse en un cable concreto (por ejemplo, como entrada a una multiplicación), el compilador la materializa:
- Si la CL ya es una sola variable (como solo
x), no se necesita restricción - De lo contrario, se asigna un cable testigo nuevo y se agrega una restricción de igualdad (1 restricción)
Ejemplo: Ecuación Cuadrática
Sección titulada «Ejemplo: Ecuación Cuadrática»Considera probar conocimiento de x tal que x^2 + x + 5 = 35:
circuit quadratic(out: Public, x: Witness) { let x_sq = x * x assert_eq(x_sq + x + 5, out)}Esto produce 2 restricciones:
| # | A | B | C | Propósito |
|---|---|---|---|---|
| 1 | x | x | x_sq | x * x = x_sq |
| 2 | x_sq + x + 5*ONE | 1 | out | x_sq + x + 5 = out |
Con testigo x = 5, out = 35, ambas restricciones se satisfacen: 5*5 = 25 y 25 + 5 + 5 = 35.
Verificación Booleana
Sección titulada «Verificación Booleana»Varias operaciones necesitan verificar que un valor es booleano (0 o 1). El gadget estándar:
b * (1 - b) = 0Esta restricción única fuerza a b a ser 0 o 1 — las únicas dos soluciones.
El pase de optimización bool_prop rastrea qué variables son probablemente booleanas (salidas de comparaciones, RangeCheck(x, 1), etc.) y omite la verificación redundante, ahorrando restricciones.
Gadget IsZero
Sección titulada «Gadget IsZero»Las comparaciones de igualdad y desigualdad usan el gadget IsZero. Dado un valor d, produce 1 si d = 0, y 0 en caso contrario:
d * inv = 1 - resultd * result = 0- Si
d = 0:result = 1,invpuede ser cualquier cosa (la segunda restricción fuerza aresultoda ser 0) - Si
d != 0:result = 0,inv = 1/d
Costo: 2 restricciones.
Comparaciones de Orden
Sección titulada «Comparaciones de Orden»<, <=, >, >= son las operaciones más costosas. El enfoque:
- Asegurar que ambos operandos estén acotados (verificación de rango de 252 bits si no están probados)
- Calcular
diff = b - a + 2^bits - 1(desplazamiento para mantener el resultado positivo) - Descomponer
diffenbits + 1bits con verificación booleana - El bit superior indica el resultado de la comparación
Costo: ~760 restricciones sin cotas previas de rango. Con range_check, el compilador reutiliza cotas probadas, reduciendo a O(bits).
Referencia de Costos de Restricciones
Sección titulada «Referencia de Costos de Restricciones»| Operación | Restricciones | Notas |
|---|---|---|
+, -, negación | 0 | Combinación lineal |
* constante | 0 | Multiplicación escalar |
* variable | 1 | Una restricción R1CS |
/ constante | 0 | Multiplicar por inverso |
/ variable | 2 | Inverso + multiplicación |
assert_eq | 1 | Forzar igualdad |
assert | 2 | Verificación booleana + forzar = 1 |
==, != | 2 | Gadget IsZero |
<, <=, >, >= | ~760 | 2x252 rango + descomposición de 253 bits |
&&, || | 3 | 2 verificaciones booleanas + 1 multiplicación |
! | 1 | Verificación booleana (0 si probado) |
mux (if/else) | 2 | Verificación booleana + selección |
range_check(x, n) | n + 1 | n bits booleanos + 1 igualdad de suma |
poseidon(l, r) | 361 | 360 permutación + 1 capacidad |
Exportación Binaria
Sección titulada «Exportación Binaria»Achronyme exporta archivos .r1cs y .wtns en el formato binario iden3, compatible con snarkjs:
.r1cs(v1): 3 secciones — encabezado, restricciones, mapeo cable-a-etiqueta.wtns(v2): 2 secciones — encabezado, valores del testigo (32 bytes por elemento de campo)
Ambos usan codificación little-endian con el primo del campo escalar BN254 incrustado en el encabezado.
Lectura Adicional
Sección titulada «Lectura Adicional»- Operadores y Costos — costos detallados de restricciones para todas las operaciones de circuito
- Funciones Integradas — costos de restricciones de funciones integradas
- Generación de Pruebas — usando R1CS para pruebas Groth16