Introducing Achronyme — a language for zero-knowledge proofs. Read the announcement

Field Elements

BN254 scalar field arithmetic.

A field element is a number in the BN254 scalar field — integers modulo the prime:

p = 21888242871839275222246405745257275088548364400416034343698204186575808495617

All arithmetic on field elements is modular: addition, subtraction, and multiplication wrap around at p, and division computes the modular inverse.

Int vs Field

IntField
Range-2^59 to 2^59-10 to p-1
OverflowRuntime errorWraps modulo p
Negation-xp - x
DivisionTruncating (7 / 2 = 3)Modular inverse (1/2 = (p+1)/2)
StorageInline (60-bit tagged)Heap-allocated (256-bit Montgomery)

Int and Field are distinct types. Mixing them in arithmetic is a runtime error:

0p3 + 5       // Error: Cannot mix Int and Field
0p3 + 0p5     // OK: 0p8

Creating Field Elements

Use the 0p prefix to create field elements. It works like 0x for hex:

let a = 0p42         // decimal field literal
let b = 0pxFF        // hex field literal (0px prefix)
let c = 0pb1010      // binary field literal (0pb prefix)
let d = 0p12345      // large decimal

Arithmetic

Field elements support +, -, *, /, ^, and ==:

let a = 0p10
let b = 0p3

let sum  = a + b        // 0p13
let diff = a - b        // 0p7
let prod = a * b        // 0p30
let quot = a / b        // modular inverse of 3, times 10
let pow  = a ^ 5        // 10^5 mod p

// Negative exponents compute modular inverse
let inv = a ^ -1        // same as 0p1 / a

In Circuits

In circuit mode (prove {} blocks and circuit CLI), all values are field elements implicitly. Integer variables captured by a prove {} block are converted to field elements automatically:

let x = 42
prove(x: Public) {
    // x is automatically converted to 0p42 inside the circuit
    assert_eq(x, 42)
}

This is the only place where Int→Field conversion happens implicitly. In regular VM execution, the conversion must always be explicit via 0p field literals.

Navigation