Ir al contenido

Manejo de Errores

Achronyme proporciona mensajes de error detallados en todos los modos de ejecución. Los errores incluyen información de ubicación en el código fuente cuando está disponible.

Al ejecutar con ach run, la VM reporta errores con números de línea:

[line 5] in main: DivisionByZero
ErrorCausa
DivisionByZeroDivisión o módulo por cero
IntegerOverflowDesbordamiento aritmético i60 (sin promoción silenciosa)
TypeMismatchTipos incompatibles en operación (ej., Int + Field)
ArityMismatchNúmero incorrecto de argumentos para una función
AssertionFailedassert(expr) evaluó a falso
OutOfBoundsÍndice de array fuera de rango
StackOverflowLa pila de llamadas excedió 65,536 entradas (probable recursión infinita)
StackUnderflowError interno — pop de pila vacía
InvalidOpcodeBytecode corrupto — instrucción desconocida
FunctionNotFoundReferencia a closure o función inválida
ProveBlockFailedError durante ejecución de prove {}
ProveHandlerNotConfiguredprove {} usado sin --ptau
SystemErrorCorrupción del estado interno de la VM

Achronyme usa enteros con signo de 60 bits (rango: -2^59 a 2^59 - 1). El desbordamiento siempre es un error:

let big = 576460752303423487 // 2^59 - 1 (máximo i60)
let overflow = big + 1 // ERROR: IntegerOverflow

Para trabajar con valores más grandes, usa literales de campo 0p para elementos del campo BN254 (ej., 0p42, 0pxFF).

Los valores enteros y de campo no pueden mezclarse directamente:

let x = 42
let y = 0p10
let z = x + y // ERROR: TypeMismatch

Usa literales 0p para conversión explícita: let z = 0p42 + y.

Los errores de sintaxis incluyen información de línea y columna:

parse error at line 3, col 10: expected expression

Al compilar circuitos con ach circuit, la fase de bajada a IR reporta errores con rangos de código fuente:

ErrorCausa
UndeclaredVariableVariable usada sin declaración public/witness
UnsupportedOperationOperación no disponible en modo circuito (ej., print)
TypeNotConstrainableTipo no representable en campo usado en circuito (cadena, mapa, etc.)
UnboundedLoopBucle sin límites fijos (los circuitos requieren desenrollado estático)
WrongArgumentCountFunción integrada llamada con aridad incorrecta
DuplicateInputMisma variable declarada dos veces
IndexOutOfBoundsAcceso a array más allá de su longitud
ArrayLengthMismatchTamaño de array no coincide con la anotación de tipo
RecursiveFunctionLlamada recursiva detectada (no permitida en circuitos)
TypeMismatchTipo de expresión no coincide con la anotación
AnnotationMismatchTipo declarado conflicta con el tipo inferido

Algunos errores incluyen orientación amigable para el usuario:

// Usando una cadena en un circuito:
"cannot be used in circuits (circuits operate on field elements only)"
// Usando un mapa en un circuito:
"cannot be used in circuits (use arrays instead)"
// Usando un decimal:
"field arithmetic is integer-only — use whole numbers"

Errores durante la generación de restricciones:

R1CS compilation error: [3:5] undeclared variable 'x'

El prefijo [línea:col] mapea a la ubicación en el código fuente cuando está disponible.

Al usar compile_ir_with_witness(), el evaluador IR valida las entradas antes de la generación de restricciones:

ErrorCausa
MissingInputEntrada de circuito requerida no proporcionada
DivisionByZeroDivisión por cero con valores concretos
AssertionFailedassert(expr) falla con las entradas proporcionadas
AssertEqFailedassert_eq(a, b) falla — los valores no coinciden
RangeCheckFailedEl valor no cabe en el ancho de bits declarado
NonBooleanMuxConditionLa condición de mux no es 0 ni 1
UndefinedVarError interno — variable SSA no calculada

Estos errores incluyen los valores concretos que causaron el fallo, facilitando la depuración:

assert_eq failed: x (= 42) != y (= 43)

Después de la compilación del circuito, el pase de análisis de contaminación verifica posibles problemas de solidez:

witness input 'secret' is under-constrained (not in any assert_eq)

Una entrada declarada no se usa en ninguna restricción. Esto significa que un probador malicioso podría asignarle cualquier valor sin afectar la prueba. Esto casi siempre es un error.

public input 'unused_var' is unused

Una entrada declarada nunca se referencia en el cuerpo del circuito. Elimina la declaración o usa la variable.

Los errores dentro de bloques prove {} se categorizan por fase del pipeline:

FaseError
Bajada a IRParseo o conversión AST→IR falló
CompilaciónGeneración de restricciones falló
VerificaciónEl testigo generado no satisface las restricciones
Generación de pruebaLa prueba Groth16/PlonK falló

Ejemplo:

prove block error: IR lowering: undeclared variable 'x'

La mayoría de los fallos de circuito provienen de valores de entrada incorrectos. La bandera --inputs requiere precisión exacta a nivel de campo:

Ventana de terminal
ach circuit my_circuit.ach --inputs "a=42,b=7"

Si un circuito falla después de la optimización, intenta ejecutar sin ella:

Ventana de terminal
ach circuit my_circuit.ach --no-optimize --inputs "a=42,b=7"

Siempre revisa la salida del análisis de contaminación. Una advertencia UnderConstrained frecuentemente indica una restricción faltante que podría permitir a un probador malicioso falsificar pruebas.

En modo VM, usa print() para inspeccionar valores:

let h = poseidon(1, 2)
print("hash:", h)

Después de compilar un circuito, verifica el testigo con snarkjs:

Ventana de terminal
snarkjs r1cs info circuit.r1cs # verificar conteo de restricciones
snarkjs wtns check circuit.r1cs witness.wtns # verificar testigo

Si sospechas errores relacionados con el GC:

Ventana de terminal
ach run program.ach --stress-gc

Esto activa la recolección de basura en cada asignación, exponiendo problemas de enraizamiento.