Presentamos Achronyme — un lenguaje para pruebas zero-knowledge. Lee el anuncio

Aritmética BigInt

Enteros sin signo de ancho fijo para operaciones criptográficas.

BigInt proporciona aritmética de enteros sin signo de 256 y 512 bits en la VM. A diferencia de los elementos de campo (que usan aritmética modular sobre BN254), los BigInts usan aritmética no modular con errores explícitos de desbordamiento. Esto los hace ideales para operaciones donde necesitas semántica de enteros exacta a anchos criptográficos.

Crear BigInts

Hay tres formas de crear valores BigInt:

Sintaxis literal

Usa el prefijo 0i seguido del ancho (256 o 512) y la base (x para hex, d para decimal, b para binario):

let a = 0i256xFF           // 256 bits, hex
let b = 0i256d255          // 256 bits, decimal
let c = 0i256b11111111     // 256 bits, binario
let d = 0i512x1234ABCD     // 512 bits, hex

Las tres representaciones de 255 son iguales:

assert(0i256xFF == 0i256d255)
assert(0i256d255 == 0i256b11111111)

Funciones constructoras

bigint256() y bigint512() construyen desde enteros o cadenas:

let a = bigint256(42)          // desde entero
let b = bigint256("0xFF")     // desde cadena hexadecimal
let c = bigint256("12345")    // desde cadena decimal
let d = bigint512(0)           // 512 bits cero

Verificación de tipo

Usa typeof() para inspeccionar valores BigInt:

let x = 0i256d42
print(typeof(x))   // "BigInt256"

let y = 0i512d42
print(typeof(y))   // "BigInt512"

Aritmética

Los operadores estándar funcionan entre BigInts del mismo ancho:

let a = 0i256d100
let b = 0i256d200

print(a + b)   // BigInt256(0x12c)  (300)
print(b - a)   // BigInt256(0x64)   (100)
print(a * b)   // BigInt256(0x4e20) (20000)
print(b / a)   // BigInt256(0x2)    (2)
print(b % a)   // BigInt256(0x0)    (0)

La exponenciación usa ^ con un exponente entero:

let base = 0i256d2
let result = base ^ 128
print(result)  // 2^128 como entero de 256 bits

Desbordamiento y Subdesbordamiento

A diferencia de los elementos de campo, la aritmética BigInt no se envuelve. Las operaciones que exceden el rango producen errores en tiempo de ejecución:

// Esto generará error: desbordamiento BigInt
let max = bit_not(bigint256(0))  // todos los bits activados = 2^256 - 1
let boom = max + bigint256(1)    // ERROR: BigIntOverflow
// Esto generará error: subdesbordamiento BigInt
let zero = bigint256(0)
let boom = zero - bigint256(1)   // ERROR: BigIntUnderflow

Esto hace los errores visibles inmediatamente en lugar de producir resultados silenciosamente incorrectos.

Seguridad de Tipos

BigInt aplica límites estrictos de tipo. No puedes mezclar BigInt con Int, Field, ni con un BigInt de diferente ancho:

// Todos estos son errores en tiempo de ejecución:
// bigint256(1) + 1           -- BigInt + Int
// bigint256(1) + 0p1         -- BigInt + Field
// bigint256(1) + bigint512(1) -- incompatibilidad de ancho

Esto previene aritmética accidental entre tipos incompatibles.

Operaciones a Nivel de Bits

BigInt soporta manipulación completa a nivel de bits a través de funciones nativas:

let a = 0i256xFF
let b = 0i256x0F

print(bit_and(a, b))   // 0x0F
print(bit_or(a, b))    // 0xFF
print(bit_xor(a, b))   // 0xF0
print(bit_not(b))      // todos los bits invertidos

Desplazamientos

let one = bigint256(1)

// Desplazar a la izquierda: multiplicar por potencias de 2
let shifted = bit_shl(one, 128)   // 2^128

// Desplazar a la derecha: dividir por potencias de 2
let back = bit_shr(shifted, 128)  // de vuelta a 1
assert(back == one)

Los desplazamientos a la izquierda generan error si algún bit activado es desplazado fuera (protección contra desbordamiento). Los desplazamientos a la derecha descartan los bits desplazados.

Descomposición de Bits

Convierte entre BigInts y bits individuales con to_bits() y from_bits():

let val = bigint256(42)
let bits = to_bits(val)

// bits es una lista de 256 enteros (0 o 1), LSB primero
print(len(bits))   // 256
print(bits[0])     // 0  (bit menos significativo)
print(bits[1])     // 1
print(bits[2])     // 0
print(bits[3])     // 1
print(bits[4])     // 0
print(bits[5])     // 1
// 42 = 0b101010, LSB primero = [0, 1, 0, 1, 0, 1, 0, 0, ...]

// Reconstruir desde bits
let reconstructed = from_bits(bits, 256)
assert(reconstructed == val)

El segundo argumento de from_bits() es el ancho objetivo (256 o 512).

Ejemplo: Conteo de Bits

Contar el número de bits activados en un BigInt:

fn popcount(x) {
    let bits = to_bits(x)
    mut count = 0
    for b in bits {
        count = count + b
    }
    return count
}

assert(popcount(bigint256(0)) == 0)
assert(popcount(bigint256(1)) == 1)
assert(popcount(bigint256(255)) == 8)
assert(popcount(bigint256("0xFFFF")) == 16)

print("popcount(0xFF) =", popcount(bigint256(255)))  // 8

Ejemplo: Intercambio XOR

Intercambiar dos valores usando XOR sin variable temporal:

mut a = 0i256d42
mut b = 0i256d99

a = bit_xor(a, b)
b = bit_xor(b, a)
a = bit_xor(a, b)

assert(a == 0i256d99)
assert(b == 0i256d42)
print("Después del intercambio XOR: a =", a, "b =", b)

Ejemplo: Verificación de Potencia de Dos

Verificar si un BigInt es potencia de dos usando el truco de bits n & (n - 1) == 0:

fn is_power_of_two(n) {
    if n == bigint256(0) {
        return false
    }
    let prev = n - bigint256(1)
    return bit_and(n, prev) == bigint256(0)
}

assert(is_power_of_two(bigint256(1)) == true)
assert(is_power_of_two(bigint256(256)) == true)
assert(is_power_of_two(bit_shl(bigint256(1), 128)) == true)
assert(is_power_of_two(bigint256(3)) == false)
assert(is_power_of_two(bigint256(100)) == false)

print("2^128 es potencia de 2:", is_power_of_two(bit_shl(bigint256(1), 128)))

BigInt vs Field

BigIntField
AritméticaNo modular (errores de desbordamiento)Modular (se envuelve en primo BN254)
Anchos256 bits, 512 bits254 bits (campo escalar BN254)
Soporte de circuitosSolo VMVM y circuitos
Caso de usoAritmética entera exacta a anchos criptográficosValores de circuito ZK, hashing Poseidon
DivisiónDivisión entera (trunca)Inverso modular
NegaciónError (sin signo)Inverso aditivo en campo

Elige BigInt cuando necesites semántica de enteros exacta. Elige Field cuando necesites aritmética modular o compatibilidad con circuitos.

Navigation